The `@forward` in SASS
This article explains about @forward in SASS.
We will explain @forward in an easy-to-understand way, including practical examples.
YouTube Video
The @forward in SASS
What is @forward?
In SASS’s module system, you use @use and @forward instead of @import. @forward is an important feature for keeping your architecture clean. It is a directive used to 'expose' variables, mixins, and functions defined in other files. Rather than using it by itself, it acts as an entry point specifying, 'Use this module from here.'.
1@forward "variables";- This code means 'making the contents of
variables.scssavailable for use from other files.'.
Difference between @use and @forward
@use and @forward are both syntax for handling modules, but their purposes are clearly different. @use is a directive for using items within the file, and @forward is a directive for making items available to other files.
1// @use: import the module for use in this file
2@use "variables";
3
4// @forward: re-export the module for other files to consume
5@forward "variables";@userepresents the dependencies necessary for the current file's implementation, whereas@forwardmakes the file function as a public API entry point. Understanding this difference will help you decide where to use@forward.
Why is @forward necessary?
As you add more Sass files, you may need to write a lot of @use statements. By using @forward, you can centralize everything into a single entry file.
1styles/
2├─ foundation/
3│ ├─ _variables.scss
4│ ├─ _mixins.scss
5│ └─ _index.scss
6└─ main.scss- In this structure,
_index.scssserves as the 'public API.'.
Basic usage of @forward
Let's look at the basic usage of @forward.
1// _variables.scss
2// Color definitions used across the project
3
4$primary-color: #006ab1;
5$secondary-color: #e0f0ff;
6
7// Internal use only (will be hidden via @forward hide)
8$debug-color: magenta;- Instead of directly
@use-ing this variable, you group them with@forward.
1// _index.scss
2@forward "variables";- At this point,
_index.scsscontains nothing; it is simply a relay file.
Using modules that have been @forwarded
Instead of directly @use-ing individual files, you only @use the index file that has grouped the @forwards on the consumer side. This allows you to use it as a stable interface without having to be aware of the internal structure.
1// main.scss
2// Import the public API of the foundation layer
3@use "foundation";
4
5.button {
6 background-color: foundation.$primary-color;
7}- With this design, even if the definition locations of variables or mixins change, you can replace the internal structure without having to modify any code on the consumer side.
Combining multiple modules with @forward
In actual development, it is common to split variables, mixins, and functions according to their roles. @forward can be written multiple times, allowing you to bundle separated modules into a single public API.
Below, we provide examples of mixins and functions and demonstrate a design that exposes them to the outside as a single interface.
1// _mixins.scss
2// Reusable mixins for layout and components
3
4// Reset default button styles
5@mixin button-reset {
6 appearance: none;
7 background: none;
8 border: none;
9 padding: 0;
10 margin: 0;
11 font: inherit;
12 color: inherit;
13}
14
15// Clearfix utility
16@mixin clearfix {
17 &::after {
18 content: "";
19 display: table;
20 clear: both;
21 }
22}
23
24// Internal mixin (not intended to be part of the public API)
25@mixin debug-outline {
26 outline: 2px dashed red;
27} 1// _functions.scss
2// Utility functions for consistent styling
3
4@use "sass:math";
5
6// Convert px to rem based on a 16px root size
7@function rem($px) {
8 @return math.div($px, 16) * 1rem;
9}
10
11// Clamp a value between a minimum and maximum
12@function clamp-value($value, $min, $max) {
13 @return math.max($min, math.min($value, $max));
14}1// _index.scss
2// Re-export variables, mixins, and functions as a single public API
3@forward "variables";
4@forward "mixins";
5@forward "functions";- By exposing only this
indexfile to the outside, you can hide the internal structure and provide a user-friendly interface for consumers.
Preventing naming conflicts (as)
If the same variable or mixin names are defined in multiple modules, you can specify as to @forward to add a prefix when exposing them to prevent name conflicts.
1// Add a prefix when re-exporting to avoid name collisions
2@forward "variables" as var-*;With this code, $primary-color in variables will be exposed with the following name:.
1// foundation.$var-primary-color- This method is a way to clearly define design rules and safely scale, and it's an essential technique, especially in large-scale projects or shared libraries.
Hiding unnecessary members (hide)
Modules may contain variables or mixins intended solely for internal implementation. By using hide, you can exclude them when re-exposing and prevent them from being accessed externally.
1// Re-export everything except internal debug variables
2@forward "variables" hide $debug-color;With this configuration, $debug-color is valid only inside the module, which helps prevent accidental use by consumers.
Specifying which members to expose (show)
If you want to expose only certain mixins or functions, use show. By limiting what is exposed, you can clarify the purpose of the module and its design intent.
1// Explicitly expose only selected mixins as the public API
2@forward "mixins" show button-reset, clearfix;- By using
showin this way, it becomes clear at a glance which APIs are officially available for use.
@forward cannot be used by itself
An important point is that variables @forwarded cannot be used within that file.
1@forward "variables";
2
3.test {
4 color: $primary-color; // Error
5}@forwardis only for 're-exposing,' and 'using' is the role of@use.
An example of proper role separation
In module design for Sass, it is ideal to clearly separate the public-facing layer (API) and the implementation layer. @forward defines the public API, and @use consumes it from the implementation side.
1// _index.scss (public API)
2@forward "variables";
3@forward "mixins";1// _component.scss
2// Consume the public API of the foundation layer
3@use "foundation";
4
5.card {
6 color: foundation.$primary-color;
7}- With this structure, it becomes clear which parts are public interfaces and which parts are internal implementations, leading to better design transparency.
The definitive difference from @import
@import expands all imported definitions into the global scope. On the other hand, @use and @forward explicitly expose items and access them through namespaces.
1// @import (deprecated)
2// Everything is injected into the global scope
3$color: red;
4
5.button-import {
6 color: $color;
7}
8
9// @use + @forward (recommended)
10// Access values explicitly through a namespace
11@use "foundation";
12
13.button-use {
14 color: foundation.$primary-color;
15}- Because of this difference, you can greatly improve maintainability and safety by preventing unintended overwrites and dependency confusion.
Summary
@forward is an important feature that supports maintainable design. By being mindful of 'what to expose and what to hide as an internal implementation,' your style structure becomes safer and more readable. By properly using @use and @forward, you can clarify dependencies and achieve a design that is robust against change.
You can follow along with the above article using Visual Studio Code on our YouTube channel. Please also check out the YouTube channel.