Regrouper, combiner et organiser les sélecteurs pour un CSS efficace et lisible.
Il existe deux aspects :
C'est la capacité de penser en termes de patterns qui distingue un bon développeur CSS d'un débutant.
, permet de regrouper plusieurs sélecteurs dans une seule règle. Le bloc de déclarations s'applique à chaque sélecteur listé. C'est un gain de lignes et de lisibilité.
/* SANS regroupement : 3 blocs identiques */
h1 {
font-family: 'Inter', sans-serif;
color: #1e293b;
}
h2 {
font-family: 'Inter', sans-serif;
color: #1e293b;
}
h3 {
font-family: 'Inter', sans-serif;
color: #1e293b;
}
/* AVEC regroupement : un seul bloc */
h1, h2, h3 {
font-family: 'Inter', sans-serif;
color: #1e293b;
}
/* Format multi-lignes (recommandé) */
h1,
h2,
h3 {
font-family: 'Inter', sans-serif;
color: #1e293b;
line-height: 1.3;
}
Cas d'utilisation courants :
/* Tous les titres */
h1, h2, h3, h4, h5, h6 {
line-height: 1.3;
margin-bottom: 0.5rem;
}
/* Tous les champs de formulaire */
input, textarea, select, button {
font-family: inherit;
font-size: inherit;
}
/* Liens et boutons */
a, button {
cursor: pointer;
}
/* Éléments média */
img, video, canvas {
max-width: 100%;
display: block;
}
/* Classe + type : uniquement les <p> dans .card */
.card p {
color: #64748b;
}
/* ID + enfant direct : les <a> enfants directs de #nav */
#nav > a {
color: white;
}
/* Classe + descendant + frère adjacent */
.article .titre + p {
font-size: 1.1rem;
color: #475569;
}
/* Plusieurs classes */
.btn.btn-primary.btn-lg {
padding: 1rem 2rem;
}
/* Pattern 1 : Composants modulaires */
.card {}
.card__title {}
.card__body {}
.card__footer {}
.card--featured {}
/* Pattern 2 : État avec frère adjacent */
.tab.active + .tab-content {
display: block;
}
/* Pattern 3 : Comportement contextuel */
.sidebar.open ~ .main-content {
margin-left: 280px;
}
/* Pattern 4 : Style conditionnel */
input:disabled {
opacity: 0.5;
cursor: not-allowed;
}
┌─────────────────────────────────────────────────────┐
│ SÉLECTEURS MULTIPLES EN RÉSUMÉ │
├─────────────────────────────────────────────────────┤
│ │
│ VIRGULE (regroupement) │
│ ┌───────────────────────────────────────────┐ │
│ │ h1, h2, h3 { color: red; } │ │
│ │ ↑ ↑ ↑ │ │
│ │ └──┴──┴── Même style pour les 3 │ │
│ └───────────────────────────────────────────┘ │
│ │
│ COMBINAISON (précision) │
│ ┌───────────────────────────────────────────┐ │
│ │ .nav > ul > li > a { color: blue; } │ │
│ │ ↓ ↓ ↓ ↓ │ │
│ │ classe enf direct enf direct enf direct │ │
│ └───────────────────────────────────────────┘ │
│ │
│ MIX (virgule + combiné) │
│ ┌───────────────────────────────────────────┐ │
│ │ h1 + p, h2 + p { font-size: 1.1rem; } │ │
│ │ ↑ ↑ │ │
│ │ └────┬────┘ Même style, 2 contextes │ │
│ └───────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
Les trois modes de combinaison des sélecteurs
Démonstration : Style commun pour les titres
/* Le code appliqué */
h1, h2, h3 {
color: #dc2626;
}
Ce paragraphe n'est pas ciblé par le sélecteur groupé.
Démonstration : Composant carte
/* Structure d'une carte */
.card {
border: 1px solid #e2e8f0;
border-radius: 8px;
padding: 1rem;
}
.card__title {
font-weight: 700;
margin-bottom: 0.5rem;
}
.card__body {
color: #64748b;
font-size: 0.9rem;
}
.card__footer {
margin-top: 0.75rem;
padding-top: 0.75rem;
border-top: 1px solid #e2e8f0;
font-size: 0.85rem;
}
/* Style au survol — frère adjacent + descendant */
.card:hover .card__title {
color: #2563eb;
}
Démonstration : Navigation avec sélecteurs multiples
/* Pattern de navigation */
.pattern-nav {
display: flex;
gap: 0.5rem;
}
/* Liens : enfant direct de la nav */
.pattern-nav > a {
padding: 0.5rem 1rem;
background: white;
border: 1px solid #e2e8f0;
border-radius: 8px;
text-decoration: none;
color: #1e293b;
}
/* Au survol : pseudo-classe + descendant */
.pattern-nav > a:hover {
background: #2563eb;
color: white;
border-color: #2563eb;
}
Démonstration : Tableau avec sélecteurs multiples
/* Tableau complet */
table {
width: 100%;
border-collapse: collapse;
}
/* En-têtes : descendant */
thead th {
background: #f1f5f9;
font-weight: 600;
text-transform: uppercase;
font-size: 0.8rem;
letter-spacing: 0.05em;
}
/* Corps : enfant direct */
tbody > tr {
border-bottom: 1px solid #e2e8f0;
}
/* Dernière ligne : pseudo-classe + descendant */
tbody > tr:last-child {
border-bottom: none;
}
/* Survol de ligne : pseudo-classe */
tbody > tr:hover {
background: #f8fafc;
}
/* Cellules : descendant */
td {
padding: 0.75rem 1rem;
text-align: left;
}
/* FAUX — cible un élément avec les 3 classes à la fois */
h1 h2 h3 { color: red; }
/* CORRECT — la virgule sépare les sélecteurs */
h1, h2, h3 { color: red; }
/* FAUX — trop de sélecteurs dans une règle */
.card, .btn, .input, .nav, .footer, .header, .modal {
font-family: inherit;
}
/* CORRECT — utiliser le sélecteur universel ou un body */
body {
font-family: inherit;
}
/* FAUX — mélange inutile et confus */
#header .nav > ul li a.active, .sidebar .menu-item:hover, footer a {
color: blue;
}
/* CORRECT — séparer par composant */
.header-nav .nav-link.active { color: blue; }
.sidebar .menu-item:hover { color: blue; }
.footer a { color: blue; }
/* FAUX — l'ID rend la règle impossible à surcharger */
#header, .sidebar, .footer {
padding: 1rem;
}
/* CORRECT — utiliser des classes pour le regroupement */
.header, .sidebar, .footer {
padding: 1rem;
}
/* ==========================================
RESET & BASE
========================================== */
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body, h1, h2, h3, h4, h5, h6, p {
margin: 0;
}
img, video {
max-width: 100%;
display: block;
}
/* ==========================================
COMPOSANT : BOUTON
========================================== */
.btn {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 1rem;
border: none;
border-radius: 6px;
font-weight: 600;
cursor: pointer;
transition: background 0.2s;
}
.btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.btn-primary {
background: #2563eb;
color: white;
}
.btn-secondary {
background: #64748b;
color: white;
}
Exercice 1 : Regroupement
Regroupe les règles suivantes en une seule :
h1 { font-family: Arial; }
h2 { font-family: Arial; }
h3 { font-family: Arial; }
Solution :
h1, h2, h3 {
font-family: Arial;
}
Exercice 2 : Combinaison complexe
Écris un sélecteur pour cibler :
<a> à l'intérieur d'un élément avec la classe .sidebarcolor: #2563eb; text-decoration: none; display: block; padding: 0.5rem;Solution :
.sidebar a {
color: #2563eb;
text-decoration: none;
display: block;
padding: 0.5rem;
}
Exercice 3 : Regroupement + combiné
Écris un sélecteur pour cibler les titres <h2> et <h3> qui sont des enfants directs d'un <article>. Le style :
color: #1e293bborder-bottom: 2px solid #e2e8f0padding-bottom: 0.5remSolution :
article > h2,
article > h3 {
color: #1e293b;
border-bottom: 2px solid #e2e8f0;
padding-bottom: 0.5rem;
}
Exercice 4 : Défi combiné
Crée un sélecteur pour cibler les liens dans un <nav> qui sont les enfants directs d'une liste <ul>. Le style :
color: whitetext-decoration: nonepadding: 0.5rem 1remborder-radius: 4pxSolution :
nav > ul > a {
color: white;
text-decoration: none;
padding: 0.5rem 1rem;
border-radius: 4px;
}
Projet : Layout de blog avec composants
Crée un fichier index.html et style.css avec :
Structure HTML :
<header> avec un titre et une navigation<main> contenant 3 articles avec des <h2>, <p>, <footer><aside> avec des liens et une liste<footer> globalCSS requis (utilise les sélecteurs multiples) :
header, main, footerarticle > h2, article > ph1, h2, h3 pour la typographieaside a:hover, article footer p.highlight, .featured pour les états spéciauxQuiz rapide
h1, h2 applique le même style à h1 et h2 ? Oui / Non.card p cible un <p> à 3 niveaux de profondeur ? Oui / Non#header, .sidebar { padding: 1rem; } ?<li> enfants directs d'un <ul> qui est enfant direct d'un <nav>.,.ma-classe, h1, #mon-id { ... }nav > ul > li { ... }