Placeholders
Partage des blocs de styles sans duplication de code.
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;
}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: "🏠";
}
}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é