Sass @forward Rule

Beginner
⏱️ 13 min read
📚 Updated: Jul 2026
🎯 5 Examples
with !default · 1.24+

What You’ll Learn

The Sass @forward rule re-exports another module’s public API through your stylesheet. Library authors split code across files while users load one entrypoint with @use. This page covers prefixes, show/hide, configuration, and five compiled examples.

01

Re-export

@forward "url"

02

Prefix

as list-*

03

Filter

show / hide

04

Configure

with (!default)

05

Pair

@use too

06

Practice

5 examples

What Is @forward?

Official docs: the @forward rule loads a Sass stylesheet and makes its mixins, functions, and variables available when your stylesheet is loaded with @use. It organizes libraries across many files while letting users load a single entrypoint.

  • Written @forward "url"—loads like @use, but for re-export.
  • Public members look as if they were defined in your module.
  • Those members are not available inside the forwarding file unless you also @use it.
  • Sass still loads the module only once if you write both @forward and @use.
  • Forwarded CSS is included in the output (same as @use for CSS).
💡
Beginner tip

Think of @forward as a receptionist: it points visitors to the right tools from back-office files. Visitors still enter through your front door with @use "bootstrap".

📝 Syntax

styles.scss
@forward "url";
@forward "url" as prefix-*;
@forward "url" hide member, $variable;
@forward "url" show member, $variable;
@forward "url" with (
  $variable: value !default
);

Parts of the rule

PartMeaning
"url"Module to load and re-export
as prefix-*Add a prefix to every forwarded member name
hide …Forward everything except the listed members
show …Forward only the listed members
with (…)Configure upstream !default variables (may use !default)

📦 Basic Re-Export

Official pattern: a library file forwards internal modules; the app loads only the library.

styles.scss
// src/_list.scss
@mixin list-reset {
  margin: 0;
  padding: 0;
  list-style: none;
}

// bootstrap.scss
@forward "src/list";

// styles.scss
@use "bootstrap";

li {
  @include bootstrap.list-reset;
}
💡
Order tip

If the same file both @forwards and @uses a module, write @forward first so user configuration applies before your local @use.

🏷️ Adding a Prefix

Official docs: module members are usually used with a namespace, so short names are readable inside a file—but outside they may need context. @forward "…" as list-* prefixes every forwarded mixin, function, and variable.

Defined asForwarded asUsed as
@mixin resetas list-*bootstrap.list-reset

🔒 Controlling Visibility

Official docs: use hide or show to control exactly which members get forwarded. List mixin/function names and variables (including $).

  • hide a, $b — forward everything except these.
  • show a, $b — forward only these.
  • Useful for keeping package-private helpers out of the public API.
styles.scss
// bootstrap.scss
@forward "src/list" hide list-reset, $horizontal-list-gap;

⚙️ Configuring Modules

Official docs: @forward can load a module with configuration (Dart Sass 1.24+). It mostly matches @use … with, with one addition: configuration values may use !default so downstream stylesheets can still override them.

styles.scss
// _opinionated.scss
@forward "library" with (
  $black: #222 !default,
  $border-radius: 0.1rem !default
);

// style.scss
@use "opinionated" with ($black: #333);

Here the opinionated package sets new defaults; the app still overrides $black to #333.

🔁 @forward vs @use

@use@forward
Who uses members?The current fileDownstream files that @use you
Members in this file?Yes (namespaced)No (unless you also @use)
Typical roleConsumer / app codeLibrary entrypoint
CSS from moduleIncluded onceIncluded once (same idea)

🛠 Compatibility

This is about Sass compilers, not browsers. Module rules resolve at compile time.

FeatureDart SassLibSass / Ruby Sass
@forwardYes (module system)No
@forward … with + !defaultYes (since 1.24.0)No

⚡ Quick Reference

GoalCode
Re-export a module@forward "src/list";
Add a name prefix@forward "src/list" as list-*;
Hide members@forward "src/list" hide list-reset, $gap;
Show only some@forward "src/list" show list-horizontal;
Set overridable defaults@forward "lib" with ($black: #222 !default);
Use it yourself too@forward "src/list"; @use "src/list";
Consume the entrypoint@use "bootstrap";

Examples Gallery

Multi-file samples show the source module, the forwarding entrypoint, and the consumer (as in the official docs). Open View Compiled CSS for verified output.

📚 Getting Started

Single entrypoint and prefixed member names.

Example 1 — Basic @forward

Users load bootstrap and get members from src/list.

styles.scss
// src/_list.scss
@mixin list-reset {
  margin: 0;
  padding: 0;
  list-style: none;
}

// bootstrap.scss
@forward "src/list";

// styles.scss
@use "bootstrap";

li {
  @include bootstrap.list-reset;
}

How It Works

list-reset is defined in a partial, forwarded by the entry file, then called through the bootstrap namespace.

Example 2 — Prefix With as list-*

Rename short internal members for a clearer public API.

styles.scss
// src/_list.scss
@mixin reset {
  margin: 0;
  padding: 0;
  list-style: none;
}

// bootstrap.scss
@forward "src/list" as list-*;

// styles.scss
@use "bootstrap";

li {
  @include bootstrap.list-reset;
}

How It Works

Internal name reset becomes public list-reset after the prefix—matches the official docs sample.

📈 Practical Patterns

Hide internals, configure defaults, and use members locally too.

Example 3 — hide Members

Forward list-horizontal while keeping helpers off the public API.

styles.scss
// src/_list.scss
$horizontal-list-gap: 2em;

@mixin list-reset {
  margin: 0;
  padding: 0;
  list-style: none;
}

@mixin list-horizontal {
  @include list-reset;

  li {
    display: inline-block;
    margin: {
      left: -2px;
      right: $horizontal-list-gap;
    }
  }
}

// bootstrap.scss
@forward "src/list" hide list-reset, $horizontal-list-gap;

// styles.scss
@use "bootstrap";

.nav {
  @include bootstrap.list-horizontal;
}

How It Works

Consumers can call list-horizontal, but not bootstrap.list-reset or bootstrap.$horizontal-list-gap. The mixin still uses those private pieces internally.

Example 4 — with and !default

An opinionated wrapper sets defaults; the app overrides one of them.

styles.scss
// _library.scss
$black: #000 !default;
$border-radius: 0.25rem !default;
$box-shadow: 0 0.5rem 1rem rgba($black, 0.15) !default;

code {
  border-radius: $border-radius;
  box-shadow: $box-shadow;
}

// _opinionated.scss
@forward "library" with (
  $black: #222 !default,
  $border-radius: 0.1rem !default
);

// style.scss
@use "opinionated" with ($black: #333);

How It Works

Radius keeps the opinionated default (0.1rem). Black becomes #333 from the consumer, so the shadow uses rgba(51, 51, 51, 0.15).

Example 5 — @forward + @use

Re-export for consumers and use the same module locally.

styles.scss
// src/_list.scss
@mixin list-reset {
  margin: 0;
  padding: 0;
  list-style: none;
}

// entry.scss — forward first, then use
@forward "src/list";
@use "src/list";

.local {
  @include list.list-reset;
}

// app.scss
@use "entry";

.remote {
  @include entry.list-reset;
}

How It Works

@forward alone would not let entry.scss call list-reset. Adding @use unlocks local access; the module still loads only once.

🚀 Real-World Use Cases

  • Library entrypoints — one @use "my-lib" for many partials.
  • Public API shaping — prefix or hide members before shipping a package.
  • Opinionated themes — forward a base library with new !default values.
  • Monorepo design systems — forward tokens, mixins, and components from index files.
  • Gradual modularization — keep a stable import path while splitting internals.

🧠 How Compilation Works

1

Author splits files

Define members in partials; @forward them from an entry file.

Library
2

Shape the public API

Apply prefixes, show/hide, and optional with defaults.

Entrypoint
3

App loads one module

Consumers write @use "bootstrap" and call namespaced members.

Consumer
4

CSS ships

Browsers only see finished rules like list-style: none.

⚠️ Common Pitfalls

  • Expecting local access@forward alone does not give you the members in that file.
  • @use before @forward — can block consumer configuration; forward first.
  • Forgetting $ in hide/show — variables need the dollar sign in the list.
  • Prefix confusionas list-* changes the member name, not only the namespace.
  • Old compilers — LibSass does not support @forward.

💡 Best Practices

✅ Do

  • Build a single public entry file with @forward
  • Write @forward before @use for the same module
  • Use hide/show to keep a clean API
  • Prefix short internal names when they leave the package
  • Use !default in with so apps can still theme

❌ Don’t

  • Force users to @use dozens of internal partials
  • Forward every private helper by accident
  • Assume @forward imports members into the current file
  • Rely on LibSass for module rules
  • Skip documenting your public forwarded API

Key Takeaways

Knowledge Unlocked

Five things to remember about Sass @forward

Re-export modules so users load one entrypoint with @use.

5
Core concepts
🏷️ 02

Prefix

as list-*

API
🔒 03

Filter

show / hide

Control
⚙️ 04

Config

with !default

1.24+
05

Local use

also @use

Pair

❓ Frequently Asked Questions

It loads a Sass stylesheet and makes that module’s public mixins, functions, and variables available to anyone who @use’s your stylesheet. Users can load one entrypoint instead of many files.
No. Official docs: those members aren’t available in your module unless you also write @use for the same module. Don’t worry—Sass still loads the module only once.
It adds a prefix to every forwarded member name. A mixin named reset becomes list-reset for downstream users (for example bootstrap.list-reset after @use "bootstrap").
They control which members are re-exported. hide lists members to keep private from consumers; show lists the only members to forward. Include $ for variable names.
Yes (Dart Sass 1.24+). It works like @use with (…), and configuration may use !default so downstream stylesheets can still override those defaults.
If you write both for the same module in one file, put @forward first. That way user configuration applies to the @forward before your @use loads the module.
Did you know?

Official Sass docs note that @forward includes a module’s CSS just like @use—and your forwarding file can even @extend selectors from that CSS without also writing @use.

Conclusion

@forward turns many partials into one friendly entrypoint. Prefix and filter the public API, configure overridable defaults when needed, and pair with @use whenever the forwarding file must call those members itself.

Continue with @import (legacy) or browse @use.

Next: Sass @import Rule

Learn the deprecated import rule so you can migrate legacy code to @use.

@import rule →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful