Placeholders
Partage des blocs de styles sans duplication de code.
Imagine : dans ton grimoire d'enchantements, tu as des formules de base que tu peux invoquer dans plusieurs sorts différents, mais ces formules n'existent pas par elles-mêmes. Elles ne deviennent réelles que quand tu les intègres dans un sort complet. Les placeholders SCSS fonctionnent pareil : ils définissent des styles partagés qui ne génèrent du CSS que quand ils sont explicitement utilisés.
10.1Qu'est-ce qu'un placeholder ?
Un placeholder (ou silent class) se définit avec % au lieu de .. Il contient des styles réutilisables, mais contrairement aux classes normales, il n'apparaît jamais dans le CSS final. Il faut l'invoquer avec @extend :
// Définition du placeholder
%bouton-base {
padding: 0.8rem 1.5rem;
border: none;
border-radius: 6px;
cursor: pointer;
font-weight: 600;
transition: all 0.3s ease;
}
// Utilisation avec @extend
.bouton-primaire {
@extend %bouton-base;
background: #3498db;
color: white;
}
.bouton-danger {
@extend %bouton-base;
background: #e74c3c;
color: white;
}Le CSS généré sera optimisé et groupé :
.bouton-primaire, .bouton-danger {
padding: 0.8rem 1.5rem;
border: none;
border-radius: 6px;
cursor: pointer;
font-weight: 600;
transition: all 0.3s ease;
}
.bouton-primaire {
background: #3498db;
color: white;
}
.bouton-danger {
background: #e74c3c;
color: white;
}10.2Placeholder vs Mixin : quelle différence ?
C'est LA question qu'on se pose toujours. Voici la différence fondamentale :
// MIXIN : duplique le code
@mixin bouton-style {
padding: 1rem;
border-radius: 4px;
}
.btn-1 { @include bouton-style; }
.btn-2 { @include bouton-style; }
// CSS généré avec MIXIN (duplication)
.btn-1 {
padding: 1rem;
border-radius: 4px;
}
.btn-2 {
padding: 1rem;
border-radius: 4px;
}
// PLACEHOLDER : groupe le code
%bouton-style {
padding: 1rem;
border-radius: 4px;
}
.btn-1 { @extend %bouton-style; }
.btn-2 { @extend %bouton-style; }
// CSS généré avec PLACEHOLDER (groupé)
.btn-1, .btn-2 {
padding: 1rem;
border-radius: 4px;
}Règle de choix
Utilise lesplaceholders pour des styles identiques partagés (réduction de poids CSS). Utilise les mixins pour des styles avec paramètres ou légèrement différents.10.3Placeholders avec des sélecteurs complexes
Les placeholders peuvent contenir des sélecteurs imbriqués et des états :
%carte-interactive {
background: white;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
transition: all 0.3s ease;
&:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}
.titre {
font-size: 1.2rem;
margin-bottom: 0.5rem;
}
.contenu {
line-height: 1.6;
}
}
.carte-produit {
@extend %carte-interactive;
border-left: 4px solid #3498db;
}
.carte-article {
@extend %carte-interactive;
border-left: 4px solid #27ae60;
}10.4Composition de placeholders
Un placeholder peut étendre un autre placeholder, créant des chaînes d'héritage :
// Placeholder de base
%element-base {
margin: 0;
padding: 0;
box-sizing: border-box;
}
// Placeholder qui hérite du précédent
%element-interactif {
@extend %element-base;
cursor: pointer;
transition: all 0.2s ease;
&:hover {
opacity: 0.8;
}
}
// Placeholder spécialisé
%bouton-style {
@extend %element-interactif;
border: none;
border-radius: 4px;
font-weight: 600;
}
// Utilisation finale
.mon-bouton {
@extend %bouton-style;
background: #3498db;
color: white;
}10.5Placeholders conditionnels
Tu peux créer des placeholders qui ne s'activent que dans certaines conditions :
$theme: "sombre";
%texte-lisible {
@if $theme == "sombre" {
color: #f0f0f0;
background: #333;
} @else {
color: #333;
background: #f0f0f0;
}
}
%focus-visible {
@if $theme == "sombre" {
outline: 2px solid #64b5f6;
} @else {
outline: 2px solid #1976d2;
}
}
.champ-texte {
@extend %texte-lisible;
&:focus {
@extend %focus-visible;
}
}10.6Placeholder avec media queries
Attention avec les media queries ! Tu ne peux pas étendre un placeholder depuis l'intérieur d'une media query si le placeholder est défini à l'extérieur :
%responsive-text {
font-size: 1rem;
@media (max-width: 768px) {
font-size: 0.9rem;
}
}
// ✅ Fonctionne : extend en dehors de media query
.titre {
@extend %responsive-text;
font-weight: bold;
}
// ❌ Erreur : extend depuis l'intérieur d'une media query
.description {
color: #666;
@media (max-width: 768px) {
@extend %responsive-text; // Erreur !
}
}
// ✅ Solution : créer des placeholders spécifiques aux media queries
%text-mobile {
font-size: 0.9rem;
}
.description {
color: #666;
font-size: 1rem;
@media (max-width: 768px) {
@extend %text-mobile; // OK
}
}10.7Organisation des placeholders
Comme pour les autres éléments SCSS, organise tes placeholders par fonction :
abstracts/
├── _placeholders-layout.scss // Positionnement, grilles
├── _placeholders-ui.scss // Boutons, cartes, interfaces
├── _placeholders-text.scss // Typographie, mise en forme
└── _placeholders-states.scss // États (hover, focus, disabled)10.8Bonnes pratiques avec les placeholders
Voici les règles d'or pour utiliser efficacement les placeholders :
// ✅ BON : placeholder pour styles identiques répétés
%reset-list {
list-style: none;
padding: 0;
margin: 0;
}
.nav-menu { @extend %reset-list; }
.breadcrumb { @extend %reset-list; }
.tag-list { @extend %reset-list; }
// ❌ ÉVITER : placeholder pour un seul usage
%title-unique {
font-size: 2rem;
color: #333;
}
.page-title {
@extend %title-unique; // Seulement utilisé ici = inutile
}
// ✅ MIEUX : style direct
.page-title {
font-size: 2rem;
color: #333;
}
// ❌ ÉVITER : placeholder trop spécifique
%bouton-bleu-avec-icone-maison {
background: #3498db;
&::before {
content: "🏠";
}
}
// ✅ MIEUX : placeholder générique + modificateur
%bouton-avec-icone {
position: relative;
padding-left: 2rem;
&::before {
position: absolute;
left: 0.5rem;
}
}
.bouton-accueil {
@extend %bouton-avec-icone;
background: #3498db;
&::before {
content: "🏠";
}
}Performance optimale
Les placeholders brillent quand ils sont utilisés par 3+ sélecteurs. En dessous, un mixin ou du code direct peut être plus approprié. Au-dessus, tu économises significativement du poids CSS.10.9Placeholder ou classe utilitaire ?
Parfois, tu hésites entre un placeholder et une vraie classe CSS. Voici comment décider :
// PLACEHOLDER : styles partagés en SCSS uniquement
%flex-center {
display: flex;
justify-content: center;
align-items: center;
}
.modal-overlay { @extend %flex-center; }
.loading-spinner { @extend %flex-center; }
// CLASSE UTILITAIRE : utilisable directement en HTML
.text-center { text-align: center; }
.hidden { display: none; }
.mt-2 { margin-top: 0.5rem; }Choix selon l'usage :
- Placeholder : style réutilisé uniquement en SCSS, optimisation du CSS
- Classe utilitaire : style appliqué directement en HTML, flexibilité