Sass @forward Rule

Beginner
11 min read
Updated: Nov 2026
5 examples
Compiled CSS

Definition and Usage

The Sass @forward rule is written @forward "url";. It loads a stylesheet and makes its public mixins, functions, and variables available when your stylesheet is loaded with @use.

That lets you organize a library across many files while users load a single entrypoint. Forwarded members are not available in the forwarding file itself — add @use for the same module if you need them locally (Sass still loads it once).

Official pattern.

Per the Sass docs: write @forward before @use for the same module so consumer with configuration applies to the forward first.

CSS is included.

@forward acts like @use for a module’s CSS — styles ship once, and the forwarding file can even @extend them.

Dart Sass only.

The module system (@use / @forward) is not available in LibSass or Ruby Sass. Prefer Dart Sass for new projects.

Syntax

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;
}

Pattern: partial defines members → entrypoint @forwards them → app @uses the entrypoint.

vs @use & Options

How @forward compares and what it can do:

FormMeaning
@forward "src/list";Re-export public members through this file
@forward "…" as list-*;Prefix every forwarded name (reset → list-reset)
hide / showFilter which members consumers can see
with ($x: … !default)Set overridable upstream defaults (Dart Sass 1.24+)
@use (same module)Also use members in this file; write @forward first

SCSS Examples

Multi-file samples show the source module, the forwarding entrypoint, and the consumer. Open View Compiled CSS for verified output.

Example 1 — Basic @forward

Users load bootstrap and get members from src/list.

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

  1. Partial defines list-reset.
  2. Entrypoint forwards the module publicly.
  3. App loads @use "bootstrap".
  4. Call through the namespace as bootstrap.list-reset.

Example 2 — Prefix With as list-*

Rename short internal members for a clearer public API.

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

  1. Internal name is the short reset.
  2. as list-* prefixes every forwarded member.
  3. Public name becomes list-reset.
  4. Consumers still use the entrypoint namespace (bootstrap.).

Example 3 — hide Members

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

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

  1. hide keeps listed members off the public surface.
  2. list-horizontal is still forwarded.
  3. Hidden pieces still work inside the mixin.
  4. show is the inverse — forward only the named members.

Example 4 — with and !default

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

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

  1. Library variables use !default.
  2. Opinionated forward changes defaults, still with !default.
  3. App overrides $black to #333.
  4. Radius stays at the opinionated 0.1rem.

Example 5 — @forward + @use

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

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

  1. @forward alone does not unlock local members.
  2. Add @use to call them in the entry file.
  3. Write forward first so config still works for consumers.
  4. Module loads once even with both rules.

Edge Cases & Pitfalls

Most @forward bugs are expecting local access, wrong rule order, or using old compilers.

local

Forward ≠ local import

@forward re-exports for downstream @use. To use members in the same file, add @use too.

order

Forward before use

If both appear for the same module, put @forward first so consumer with config applies correctly.

api

Hide internals on purpose

Use hide / show so package-private helpers never become part of the public surface.

libsass

Not in LibSass

Module rules require Dart Sass. Migrate off node-sass / LibSass before relying on @forward.

Sass Support

@forward is part of the Dart Sass module system. It is not a browser CSS feature — support means your Sass compiler understands it.

ImplementationStatus
Dart SassSupported (recommended)
@forward … with + !defaultDart Sass 1.24.0+
LibSass / node-sassNot supported
Ruby SassNot supported (end-of-life)
BrowsersN/A — only see compiled CSS

Prefer Dart Sass for new projects. SCSS and indented syntax both support @forward.

Key Takeaways

  • Entrypoint: @forward re-exports modules for a single @use.
  • Not local: add @use if this file needs the members too.
  • Shape the API with as prefix-*, show, and hide.
  • with (!default) lets wrappers set defaults apps can still override.

One line: @forward turns many partials into one friendly library entrypoint.

Compile Notes

@forward never reaches the browser. Conceptual flow:

flow.txt
1. Entrypoint @forward's one or more modules
2. Optional: prefix, show/hide, or with (!default) config
3. App @use's the entrypoint (and may configure it)
4. Members appear under the entrypoint namespace
5. Module CSS is included once in the compiled output

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. Those members aren’t available in your module unless you also write @use for the same module. 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.

Next: Sass @import Rule

Legacy loading — understand it, then prefer @use and @forward.

Sass @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.

8 people found this page helpful