Chapitre 10 : La directive @forward¶
Introduction¶
Dans ce chapitre, nous allons découvrir la directive @forward, un outil puissant pour créer des API de style propres et bien organisées. @forward permet de ré-exporter des modules Sass, offrant un contrôle précis sur ce qui est visible à l'extérieur d'un dossier. C'est la clé pour créer des bibliothèques de styles maintenables et modulaires.
10.1 Créer une API de style¶
Le concept¶
Une API de style est un ensemble de fichiers organisés qui exposent une interface claire et contrôlée. L'utilisateur de l'API n'a pas besoin de connaître l'organisation interne — il importe un seul fichier et accède à tout ce dont il a besoin.
Sans @forward¶
// Pour utiliser les styles d'un projet bien organisé, il faudrait écrire :
@use 'abstracts/colors' as c;
@use 'abstracts/variables' as v;
@use 'abstracts/mixins' as *;
@use 'abstracts/functions' as *;
@use 'components/buttons' as btn;
@use 'components/cards' as card;
@use 'components/forms' as form;
// → 7 lignes d'import, l'utilisateur doit connaître l'organisation interne
Avec @forward¶
// abstracts/_index.scss — Le point d'entrée de l'API
@forward 'colors';
@forward 'variables';
@forward 'mixins';
@forward 'functions';
// main.scss — L'utilisateur importe UN SEUL fichier
@use 'abstracts';
// → Accès à colors.$primary, variables.$spacing-md, etc.
// → Un seul import, propre et simple
10.2 Ré-exporter des modules¶
Syntaxe de base¶
// _index.scss (ou tout autre fichier "barrel")
@forward 'colors';
@forward 'variables';
@forward 'mixins';
@forward 'functions';
Fonctionnement interne¶
Lorsque vous utilisez @forward, le fichier qui contient la directive ré-exporte les membres des modules转发és. Cela signifie que les modules转发és sont accessibles via le fichier转发é.
// _colors.scss
$primary: #3498db;
$secondary: #2ecc71;
// _index.scss
@forward 'colors';
// main.scss
@use 'index';
// → index.$primary n'est PAS accessible directement
// → Les membres de colors sont accessibles via le namespace du module转发é
Différence entre @forward et @use¶
// @use : IMPORTE un module (le consomme)
@use 'colors';
// → colors.$primary accessible
// @forward : RÉ-EXPORTE un module (le rend disponible pour les importateurs)
@forward 'colors';
// → Les membres de colors sont disponibles via le fichier转发é
// → Mais le fichier转发é ne les consomme pas lui-même
10.3 @forward avec @use¶
Le pattern d'utilisation typique¶
// abstracts/_index.scss
// Ce fichier forward tous les modules de abstracts
@forward 'colors';
@forward 'variables';
@forward 'mixins';
@forward 'functions';
// main.scss
@use 'abstracts' as a;
.button {
background-color: a.colors.$primary; // Accès via le namespace du forward
padding: a.variables.$spacing-md;
border-radius: a.variables.$border-radius;
@include a.mixins.flex-center();
width: a.functions.to-rem(200px);
}
Avec un alias sur le forward¶
// abstracts/_index.scss
@forward 'colors';
@forward 'variables';
@forward 'mixins' as *; // Forward le mixin sans namespace
@forward 'functions' as *; // Forward les fonctions sans namespace
// main.scss
@use 'abstracts' as a;
@use 'abstracts/mixins' as *; // Double import possible
.button {
background-color: a.colors.$primary;
padding: a.variables.$spacing-md;
@include flex-center(); // Accès direct via as *
}
10.4 Cacher et montrer avec @forward¶
Le problème¶
Parfois, un module contient des éléments qui ne doivent pas être exposés à l'extérieur. Par exemple, des variables internes ou des mixins auxiliaires.
La solution : hide¶
La syntaxe @forward 'module' hide (membres) permet de cacher certains membres du module转发é :
// _colors.scss
$primary: #3498db; // Public
$secondary: #2ecc71; // Public
$danger: #e74c3c; // Public
$internal-gray: #666; // Interne (ne doit pas être exposé)
$debug-color: red; // Debug (ne doit pas être exposé)
@mixin public-mixin() { ... } // Public
@mixin internal-helper() { ... } // Interne
// _index.scss
@forward 'colors' hide ($internal-gray, $debug-color, internal-helper);
// Seuls $primary, $secondary, $danger et public-mixin sont exposés
// main.scss
@use 'abstracts' as a;
.element {
color: a.colors.$primary; // ✅ OK
color: a.colors.$internal-gray; // ❌ Erreur ! Caché
}
Cacher avec un pattern¶
// Cacher toutes les variables sauf celles listées
@forward 'colors' hide ($primary); // Cache uniquement $primary
// Cacher un seul mixin
@forward 'mixins' hide (internal-helper);
La solution : show¶
La syntaxe @forward 'module' show (membres) permet de montrer uniquement certains membres :
// _colors.scss
$primary: #3498db;
$secondary: #2ecc71;
$danger: #e74c3c;
$internal-gray: #666;
$debug-color: red;
// _index.scss
@forward 'colors' show ($primary, $secondary, $danger);
// Seules ces 3 variables sont exposées, tout le reste est caché
show vs hide¶
// Utilisez SHOW quand vous voulez exposer PEU de choses
@forward 'colors' show ($primary, $secondary, $danger);
// → 3 variables exposées, le reste caché
// Utilisez HIDE quand vous voulez cacher PEU de choses
@forward 'colors' hide ($debug-color, $internal-gray);
// → Tout exposé sauf 2 variables
10.5 Configurer les modules转发és¶
La configuration via @forward¶
// _index.scss
// Permettre la configuration des modules转发és
@forward 'theme';
// OU avec une configuration par défaut
@forward 'theme' with (
$primary: #3498db
);
// main.scss
// L'utilisateur peut maintenant configurer les modules转发és
@use 'abstracts' with (
$primary: #e74c3c
);
Configuration avancée¶
// _index.scss
@forward 'colors' with (
$primary: #3498db
);
@forward 'variables' with (
$spacing-unit: 8px,
$border-radius: 4px
);
@forward 'theme' with (
$primary: #3498db,
$secondary: #2ecc71
);
10.6 Patterns d'organisation modernes¶
Pattern 1 : Barrel files (fichiers barrel)¶
// Chaque dossier a un _index.scss qui forward ses modules
// Ce fichier est le "barrel" du dossier
// abstracts/_index.scss
@forward 'colors';
@forward 'variables';
@forward 'mixins';
@forward 'functions';
// components/_index.scss
@forward 'buttons';
@forward 'cards';
@forward 'forms';
@forward 'modals';
// layout/_index.scss
@forward 'grid';
@forward 'header';
@forward 'footer';
// pages/_index.scss
@forward 'home';
@forward 'about';
@forward 'contact';
// main.scss — Importe les barrels
@use 'abstracts';
@use 'components';
@use 'layout';
@use 'pages';
Pattern 2 : API publique vs interne¶
// abstracts/_index.scss
// API publique — ce que les autres dossiers peuvent utiliser
@forward 'colors';
@forward 'variables';
@forward 'mixins' as *;
@forward 'functions' as *;
// Cacher les détails d'implémentation
@forward 'internal-helpers' hide (debug, test);
@forward 'deprecated-utils' hide *; // Cache tout
Pattern 3 : Thèmes configurables¶
// themes/_index.scss
@forward 'light-theme' with (
$bg-color: white,
$text-color: #333,
$border-color: #ddd
);
@forward 'dark-theme' with (
$bg-color: #1a1a1a,
$text-color: #f0f0f0,
$border-color: #444
);
@forward 'high-contrast-theme' with (
$bg-color: black,
$text-color: yellow,
$border-color: yellow
);
Pattern 4 : Bibliothèque de composants¶
// components/_index.scss
// Composants principaux (publics)
@forward 'buttons';
@forward 'cards';
@forward 'forms';
@forward 'modals';
@forward 'navigation';
// Composants internes (non exposés)
@forward 'internal/card-variants' hide *;
@forward 'internal/form-helpers' hide *;
Pattern 5 : Organisation par responsabilité¶
// _index.scss — Point d'entrée principal
// 1. Abstracts (pas de CSS généré)
@forward 'abstracts/colors';
@forward 'abstracts/variables';
@forward 'abstracts/mixins' as *;
@forward 'abstracts/functions' as *;
// 2. Base (CSS minimal)
@forward 'base/reset';
@forward 'base/typography';
// 3. Layout (structures)
@forward 'layout/grid';
@forward 'layout/header';
@forward 'layout/footer';
// 4. Composants (éléments UI)
@forward 'components/buttons';
@forward 'components/cards';
// 5. Utilitaires (classes helper)
@forward 'utilities/spacing';
@forward 'utilities/text';
10.7 Cas d'utilisation pratiques¶
Cas 1 : Créer une bibliothèque de design tokens¶
// tokens/_index.scss
@forward 'colors' show ($primary, $secondary, $success, $warning, $danger, $info);
@forward 'spacing' show ($xs, $sm, $md, $lg, $xl, $xxl);
@forward 'typography' show ($font-family, $font-size, $font-weight, $line-height);
@forward 'shadows' show ($shadow-sm, $shadow-md, $shadow-lg);
@forward 'border-radius' show ($radius-sm, $radius-md, $radius-lg, $radius-full);
// Utilisation de la bibliothèque
@use 'tokens' as t;
.button {
background-color: t.colors.$primary;
padding: t.spacing.$md t.spacing.$lg;
font-family: t.typography.$font-family;
border-radius: t.border-radius.$radius-md;
box-shadow: t.shadows.$shadow-sm;
}
Cas 2 : Système de thèmes dark mode¶
// themes/_index.scss
@forward 'light';
@forward 'dark';
// light.scss
$bg-primary: #ffffff;
$bg-secondary: #f8f9fa;
$text-primary: #212529;
$text-secondary: #6c757d;
$border-color: #dee2e6;
$shadow-color: rgba(0, 0, 0, 0.1);
// dark.scss
$bg-primary: #1a1a2e;
$bg-secondary: #16213e;
$text-primary: #e0e0e0;
$text-secondary: #a0a0a0;
$border-color: #333355;
$shadow-color: rgba(0, 0, 0, 0.3);
// main.scss
@use 'abstracts/colors' as c;
// Application du thème clair par défaut
@use 'themes/light' as theme;
// Mode sombre via une classe CSS
.dark-mode {
@use 'themes/dark' as theme;
}
.card {
background-color: theme.$bg-primary;
color: theme.$text-primary;
border: 1px solid theme.$border-color;
box-shadow: 0 2px 8px theme.$shadow-color;
}
Cas 3 : Bundle de composants¶
// components/_index.scss
// Forward tous les composants
@forward 'buttons';
@forward 'cards';
@forward 'forms';
@forward 'modals';
@forward 'alerts';
@forward 'badges';
@forward 'breadcrumbs';
@forward 'pagination';
@forward 'tabs';
@forward 'tooltips';
// Utilisateur importe uniquement ce dont il a besoin
@use 'components/buttons' as btn;
@use 'components/cards';
// OU importe tout
@use 'components';
Cas 4 : Overrides et personnalisations¶
// _defaults.scss
// Valeurs par défaut configurables
$font-size-base: 16px !default;
$line-height-base: 1.5 !default;
$color-primary: #3498db !default;
$spacing-unit: 8px !default;
// _index.scss
@forward 'defaults';
// main.scss — Personnalisation
@use 'abstracts' with (
$font-size-base: 18px,
$color-primary: #e74c3c,
$spacing-unit: 10px
);
10.8 Avantages de @forward¶
1. Encapsulation¶
// Les modules转发és sont encapsulés
// L'utilisateur ne voit que ce qui est exposé
// _internal.scss
$secret-variable: 42; // Interne
$public-variable: 100; // Public
@mixin secret-mixin() { ... } // Interne
@mixin public-mixin() { ... } // Public
// _index.scss
@forward 'internal' show ($public-variable, public-mixin);
// main.scss
@use 'index';
// → $public-variable accessible
// → $secret-variable inaccessible
2. Organisation claire¶
// L'utilisateur sait exactement où trouver quoi
@use 'abstracts'; // Variables, mixins, fonctions
@use 'components'; // Composants UI
@use 'layout'; // Mise en page
// Pas besoin de connaître les détails internes
3. Réutilisabilité¶
// La bibliothèque peut être partagée entre projets
// Le fichier _index.scss définit l'API publique
// Les détails d'implémentation sont cachés
4. Maintenance¶
// Modifier l'implémentation interne sans casser l'API publique
// Réorganiser les fichiers internes sans affecter les importateurs
10.9 Erreurs courantes¶
Erreur 1 : @forward après @use¶
// ❌ ERREUR — @forward doit être avant @use
@use 'colors';
@forward 'mixins'; // ⚠️ @forward doit être avant tout @use
// ✅ CORRECT
@forward 'colors';
@forward 'mixins';
@use 'abstracts';
Erreur 2 : Confondre @forward et @use¶
// @forward RÉ-EXPORTE (rend disponible)
// @use CONSOMME (importe pour usage propre)
// _index.scss
@forward 'colors'; // Rend colors disponible pour les importateurs
// main.scss
@use 'abstracts'; // Consomme l'API de abstracts
@use 'colors'; // ⚠️ Les deux importent colors, mais @use a priorité
Erreur 3 : Utiliser des membres cachés¶
// _index.scss
@forward 'colors' show ($primary, $secondary);
// main.scss
@use 'abstracts' as a;
a.colors.$danger; // ❌ Erreur ! $danger n'est pas dans show
Erreur 4 : Oublier que @forward ne consomme pas¶
// _index.scss
@forward 'colors';
@forward 'mixins';
// Le fichier _index.scss ne peut PAS utiliser les membres de colors
// car il ne fait que les ré-exporter
// Pour utiliser les membres DANS _index.scss, il faut aussi @use
@forward 'colors';
@use 'colors' as c; // Maintenant _index.scss peut utiliser c.$primary
10.10 Exercices¶
Exercice 1 : Créer un barrel file¶
Créez la structure suivante et les fichiers barrel :
abstracts/
├── _colors.scss (5+ couleurs)
├── _variables.scss (5+ variables)
├── _mixins.scss (3+ mixins)
├── _functions.scss (2+ fonctions)
└── _index.scss (barrel file qui forward tout)
Exercice 2 : API publique vs interne¶
Créez un fichier _utils.scss contenant :
- 3 fonctions publiques
- 2 fonctions internes (à cacher)
- 5 variables (3 publiques, 2 internes)
- 2 mixins (1 public, 1 interne)
Puis créez un _index.scss qui forward uniquement les éléments publics.
// Votre _utils.scss
@function public-fn-1() { ... }
@function internal-fn-1() { ... }
$public-var-1: 10;
$internal-var: 20;
@mixin public-mixin() { ... }
@mixin internal-mixin() { ... }
// Votre _index.scss
@forward 'utils' show (???);
Exercice 3 : Thème configurable¶
Créez un système de thèmes :
_light.scsset_dark.scssavec des variables !default_themes-index.scssqui forward les deux thèmesmain.scssqui utilise le thème avec configuration
// light.scss
$bg: white !default;
$text: #333 !default;
// dark.scss
$bg: #1a1a1a !default;
$text: #f0f0f0 !default;
// themes-index.scss
@forward 'light';
@forward 'dark';
// main.scss
@use 'themes' with ($bg: #f5f5f5, $text: #222);
Exercice 4 : Bibliothèque de composants¶
Créez une bibliothèque de composants avec @forward :
Chaque composant doit :
- Importer les abstracts nécessaires avec @use
- Exposer des mixins pour générer les styles
- Être forwardé via _index.scss
Exercice 5 : Migration vers @forward¶
Convertissez ce projet @import en projet @use + @forward :
// AVANT — main.scss
@import 'abstracts/colors';
@import 'abstracts/variables';
@import 'abstracts/mixins';
@import 'abstracts/functions';
@import 'base/reset';
@import 'base/typography';
@import 'layout/grid';
@import 'components/buttons';
@import 'components/cards';
// Créez les barrel files et le nouveau main.scss
Résumé¶
| Concept | Syntaxe | Description |
|---|---|---|
| Ré-exporter | @forward 'module' |
Rend un module disponible pour les importateurs |
| Cacher | @forward 'module' hide (...) |
Cache certains membres |
| Montrer | @forward 'module' show (...) |
Expose uniquement certains membres |
| Configurer | @forward 'module' with (...) |
Configure les variables !default |
| Barrel file | _index.scss |
Fichier qui forward tous les modules d'un dossier |
| Ordre | Avant @use | @forward doit apparaître avant @use |
Quand utiliser @forward ?¶
@forward → Créer une API publique (barrel files)
@forward → Cacher des détails d'implémentation
@forward → Ré-exporter des modules dans un seul fichier
@forward → Créer des bibliothèques de composants
@use → Consommer un module dans votre code
Prochain chapitre : Chapitre 11 : Structure professionnelle — Organisation complète d'un projet Sass professionnel.