Sélecteurs
Sélecteurs de base
Les sélecteurs CSS ciblent les éléments HTML pour le style. Les sélecteurs de type correspondent aux noms d'élément (p, div). Les sélecteurs de classe (.) correspondent aux attributs class et peuvent être réutilisés. Les sélecteurs d'ID (#) correspondent à un seul élément et devraient être uniques. Le sélecteur universel (*) correspond à tout. Groupez les sélecteurs avec des virgules pour partager les styles.
/* Type selector - all <p> elements */
p { color: #333; }
/* Class selector - elements with class="btn" */
.btn { padding: 8px 16px; }
/* ID selector - element with id="header" */
#header { background: #fff; }
/* Universal selector - all elements */
* { box-sizing: border-box; }
/* Grouping selector */
h1, h2, h3 { font-family: Arial, sans-serif; }Combinateurs
Les combinateurs définissent les relations entre éléments. Descendant (espace) correspond à n'importe quel élément imbriqué. Enfant (>) correspond seulement aux enfants directs. Frère adjacent (+) correspond à l'élément immédiatement après. Frère général (~) correspond à tous les frères après. Comprendre les combinateurs est essentiel pour un style précis sans classes supplémentaires.
/* Descendant - any <a> inside .nav */
.nav a { text-decoration: none; }
/* Child - direct <li> children of <ul> */
ul > li { list-style: none; }
/* Adjacent sibling - <p> right after <h1> */
h1 + p { font-size: 1.2em; }
/* General sibling - all <p> after <h1> */
h1 ~ p { color: gray; }Sélecteurs d'attribut
Les sélecteurs d'attribut correspondent aux éléments basés sur les valeurs d'attribut. [attr] correspond à la présence. [attr=val] correspond à la valeur exacte. ^= correspond au préfixe, $= au suffixe, *= à la sous-chaîne. Ils sont puissants pour styler les entrées de formulaire, les liens par type, ou les éléments avec attributs data sans ajouter de classes supplémentaires.
/* Elements with type attribute */
[type] { border: 1px solid #ccc; }
/* Exact match */
[type="text"] { padding: 4px; }
/* Starts with */
a[href^="https"] { color: green; }
/* Ends with */
a[href$=".pdf"] { color: red; }
/* Contains */
a[href*="example"] { font-weight: bold; }Pseudo-classes
Les pseudo-classes sélectionnent les éléments basés sur l'état ou la position. Interactives : :hover, :focus, :active, :visited, :disabled. Structurelles : :first-child, :last-child, :nth-child(n), :nth-of-type(n). :not() négatione un sélecteur. :nth-child(odd/even) crée des rayures zébrées. :nth-child(3n) sélectionne chaque 3e élément. Elles réduisent le besoin de classes supplémentaires.
/* Interactive states */
a:hover { color: red; }
a:visited { color: purple; }
input:focus { border-color: blue; }
input:disabled { background: #eee; }
button:active { transform: scale(0.98); }
/* Structural */
li:first-child { font-weight: bold; }
li:last-child { border: none; }
li:nth-child(odd) { background: #f9f9f9; }
li:nth-child(3n) { color: blue; }
p:not(.highlight) { color: #333; }Pseudo-éléments
Les pseudo-éléments (::double-deux-points) stylent des parties spécifiques d'éléments. ::before et ::after insèrent du contenu généré (nécessite la propriété content). ::first-letter et ::first-line stylent des portions de texte. ::selection stylent le texte surligné. ::placeholder stylent les placeholders d'entrée. Note : ::before/::after sont en ligne par défaut — définissez display:block pour un comportement bloc.
/* First line of a paragraph */
p::first-line { font-weight: bold; }
/* First letter (drop cap) */
p::first-letter { font-size: 3em; float: left; }
/* Insert content before/after */
.quote::before { content: "\201C"; }
.quote::after { content: "\201D"; }
/* Selection styling */
::selection { background: yellow; color: black; }
/* Placeholder styling */
input::placeholder { color: #999; }Spécificité & !important
La spécificité détermine quelle règle s'applique quand les sélecteurs entrent en conflit. Styles en ligne > IDs > classes > types. Quand la spécificité est à égalité, la dernière règle gagne. !important surcharge tout mais casse la cascade — évitez-le. Utilisez DevTools pour inspecter la spécificité. Préférez les sélecteurs basés sur les classes pour la maintenabilité. Augmenter la spécificité en répétant des classes (.btn.btn) est un hack — évitez-le.
/* Specificity hierarchy (low to high):
1. Type selectors (p, div) = 0,0,0,1
2. Class selectors (.btn) = 0,0,1,0
3. ID selectors (#header) = 0,1,0,0
4. Inline styles (style="...") = 1,0,0,0
5. !important = overrides all
*/
/* ID beats class */
#nav .link { color: red; } /* wins */
.nav .link { color: blue; }
/* Avoid !important unless necessary */
.critical { color: red !important; }Modèle de boîte
Margin & Padding
Chaque élément est une boîte avec contenu, padding, border et margin. Le padding est à l'intérieur de la bordure (affecte le background), le margin est à l'extérieur (transparent). Raccourci : 1 valeur = tous les côtés, 2 valeurs = haut/bas gauche/droite, 3 = haut gauche/droite bas, 4 = haut droite bas gauche (sens horaire). margin: 0 auto centre les éléments bloc avec une largeur définie.
.box {
/* TRBL: top right bottom left */
margin: 10px 20px 10px 20px;
/* Shorthand: top/bottom left/right */
margin: 10px 20px;
/* All sides */
padding: 15px;
/* Individual sides */
margin-top: 0;
padding-left: 24px;
/* Center horizontally (block) */
margin: 0 auto;
}Border & Outline
border ajoute une ligne autour du padding, affectant la mise en page. outline dessine à l'extérieur de la bordure sans affecter la mise en page — utile pour les indicateurs de focus. border-radius arrondit les coins (valeur unique ou par coin : haut-gauche haut-droit bas-droit bas-gauche). outline-offset ajoute de l'espace entre bordure et outline. Fournissez toujours des styles de focus visibles pour l'accessibilité.
.box {
/* Shorthand: width style color */
border: 2px solid #333;
/* Individual sides */
border-bottom: 3px dashed red;
border-radius: 8px;
/* Outline (doesn't affect layout) */
outline: 2px solid blue;
outline-offset: 4px;
}
/* Remove default focus, add custom */
button:focus {
outline: none;
box-shadow: 0 0 0 3px rgba(0,123,255,0.5);
}Box sizing
box-sizing: content-box (par défaut) signifie que width/height s'appliquent seulement au contenu — le padding et la bordure s'ajoutent à la taille totale. box-sizing: border-box inclut le padding et la bordure dans la width/height, rendant le dimensionnement prévisible. Définissez toujours border-box globalement pour des mises en page cohérentes. C'est l'un des resets CSS les plus importants.
/* Default: width = content only */
.content-box {
box-sizing: content-box;
width: 200px;
padding: 20px;
border: 5px solid;
/* Total width: 200 + 40 + 10 = 250px */
}
/* Recommended: width includes padding+border */
.border-box {
box-sizing: border-box;
width: 200px;
padding: 20px;
border: 5px solid;
/* Total width: 200px */
}
/* Apply globally */
*, *::before, *::after {
box-sizing: border-box;
}Box shadow
box-shadow ajoute des effets d'ombre : offset-x offset-y blur-radius spread-radius color. Les offsets positifs déplacent l'ombre droite/bas. inset crée une ombre intérieure. Les ombres multiples sont superposées (première = haut). Utilisez rgba pour des ombres semi-transparentes qui se fondent naturellement. Les ombres sont géniales pour la profondeur mais la surutilisation nuit à la performance — préférez des ombres subtiles.
/* offset-x offset-y blur spread color */
.card {
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
/* Multiple shadows */
.button {
box-shadow:
0 1px 2px rgba(0,0,0,0.1),
0 4px 8px rgba(0,0,0,0.05);
}
/* Inset shadow */
.input:focus {
box-shadow: inset 0 1px 3px rgba(0,0,0,0.1);
}
/* No shadow */
.no-shadow { box-shadow: none; }Display & Visibility
display: none retire l'élément de la mise en page entièrement (pas d'espace). visibility: hidden le cache mais garde son espace. opacity: 0 le rend transparent mais encore interactif. Les éléments bloc prennent toute la largeur et cassent les lignes. Les éléments en ligne suivent le texte. inline-block combine le flux en ligne avec les dimensions bloc (width, height). Utilisez display: none pour basculer le contenu.
/* Display types */
div { display: block; } /* full width, line break */
span { display: inline; } /* content width, no break */
.inline-block { display: inline-block; } /* inline but block props */
.flex { display: flex; } /* flex container */
.grid { display: grid; } /* grid container */
.none { display: none; } /* removed from layout */
/* Visibility (keeps space) */
.hidden { visibility: hidden; }
/* Opacity (keeps space, can interact) */
.fade { opacity: 0; }Couleurs & unités
Formats de couleur
CSS supporte de multiples formats de couleur. Hex (#rrggbb) est le plus courant. RGB/RGBA ajoute la transparence alpha. HSL (Teinte 0-360, Saturation%, Luminosité%) est intuitif — changez la teinte pour décaler la couleur, la luminosité pour les nuances. currentColor hérite de la propriété color de l'élément. Le CSS moderne supporte aussi oklch() et color() pour des gamuts plus larges. Utilisez rgba/hsla pour la transparence.
/* Named colors */
.color { color: red; background: tomato; }
/* Hexadecimal */
.hex { color: #ff6600; } /* 6-digit */
.hex-short { color: #f60; } /* 3-digit shorthand */
/* RGB / RGBA */
.rgb { color: rgb(255, 102, 0); }
.rgba { background: rgba(0, 0, 0, 0.5); }
/* HSL / HSLA (hue, saturation, lightness) */
.hsl { color: hsl(20, 100%, 50%); }
.hsla { background: hsla(120, 100%, 50%, 0.3); }
/* Current color keyword */
.box { color: blue; border: 2px solid currentColor; }Unités de longueur
px est absolu et prévisible. em est relatif au font-size du parent (se cumule quand imbriqué). rem est relatif au font-size de la racine (html) — cohérent et préféré pour l'accessibilité. % est relatif au parent. vh/vw sont relatifs au viewport (100vh = hauteur complète). Utilisez rem pour les tailles de police, % pour les mises en page, et px pour les bordures/détails fins.
/* Absolute units */
.px { font-size: 16px; } /* 1px = 1/96 inch */
.pt { font-size: 12pt; } /* 1pt = 1/72 inch */
/* Relative to parent font-size */
.em { font-size: 1.5em; } /* 1.5x parent */
/* Relative to root font-size (html) */
.rem { font-size: 1.2rem; } /* 1.2x root (usually 16px) */
/* Relative to parent dimensions */
.pct { width: 50%; } /* 50% of parent */
/* Viewport units */
.vh { height: 100vh; } /* 100% of viewport height */
.vw { width: 50vw; } /* 50% of viewport width */
.vmin { font-size: 2vmin; } /* 2% of smaller dimension */Fonctions CSS
calc() effectue des mathématiques avec des unités mixtes (par exemple, 100% - 250px). min() choisit la plus petite valeur (génial pour les max-widths responsives). max() choisit la plus grande. clamp(min, préféré, max) crée des valeurs fluides qui scalent entre les bornes — parfait pour la typographie responsive. var() référence les propriétés personnalisées avec un repli optionnel. Ces fonctions rendent le CSS dynamique sans media queries.
/* calc() - mathematical calculations */
.sidebar { width: calc(100% - 250px); }
.gap { margin: calc(1rem + 10px); }
/* min() / max() - choose smaller/larger */
.responsive { width: min(90%, 1200px); }
.min-width { width: max(300px, 50%); }
/* clamp() - fluid sizing with bounds */
.title { font-size: clamp(1.5rem, 4vw, 3rem); }
/* var() - use custom properties */
.btn { color: var(--primary, #007bff); }Dégradés
Les dégradés créent des transitions de couleur douces. linear-gradient(direction, couleur1, couleur2) va dans une direction (to right, 45deg). radial-gradient s'étend depuis un point central. conic-gradient tourne autour d'un centre. Vous pouvez ajouter des stops de couleur avec des positions : linear-gradient(to right, red 0%, blue 50%, green 100%). Les dégradés sont des images, pas des couleurs, et peuvent être utilisés partout où background-image est accepté.
/* Linear gradient */
.bg1 {
background: linear-gradient(to right, #ff0000, #0000ff);
}
/* Diagonal with angle */
.bg2 {
background: linear-gradient(45deg, #ff0000, #00ff00, #0000ff);
}
/* Radial gradient */
.bg3 {
background: radial-gradient(circle, #ff0000, #0000ff);
}
/* Conic gradient */
.bg4 {
background: conic-gradient(red, yellow, green, blue, red);
}Filtres & modes de fusion
filter applique des effets visuels : blur(), brightness(), contrast(), grayscale(), sepia(), hue-rotate(), invert(), opacity(), saturate(). Les filtres multiples s'enchaînent. mix-blend-mode fusionne un élément avec ce qui est derrière (multiply, screen, overlay, etc.). backdrop-filter applique des filtres à la zone derrière un élément (génial pour le glassmorphism). Les filtres peuvent impacter la performance — utilisez-les avec parcimonie.
/* Filters */
img.bw { filter: grayscale(100%); }
img.blur { filter: blur(5px); }
img.bright { filter: brightness(1.5); }
img.sepia { filter: sepia(0.8); }
/* Multiple filters */
img.vintage {
filter: sepia(0.5) contrast(1.2) brightness(0.9);
}
/* Blend mode */
.overlay {
background: rgba(255,0,0,0.5);
mix-blend-mode: multiply;
}Typographie
Propriétés de police
font-family accepte une liste de repli — le navigateur utilise le premier disponible. Terminez toujours par une famille générique (serif, sans-serif, monospace). font-weight va de 100 (fin) à 900 (noir). line-height: 1.5 signifie 1.5x la taille de police — 1.4-1.6 est idéal pour la lisibilité du corps de texte. Le raccourci font doit inclure au minimum size et family.
body {
/* Font shorthand: style weight size/line-height family */
font: italic bold 16px/1.5 Arial, sans-serif;
/* Individual properties */
font-family: "Helvetica Neue", Arial, sans-serif;
font-size: 16px;
font-weight: 400; /* 100-900, normal=400, bold=700 */
font-style: italic; /* normal, italic, oblique */
line-height: 1.5;
}Style de texte
text-align contrôle l'alignement horizontal. text-decoration ajoute des lignes (underline, overline, line-through). text-transform change la casse. letter-spacing (tracking) et word-spacing ajustent l'espacement entre les caractères et les mots. white-space: nowrap empêche le retour à la ligne du texte. Pour l'alignement vertical, utilisez vertical-align (en ligne) ou l'alignement flexbox/grid (bloc).
p {
text-align: justify; /* left, right, center, justify */
text-decoration: underline; /* none, overline, line-through */
text-transform: capitalize; /* uppercase, lowercase, capitalize */
text-indent: 2em; /* indent first line */
letter-spacing: 0.05em; /* tracking */
word-spacing: 0.1em;
white-space: nowrap; /* prevent wrapping */
}
a {
text-decoration: none;
color: #0066cc;
}Débordement de texte & retour à la ligne
Pour tronquer le texte avec des points de suspension, vous avez besoin de trois propriétés : white-space: nowrap, overflow: hidden et text-overflow: ellipsis. overflow-wrap: break-word casse les longs mots pour prévenir le débordement. word-break: break-all casse à n'importe quel caractère. text-wrap: balance (plus récent) équilibre les longueurs de ligne pour les titres. Définissez toujours un max-width ou width pour que la troncature fonctionne.
/* Truncate with ellipsis */
.truncate {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 200px;
}
/* Break long words */
.break-word {
overflow-wrap: break-word;
word-break: break-all;
}
/* Balance text wrapping (newer) */
h1 {
text-wrap: balance;
}Polices web (@font-face)
@font-face charge les polices personnalisées. woff2 est le format moderne (meilleure compression). Fournissez woff comme repli. font-display: swap montre le texte de repli immédiatement, puis permute quand la police se charge (prévient le texte invisible). Déclarez toujours une famille de police de repli. Google Fonts fournit des polices hébergées via @import ou <link>. Préchargez les polices critiques pour la performance.
@font-face {
font-family: 'MyCustomFont';
src: url('fonts/custom.woff2') format('woff2'),
url('fonts/custom.woff') format('woff');
font-weight: 400;
font-style: normal;
font-display: swap;
}
body {
font-family: 'MyCustomFont', Arial, sans-serif;
}
/* Google Fonts import */
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');Style de listes & liens
list-style: none retire les puces par défaut pour la navigation personnalisée ou les listes stylées. list-style-type change la puce (disc, circle, square, decimal, none). list-style-position: inside met les puces à l'intérieur de la zone de contenu. Pour les liens, l'ordre LVHA compte : :link, :visited, :hover, :active. Cela assure la cascade correcte des états de lien.
/* Reset list styles */
ul {
list-style: none;
padding: 0;
margin: 0;
}
/* Custom bullets */
ul.custom {
list-style-type: square;
list-style-position: inside;
}
/* Image bullets */
ul.image {
list-style-image: url('bullet.png');
}
/* Link states (order matters!) */
a:link { color: blue; }
a:visited { color: purple; }
a:hover { color: red; text-decoration: underline; }
a:active { color: orange; }Mise en page Flexbox
Conteneur flex
display: flex crée un conteneur flex. justify-content aligne les éléments le long de l'axe principal (horizontal en row). align-items aligne le long de l'axe transversal (vertical). flex-direction change l'axe principal. flex-wrap permet aux éléments de passer à de nouvelles lignes. gap définit l'espacement entre les éléments (remplace les hacks de margin). Flexbox est idéal pour les mises en page 1D (lignes OU colonnes).
.container {
display: flex;
/* Main axis alignment */
justify-content: space-between;
/* flex-start, center, flex-end, space-around, space-evenly */
/* Cross axis alignment */
align-items: center;
/* flex-start, center, flex-end, stretch, baseline */
/* Direction */
flex-direction: row;
/* row, row-reverse, column, column-reverse */
/* Wrapping */
flex-wrap: wrap;
/* nowrap, wrap, wrap-reverse */
/* Gap between items */
gap: 16px;
}Éléments flex
flex-grow contrôle comment les éléments partagent l'espace supplémentaire (0 = ne grandit pas, 1 = grandit également). flex-shrink contrôle comment les éléments rétrécissent quand l'espace est limité. flex-basis définit la taille initiale. Le raccourci flex: 1 signifie flex-grow:1, flex-shrink:1, flex-basis:0%. align-self surcharge le align-items du conteneur pour un élément. order réordonne les éléments visuellement sans changer le DOM.
.item {
/* Grow: how much space to take (0 = don't grow) */
flex-grow: 1;
/* Shrink: how much to shrink when space is tight */
flex-shrink: 0;
/* Basis: initial size before growing/shrinking */
flex-basis: 200px;
/* Shorthand: flex: grow shrink basis */
flex: 1 0 200px;
/* Override align-items for this item */
align-self: flex-end;
/* Order (default 0, lower = earlier) */
order: -1;
}Motifs Flexbox courants
Flexbox rend le centrage trivial : justify-content: center + align-items: center. Pour un footer collant, faites du body une colonne flex avec min-height: 100vh et laissez le contenu principal flex: 1. Pour les barres de navigation, justify-content: space-between pousse les premier et dernier éléments aux extrémités opposées. Ces motifs résolvent des problèmes de mise en page courants qui étaient difficiles avant flexbox.
/* Center anything */
.center {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
/* Sticky footer */
body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.main { flex: 1; }
/* Navbar: logo left, links right */
.nav {
display: flex;
justify-content: space-between;
align-items: center;
}Direction flex & wrap
flex-direction: column crée des mises en page verticales (utile pour empiler). flex-wrap: wrap permet aux éléments de passer à de nouvelles lignes quand ils manquent d'espace. flex: 1 1 300px signifie que les éléments commencent à 300px, grandissent pour remplir l'espace et rétrécissent au besoin. align-content contrôle l'espacement entre les lignes enveloppées (fonctionne seulement avec wrap). Ce motif crée des grilles de cartes responsives.
/* Horizontal (default) */
.row { display: flex; flex-direction: row; }
/* Vertical */
.column { display: flex; flex-direction: column; }
/* Reverse */
.row-rev { display: flex; flex-direction: row-reverse; }
/* Wrap to new lines */
.cards {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
.card { flex: 1 1 300px; } /* grow, shrink, basis */
/* Align wrapped lines */
.cards { align-content: space-between; }Approfondissement de l'alignement Flexbox
En flex-direction: column, l'axe principal est vertical et l'axe transversal est horizontal — justify-content et align-items échangent les rôles. margin: auto sur un élément flex absorbe tout l'espace disponible, le centrant parfaitement. C'est une alternative à justify-content/align-items. Comprendre quel axe est « principal » vs « transversal » est clé pour maîtriser l'alignement flexbox.
.container {
display: flex;
flex-direction: column;
/* Main axis = vertical (column) */
justify-content: flex-start;
/* push items to top, center, bottom, or spread */
/* Cross axis = horizontal (column) */
align-items: stretch;
/* stretch items to full width */
}
/* Center a single item perfectly */
.wrapper {
display: flex;
min-height: 100vh;
}
.centered {
margin: auto; /* centers in both axes */
}Disposition en Grille CSS
Conteneur Grid
display: grid crée une disposition 2D. grid-template-columns définit la taille des colonnes : les unités fr répartissent l'espace libre proportionnellement. repeat(3, 1fr) crée 3 colonnes égales. repeat(auto-fit, minmax(250px, 1fr)) crée une grille responsive qui ajuste automatiquement le nombre de colonnes — c'est le « saint Graal » des grilles responsives. gap remplace les marges pour l'espacement.
.grid {
display: grid;
/* Define columns */
grid-template-columns: 200px 1fr 200px;
/* fixed, flexible, fixed */
/* Or repeat */
grid-template-columns: repeat(3, 1fr);
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
/* Define rows */
grid-template-rows: auto 1fr auto;
/* Gap (formerly grid-gap) */
gap: 20px;
row-gap: 10px;
column-gap: 20px;
}Placement des Éléments Grid
Les éléments Grid peuvent s'étendre sur plusieurs cellules avec grid-column: span N. Vous pouvez aussi utiliser les numéros de ligne : grid-column: 1 / 3 signifie commencer à la ligne 1, finir à la ligne 3. Les lignes sont numérotées de 1 (haut/gauche) à N+1 (bas/droite). grid-area assigne les éléments à des zones nommées. Grid permet un placement 2D précis — les éléments peuvent s'étendre sur les lignes et colonnes simultanément.
.grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 10px;
}
/* Span multiple columns */
.featured {
grid-column: span 2;
}
/* Explicit placement */
.sidebar {
grid-column: 1 / 3; /* start at line 1, end at line 3 */
grid-row: 1 / 4;
}
/* Named areas */
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }Zones de Modèle Grid
grid-template-areas crée une carte visuelle de la disposition en utilisant des chaînes nommées. Chaque chaîne représente une ligne ; chaque nom représente une colonne. Les éléments sont placés en définissant grid-area sur le nom correspondant. C'est la façon la plus lisible de créer des dispositions complexes. Utilisez '.' pour les cellules vides. Le même nom peut s'étendre sur plusieurs cellules. Changez les zones dans les media queries pour des dispositions responsives.
.layout {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
gap: 10px;
min-height: 100vh;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }Alignement Grid
Grid possède 6 propriétés d'alignement. align-items/justify-items alignent les éléments dans leurs cellules. align-content/justify-content alignent la piste entière de la grille dans le conteneur (visible seulement si la grille est plus petite). align-self/justify-self remplacent par élément. place-items: center est un raccourci pour align-items + justify-items. place-content: center combine les deux alignements de contenu.
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
/* Align items within their cell (cross axis) */
align-items: center; /* start, center, end, stretch */
/* Justify items within their cell (main axis) */
justify-items: center;
/* Align the entire grid (if smaller than container) */
align-content: center;
justify-content: center;
}
/* Override for individual item */
.item {
align-self: end;
justify-self: start;
}Grille Responsive (Auto-fit)
repeat(auto-fit, minmax(300px, 1fr)) crée une grille qui ajuste automatiquement le nombre de colonnes selon l'espace disponible — les éléments font au moins 300px et s'étirent pour remplir. Cela élimine les media queries pour les dispositions en cartes. auto-fill conserve les colonnes vides (les éléments restent à gauche), auto-fit les réduit (les éléments s'étirent). Utilisez auto-fit dans la plupart des cas. Combinez avec max-width sur le conteneur pour des résultats optimaux.
/* Auto-responsive grid - no media queries needed! */
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
}
/* Fixed number of columns per breakpoint */
@media (min-width: 768px) {
.cards {
grid-template-columns: repeat(2, 1fr);
}
}
@media (min-width: 1024px) {
.cards {
grid-template-columns: repeat(3, 1fr);
}
}
/* Auto-fill vs auto-fit:
auto-fit collapses empty tracks
auto-fill keeps empty tracks */Positionnement
Types de Position
static est la valeur par défaut (flux normal du document). relative se décale de sa position normale sans affecter les autres éléments (crée un contexte de positionnement). absolute retire du flux et se positionne par rapport à l'ancêtre positionné le plus proche. fixed se positionne par rapport au viewport (reste au défilement). sticky bascule entre relative et fixed — défile normalement puis se fixe au seuil.
/* Static (default) - normal flow */
.static { position: static; }
/* Relative - offset from normal position */
.relative {
position: relative;
top: 10px;
left: 20px;
}
/* Absolute - positioned relative to nearest positioned ancestor */
.absolute {
position: absolute;
top: 0;
right: 0;
}
/* Fixed - positioned relative to viewport */
.fixed {
position: fixed;
bottom: 0;
width: 100%;
}
/* Sticky - scrolls then sticks */
.sticky {
position: sticky;
top: 0;
}Positionnement Absolu
Le positionnement absolu nécessite un ancêtre positionné (relative, absolute, fixed ou sticky). Sans ancêtre, il se positionne par rapport au viewport. Les propriétés top/right/bottom/left se décalent du bord correspondant. Pour centrer un élément positionné en absolu, utilisez top:50%, left:50% avec transform: translate(-50%,-50%). Le positionnement absolu retire les éléments du flux normal.
/* Parent must be positioned */
.container {
position: relative;
width: 400px;
height: 300px;
}
/* Position relative to container */
.badge {
position: absolute;
top: 10px;
right: 10px;
}
/* Center absolutely positioned element */
.modal {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}Positionnement Sticky
position: sticky est un hybride — les éléments défilent normalement jusqu'à atteindre un seuil (ex. top: 0), puis se fixent. Idéal pour les en-têtes sticky, les barres latérales et les en-têtes de tableau. L'élément se fixe dans son conteneur parent (arrête de se fixer quand le parent défile au-delà). Sticky ne fonctionne pas si un ancêtre a overflow: hidden/auto/scroll. Définissez toujours un z-index pour éviter les problèmes de chevauchement.
/* Sticky header */
.header {
position: sticky;
top: 0;
background: white;
z-index: 100;
padding: 1rem;
}
/* Sticky sidebar */
.sidebar {
position: sticky;
top: 80px; /* offset for fixed header */
height: calc(100vh - 80px);
overflow-y: auto;
}
/* Note: sticky doesn't work if a parent has
overflow: hidden or overflow: auto */Z-index & Contexte d'Empilement
z-index contrôle l'ordre d'empilement des éléments positionnés (plus élevé = au-dessus). Il ne fonctionne que sur les éléments positionnés (pas static). Un contexte d'empilement est créé par les éléments positionnés avec z-index, opacity < 1, transform ou filter. Dans un contexte d'empilement, les valeurs z-index des enfants sont relatives à ce contexte — un enfant ne peut jamais apparaître au-dessus d'un sibling de son parent avec un z-index plus élevé. C'est une source courante de confusion.
/* Higher z-index = closer to viewer */
.modal-overlay {
position: fixed;
z-index: 9999;
top: 0; left: 0; right: 0; bottom: 0;
background: rgba(0,0,0,0.5);
}
.modal {
position: fixed;
z-index: 10000; /* above overlay */
top: 50%; left: 50%;
transform: translate(-50%, -50%);
}
/* Stacking context: z-index only works
within the same stacking context */
.parent { position: relative; z-index: 1; }
.child { position: absolute; z-index: 9999; }
/* child can't exceed parent's stacking level */Float & Clear (Legacy)
float était la principale méthode de disposition avant flexbox/grid. Il retire les éléments du flux normal et les pousse à gauche/droite, le texte s'enroulant autour. clear empêche les éléments d'apparaître à côté des flottants. Le hack clearfix force un conteneur à englober ses enfants flottants. Aujourd'hui, utilisez float uniquement pour son but prévu : enrouler du texte autour d'images. Pour les dispositions, utilisez flexbox ou grid.
/* Float text around an image */
img.float-left {
float: left;
margin: 0 1rem 1rem 0;
}
/* Clear floats */
.clear { clear: both; }
.clear-left { clear: left; }
.clear-right { clear: right; }
/* Clearfix hack for containers */
.clearfix::after {
content: "";
display: table;
clear: both;
}
/* Modern alternative: use flexbox or grid */
/* Float is mainly for text wrapping now */Design Responsive
Media Queries
Les media queries appliquent des styles selon des conditions. min-width (mobile-first) est préféré — les styles de base ciblent le mobile, puis s'améliorent pour les écrans plus grands. max-width (desktop-first) est l'inverse. Autres conditions : prefers-color-scheme (sombre/clair), print, orientation (portrait/paysage), prefers-reduced-motion. Définissez toujours une balise meta viewport dans le HTML pour que les media queries fonctionnent sur mobile.
/* Mobile-first: base styles first, then min-width */
/* Base (mobile) */
.container { flex-direction: column; }
/* Tablet and up */
@media (min-width: 768px) {
.container { flex-direction: row; }
}
/* Desktop and up */
@media (min-width: 1024px) {
.container { max-width: 1200px; margin: 0 auto; }
}
/* Print styles */
@media print {
.no-print { display: none; }
}
/* Dark mode */
@media (prefers-color-scheme: dark) {
body { background: #1a1a1a; color: #eee; }
}Typographie Fluide
clamp(min, preferred, max) crée une typographie fluide qui évolue en douceur avec la taille du viewport — sans media queries. La valeur préférée (souvent basée sur vw) évolue entre les bornes min et max. min() choisit la plus petite valeur (idéal pour les max-width responsives). Cette approche réduit le nombre de media queries nécessaires et crée une mise à l'échelle plus fluide. Définissez toujours des min/max raisonnables pour la lisibilité.
/* clamp() for fluid font sizes */
h1 {
font-size: clamp(1.5rem, 5vw, 3rem);
/* min: 1.5rem, preferred: 5vw, max: 3rem */
}
/* Fluid spacing */
.container {
padding: clamp(1rem, 3vw, 3rem);
}
/* Fluid width */
.content {
width: min(90%, 1200px);
margin: 0 auto;
}
/* Viewport-based sizing */
.hero {
height: 100vh;
font-size: clamp(2rem, 8vw, 5rem);
}Container Queries
Les container queries (CSS Containment Module Level 3) permettent de styliser des éléments selon la taille de leur conteneur parent, pas du viewport. container-type: inline-size déclare un conteneur. @container applique des styles quand le conteneur respecte la condition. C'est plus modulaire que les media queries — les composants s'adaptent à leur conteneur, pas à l'écran. Idéal pour les composants réutilisables dans différents contextes de disposition.
/* Define a container */
.card-container {
container-type: inline-size;
/* or: container: sidebar / inline-size; */
}
/* Query the container's size */
@container (min-width: 400px) {
.card {
display: flex;
flex-direction: row;
}
}
@container (max-width: 399px) {
.card {
display: flex;
flex-direction: column;
}
}Images & Médias Responsives
max-width: 100% + height: auto rend les images responsives (réduction mais jamais agrandissement). Le hack padding-bottom crée des intégrations vidéo 16:9 responsives. La propriété moderne aspect-ratio est plus propre — définissez le ratio et le navigateur calcule la hauteur. Définissez toujours les attributs width et height sur les images pour éviter le décalage de disposition (CLS). Utilisez object-fit: cover pour recadrer les images dans des dimensions fixes.
/* Responsive image */
img {
max-width: 100%;
height: auto;
}
/* Responsive video (16:9 aspect ratio) */
.video-wrapper {
position: relative;
padding-bottom: 56.25%; /* 9/16 */
height: 0;
}
.video-wrapper iframe {
position: absolute;
top: 0; left: 0;
width: 100%;
height: 100%;
}
/* Aspect ratio property */
.box {
aspect-ratio: 16 / 9;
width: 100%;
}Stratégie Mobile-First
Mobile-first signifie écrire les styles mobile comme base, puis améliorer progressivement pour les écrans plus grands avec des media queries min-width. Cela garantit que les utilisateurs mobile (souvent sur connexions plus lentes) téléchargent moins de CSS. Breakpoints courants : 768px (tablette), 1024px (desktop), 1440px (grand). Utilisez des unités relatives (rem, %, vw) au lieu de px fixes pour une meilleure scalabilité. Testez sur de vrais appareils, pas seulement DevTools.
/* 1. Start with mobile base styles */
.nav { display: none; } /* hidden on mobile */
.menu-toggle { display: block; }
/* 2. Enhance for larger screens */
@media (min-width: 768px) {
.nav { display: flex; }
.menu-toggle { display: none; }
}
/* 3. Common breakpoints */
/* Mobile: < 768px */
/* Tablet: 768px - 1023px */
/* Desktop: 1024px - 1439px */
/* Large: >= 1440px */
/* 4. Use relative units */
body { font-size: 1rem; } /* not 16px */Transitions & Animations
Transitions
transition crée des changements en douceur entre les valeurs de propriétés. Syntaxe : transition: property duration timing-function delay. Fonctions de timing : ease (par défaut), linear, ease-in, ease-out, ease-in-out, cubic-bezier(). Seules les propriétés animables transitionnent. Évitez transition: all (performance). Les transitions se déclenchent sur les changements de pseudo-classes (:hover, :focus) ou de classes via JavaScript.
.button {
background: #007bff;
transition: background 0.3s ease, transform 0.2s ease;
}
.button:hover {
background: #0056b3;
transform: translateY(-2px);
}
/* Transition all properties (use sparingly) */
.card {
transition: all 0.3s ease;
}
/* Shorthand: property duration timing-function delay */
.box {
transition: opacity 0.5s ease-in 0.2s;
}Transform
transform modifie un élément sans affecter la disposition (contrairement à margin/position). translate le déplace (translateX, translateY ou translate(x,y)). scale le redimensionne (1 = 100%). rotate le fait pivoter (deg, rad, turn). skew le distord. Plusieurs transforms s'enchaînent dans l'ordre. Les transforms sont accélérés par GPU — excellents pour la performance. Associez toujours avec transition pour des effets fluides. transform-origin change le point de pivot.
.box {
transition: transform 0.3s ease;
}
/* Translate (move) */
.box:hover { transform: translate(10px, 20px); }
.box:hover { transform: translateX(50%); }
/* Scale (resize) */
.box:hover { transform: scale(1.1); }
/* Rotate */
.box:hover { transform: rotate(45deg); }
/* Skew */
.box:hover { transform: skew(10deg, 5deg); }
/* Combine transforms */
.box:hover {
transform: translate(10px, 0) scale(1.1) rotate(5deg);
}Animations Keyframes
@keyframes définit les étapes d'animation. 0%/from est le début, 100%/to est la fin. Vous pouvez ajouter des étapes intermédiaires (25%, 50%, 75%). Le raccourci animation : name duration timing-function delay iteration-count direction fill-mode. infinite boucle indéfiniment. direction: alternate inverse sur les itérations paires. fill-mode: forwards conserve l'état final. Les animations s'exécutent automatiquement, contrairement aux transitions.
@keyframes bounce {
0% { transform: translateY(0); }
50% { transform: translateY(-20px); }
100% { transform: translateY(0); }
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.ball {
animation: bounce 0.5s ease infinite;
}
.element {
animation: fadeIn 1s ease forwards;
/* name duration timing delay iteration direction fill-mode */
}Propriétés d'Animation
Les propriétés d'animation individuelles offrent un contrôle fin. animation-iteration-count peut être un nombre ou infinite. animation-direction: alternate joue en avant puis en arrière (idéal pour les effets ping-pong). animation-fill-mode: forwards conserve l'état final après la fin. animation-play-state: paused fige l'animation — utile pour pause-au-survol. Plusieurs animations séparées par virgule : animation: spin 1s, fade 2s;.
.spinner {
animation-name: spin;
animation-duration: 1s;
animation-timing-function: linear;
animation-delay: 0s;
animation-iteration-count: infinite;
animation-direction: normal; /* alternate, reverse */
animation-fill-mode: none; /* forwards, backwards, both */
animation-play-state: running; /* paused */
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
/* Pause on hover */
.spinner:hover {
animation-play-state: paused;
}Performance & Mouvement Réduit
Pour des animations fluides à 60fps, animez uniquement transform et opacity — ils sont accélérés par GPU et ne déclenchent pas de layout (reflow). Animer width, margin, top, etc. force le navigateur à recalculer la disposition à chaque frame, causant des saccades. Respectez toujours prefers-reduced-motion: reduce — certains utilisateurs souffrent du mal des transports ou ont des troubles vestibulaires. Fournissez des transitions instantanées ou désactivez les animations pour ces utilisateurs.
/* Only animate transform and opacity for performance */
.good {
transition: transform 0.3s, opacity 0.3s;
}
/* Avoid animating these (cause reflow/repaint): */
/* margin, padding, width, height, top, left */
/* Respect user's motion preference */
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
}
}Variables & Fonctions Avancées
Propriétés Personnalisées (Variables)
Les propriétés personnalisées (variables CSS) stockent des valeurs réutilisables. Définissez-les dans :root pour un accès global. Référencez avec var(--name). Elles se propagent et peuvent être remplacées dans n'importe quelle portée — parfait pour le theming (mode sombre/clair). Contrairement aux variables de préprocesseur, elles sont dynamiques (changent à l'exécution) et peuvent être manipulées avec JavaScript. Fournissez toujours des valeurs de repli : var(--primary, #007bff). C'est la façon moderne de gérer les design tokens.
:root {
/* Colors */
--primary: #007bff;
--primary-dark: #0056b3;
--text: #333;
--bg: #fff;
/* Spacing scale */
--space-sm: 0.5rem;
--space-md: 1rem;
--space-lg: 2rem;
/* Font sizes */
--font-base: 16px;
--font-lg: 1.5rem;
}
.button {
background: var(--primary);
padding: var(--space-sm) var(--space-md);
font-size: var(--font-base);
color: white;
}
/* Override in a scope */
.dark-theme {
--bg: #1a1a1a;
--text: #eee;
}calc() & Fonctions Mathématiques
calc() effectue des calculs avec n'importe quelles unités, y compris en mélangeant px, %, em, rem, vw. Essentiel pour les dispositions responsives. Vous pouvez imbriquer calc() mais c'est inutile — calc(100% - 2rem) / 3 fonctionne sans calc interne. min() retourne la plus petite valeur, max() la plus grande, clamp() borne une valeur entre min et max. Ces fonctions rendent le CSS dynamique sans JavaScript ni media queries.
/* Mixed unit calculations */
.sidebar {
width: calc(100% - 250px);
}
/* With variables */
.box {
padding: calc(var(--space-md) + 10px);
}
/* Nested calc */
.responsive {
width: calc(calc(100% - 2rem) / 3);
}
/* min(), max(), clamp() */
.fluid {
width: min(90%, 1200px);
font-size: clamp(1rem, 2vw + 1rem, 2rem);
height: max(200px, 50vh);
}Object Fit & Position
object-fit contrôle comment les images/vidéos remplissent leur conteneur (comme background-size pour <img>). cover remplit le conteneur et recadre le débordement (idéal pour avatars/vignettes). contain s'ajuste entièrement sans recadrage (peut laisser de l'espace vide). fill étire (distord). object-position ajuste l'alignement (comme background-position). Cela remplace le besoin de hacks background-image pour les images responsives.
/* Cover: fill container, crop overflow */
.avatar {
width: 100px;
height: 100px;
object-fit: cover;
border-radius: 50%;
}
/* Contain: fit entirely, may letterbox */
.preview {
width: 200px;
height: 200px;
object-fit: contain;
background: #eee;
}
/* Position the image within the frame */
.image {
object-fit: cover;
object-position: top center;
}Propriétés de Background
background est un raccourci puissant. background-size: cover remplit le conteneur (recadrage) ; contain s'ajuste sans recadrage. background-attachment: fixed crée un effet parallaxe (l'image reste immobile au défilement). Plusieurs backgrounds se superposent avec des virgules (premier = couche supérieure). Utilisez linear-gradient comme background pour les superpositions : background: linear-gradient(rgba(0,0,0,0.5), transparent), url('image.jpg').
.hero {
/* Shorthand */
background: url('hero.jpg') center/cover no-repeat fixed;
/* Individual properties */
background-image: url('hero.jpg');
background-size: cover; /* cover, contain, or px/% */
background-position: center; /* top, bottom, left, right, or x y */
background-repeat: no-repeat;
background-attachment: fixed; /* scroll, fixed, local */
/* Multiple backgrounds */
background:
url('overlay.png') no-repeat center,
url('hero.jpg') center/cover;
}Imbrication CSS (Moderne)
Le CSS moderne supporte l'imbrication native (comme Sass/Less). Utilisez & pour référencer le sélecteur parent. L'imbrication améliore la lisibilité et réduit la répétition. Les media queries peuvent être imbriquées directement dans les règles. Le support navigateur est bon dans les navigateurs modernes (2023+). Le & est requis pour les pseudo-classes (&:hover) et les combinateurs (& > .child). Évitez l'imbrication profonde (3+ niveaux) car elle augmente la spécificité et réduit la maintenabilité.
/* Native CSS nesting (no preprocessor needed) */
.card {
background: white;
border-radius: 8px;
& .title {
font-size: 1.5rem;
font-weight: bold;
}
& .body {
padding: 1rem;
& p {
line-height: 1.6;
}
}
&:hover {
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
@media (max-width: 768px) {
padding: 0.5rem;
}
}Propriétés Personnalisées CSS (Variables) Approfondi
Définition & Utilisation des Variables
Les propriétés personnalisées CSS (variables) sont définies avec --name et utilisées avec var(). Définissez les variables globales dans :root pour les valeurs de thème. Contrairement aux variables Sass, les variables CSS sont live — les modifier met à jour toutes les utilisations instantanément. Elles sont limitées à l'élément où elles sont définies et héritées par les descendants. var() accepte une valeur de repli comme second argument, et les replis peuvent être chaînés. Cela les rend bien plus puissantes que les variables de préprocesseur pour le theming dynamique.
:root {
--primary: #3498db;
--spacing: 16px;
--radius: 8px;
--max-width: 1200px;
}
.button {
background: var(--primary);
padding: var(--spacing);
border-radius: var(--radius);
max-width: var(--max-width);
}
/* Fallback values */
color: var(--text-color, #333);
/* Chained fallbacks */
color: var(--text, var(--default, black));Theming Dynamique avec JavaScript
Les variables CSS permettent un theming à l'exécution que les préprocesseurs ne peuvent pas faire. Définissez data-theme sur <html> et remplacez les variables par thème. JavaScript peut lire (getComputedStyle) et définir (style.setProperty) des variables à l'exécution, permettant des sélecteurs de couleur dynamiques, des préférences utilisateur et des aperçus en direct. C'est l'approche standard pour le mode sombre, la personnalisation de marque et les thèmes sélectionnables par l'utilisateur. Les variables se propagent et héritent, donc remplacer dans un enfant n'affecte que ce sous-arbre.
/* Define theme variables */
:root {
--bg: #ffffff;
--text: #333333;
}
[data-theme="dark"] {
--bg: #1a1a1a;
--text: #e0e0e0;
}
body {
background: var(--bg);
color: var(--text);
}
/* Toggle theme with JS */
<script>
document.documentElement.setAttribute(
"data-theme",
isDark ? "dark" : "light"
);
/* Or set a single variable directly */
document.documentElement.style
.setProperty("--primary", "#e74c3c");
</script>Variables à Portée & Héritage
Les variables CSS héritent comme les autres propriétés. Une variable définie sur :root est disponible partout ; une définie sur .card n'affecte que .card et ses descendants. Cette portée permet la personnalisation au niveau du composant. Vous pouvez remplacer des variables dans les media queries pour créer des valeurs de variables responsives — la variable elle-même ne peut pas être utilisée dans les conditions @media, mais vous pouvez changer sa valeur dans un bloc media query. Ce pattern est puissant pour le design responsive sans répéter les déclarations de propriétés.
:root {
--padding: 20px;
}
.card {
--padding: 12px; /* overrides only for .card subtree */
padding: var(--padding);
}
.card .inner {
padding: var(--padding); /* inherits 12px from .card */
}
/* Variables in media queries don't work, but... */
.sidebar {
--width: 250px;
width: var(--width);
}
@media (max-width: 768px) {
.sidebar { --width: 100%; }
}Variables avec calc()
Combiner les variables CSS avec calc() crée des design systems puissants. Définissez une taille de base et un facteur d'échelle, puis calculez les tailles dérivées. Cela permet des échelles typographiques et des systèmes d'espacement cohérents. calc() fonctionne avec des unités mixtes (px, %, em, vw) et des variables. Vous pouvez même utiliser des variables sans repli (var(--nav-h, 60px) fournit une valeur par défaut). Cette approche est la fondation des design systems modernes — changez une variable et toute l'échelle s'ajuste proportionnellement.
:root {
--base-size: 16px;
--scale: 1.25;
}
h1 { font-size: calc(var(--base-size) * var(--scale) * 2); }
h2 { font-size: calc(var(--base-size) * var(--scale) * 1.5); }
p { font-size: var(--base-size); }
/* Spacing scale */
:root {
--space: 8px;
}
.margin { margin: calc(var(--space) * 2); }
.padding { padding: calc(var(--space) * 3); }
/* Mixed units */
.header { height: calc(var(--nav-h, 60px) + var(--content-h)); }Enregistrement des Propriétés Personnalisées (@property)
@property enregistre les propriétés personnalisées avec un type (syntax), une valeur initiale et un indicateur d'héritage. Cela permet aux variables CSS d'être animées et transitionnées — sans @property, les variables sont traitées comme des chaînes et ne peuvent pas être interpolées. syntax accepte des types comme <angle>, <color>, <length>, <number>, <percentage> ou '*'. Cela débloque des animations fluides de gradients, transforms et couleurs pilotées par des variables. Le support navigateur est bon dans Chromium et Safari, Firefox ajoutant le support. Une avancée majeure pour les capacités d'animation CSS.
/* Type-safe custom properties */
@property --angle {
syntax: "<angle>";
initial-value: 0deg;
inherits: false;
}
@property --color {
syntax: "<color>";
initial-value: #3498db;
inherits: false;
}
/* Now animatable! */
@keyframes spin {
to { --angle: 360deg; }
}
.loader {
--angle: 0deg;
animation: spin 1s linear infinite;
background: conic-gradient(
from var(--angle),
var(--color), transparent
);
}Transforms 3D
Fonctions de Transform 3D
Les transforms 3D ajoutent de la profondeur aux éléments. perspective() comme fonction de transform s'applique à un seul élément ; la propriété perspective sur un parent s'applique à tous les enfants uniformément. rotateX/rotateY/rotateZ pivotent autour des axes ; translateZ se déplace le long de l'axe Z (vers/loin du spectateur). Des valeurs perspective plus basses créent des effets 3D plus dramatiques (point de vue plus proche). Définissez toujours perspective sur le conteneur parent pour un espace 3D cohérent entre plusieurs enfants transformés. Combinez plusieurs transforms pour un positionnement 3D complexe.
.card {
transform: perspective(1000px) rotateY(45deg) rotateX(15deg);
}
/* Using the perspective property instead */
.container {
perspective: 1000px;
}
.container .card {
transform: rotateY(45deg) rotateX(15deg);
}
/* translateZ moves toward/away from viewer */
.layer {
transform: translateZ(100px);
}
/* scale3d for 3D scaling */
.box {
transform: scale3d(1.5, 1.5, 1.5);
}transform-style & backface-visibility
transform-style: preserve-3d maintient l'espace 3D pour les éléments enfants (flat est la valeur par défaut, qui aplatit les enfants). backface-visibility: hidden cache le dos d'un élément quand il est pivoté — essentiel pour les effets de carte retournée. La carte retournée classique utilise deux faces positionnées en absolu : la face avant fait face à l'avant, la face arrière est pré-pivotée de 180deg. Au survol, le parent pivote de 180deg, inversant quelle face est visible. C'est un des patterns 3D CSS les plus populaires.
.container {
perspective: 1000px;
}
.flip-card {
transform-style: preserve-3d;
transition: transform 0.6s;
position: relative;
}
.flip-card:hover {
transform: rotateY(180deg);
}
.flip-card .front,
.flip-card .back {
position: absolute;
inset: 0;
backface-visibility: hidden;
}
.flip-card .back {
transform: rotateY(180deg);
}Cube 3D
Un cube 3D est construit avec 6 faces, chacune positionnée avec rotate + translateZ. translateZ(100px) pousse la face de la moitié de la largeur du cube vers l'extérieur. Chaque face est pré-pivotée pour faire face à sa direction avant d'être poussée. transform-style: preserve-3d sur le conteneur du cube est essentiel — sans lui, les faces s'aplatissent. L'animation fait pivoter le cube sur les axes X et Y. Cela démontre toute la puissance des transforms 3D CSS. Ajustez translateZ pour correspondre à la moitié de la taille de votre cube pour une géométrie correcte.
.scene {
perspective: 800px;
width: 200px; height: 200px;
}
.cube {
position: relative;
width: 100%; height: 100%;
transform-style: preserve-3d;
animation: rotate 8s infinite linear;
}
@keyframes rotate {
from { transform: rotateX(0) rotateY(0); }
to { transform: rotateX(360deg) rotateY(360deg); }
}
.face {
position: absolute;
width: 200px; height: 200px;
opacity: 0.85;
}
.front { transform: translateZ(100px); background: red; }
.back { transform: rotateY(180deg) translateZ(100px); background: blue; }
.right { transform: rotateY(90deg) translateZ(100px); background: green; }
.left { transform: rotateY(-90deg) translateZ(100px); background: yellow; }
.top { transform: rotateX(90deg) translateZ(100px); background: purple; }
.bottom { transform: rotateX(-90deg) translateZ(100px); background: orange; }Effet d'Inclinaison de Carte 3D
L'effet d'inclinaison de carte suit la position de la souris et fait pivoter la carte en 3D selon le décalage du curseur par rapport au centre. Le calcul divise le décalage par un facteur (10) pour limiter l'angle de rotation. Au mouseleave, la carte se réinitialise à plat. La transition crée un mouvement fluide. Ajouter une superposition d'éblouissement/brillance avec un gradient radial qui suit la souris améliore l'effet. C'est un pattern UI interactif populaire pour les cartes produit et les sections hero. La perspective dans la chaîne transform assure le rendu 3D même sans propriété perspective parent.
.tilt-card {
transition: transform 0.1s ease-out;
transform-style: preserve-3d;
}
/* JavaScript-driven tilt */
<script>
const card = document.querySelector(".tilt-card");
card.addEventListener("mousemove", (e) => {
const rect = card.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const centerX = rect.width / 2;
const centerY = rect.height / 2;
const rotateX = (y - centerY) / 10;
const rotateY = (centerX - x) / 10;
card.style.transform =
`perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
});
card.addEventListener("mouseleave", () => {
card.style.transform = "perspective(1000px) rotateX(0) rotateY(0)";
});
</script>perspective-origin & Espacement 3D
perspective-origin définit la position du point de fuite (comme bouger la tête). La valeur par défaut est 50% 50% (centre). La déplacer crée des angles de vue dynamiques. Pour les effets parallaxe, les éléments à différentes valeurs translateZ se déplacent à des vitesses différentes quand le conteneur défile ou pivote. Les éléments plus en arrière (translateZ négatif) ont besoin de scale() pour compenser la réduction de perspective. Cette technique crée de la profondeur dans l'UI sans JavaScript — parallaxe pur CSS. Combiné avec les animations pilotées par défilement, cela crée des expériences de défilement immersives.
.stage {
perspective: 1200px;
perspective-origin: 50% 30%; /* x y position of vanishing point */
transform-style: preserve-3d;
}
.layer-1 { transform: translateZ(0); }
.layer-2 { transform: translateZ(50px); }
.layer-3 { transform: translateZ(100px); }
/* Parallax-like depth */
.depth-bg { transform: translateZ(-200px) scale(1.2); }
.depth-mid { transform: translateZ(-100px) scale(1.1); }
.depth-fg { transform: translateZ(0); }Filtres CSS & Filtres de Fond
Fonctions de Filtre
Les filtres CSS appliquent des effets visuels aux éléments. grayscale, sepia et invert changent les couleurs ; blur adoucit ; brightness/contrast/saturate ajustent l'intensité ; hue-rotate décale les couleurs. Plusieurs filtres s'enchaînent de gauche à droite. drop-shadow est supérieur à box-shadow pour les images PNG/SVG car il suit la forme alpha (les zones transparentes ne reçoivent pas d'ombre). Les filtres sont accélérés par GPU et performants. Usage courant : grayscale au survol pour les galeries d'images, effets photo vintage et accessibilité (modes contraste élevé).
img.grayscale { filter: grayscale(100%); }
img.blur { filter: blur(5px); }
img.bright { filter: brightness(1.5); }
img.contrast { filter: contrast(200%); }
img.sepia { filter: sepia(80%); }
img.saturate { filter: saturate(2); }
img.hue { filter: hue-rotate(90deg); }
img.invert { filter: invert(100%); }
/* Combine multiple filters */
img.vintage {
filter: sepia(50%) contrast(110%) brightness(90%) saturate(120%);
}
/* Drop shadow (follows alpha shape) */
img.png-shadow {
filter: drop-shadow(2px 4px 6px rgba(0,0,0,0.4));
}backdrop-filter (Glassmorphism)
backdrop-filter applique des filtres à la zone derrière un élément (pas l'élément lui-même), créant l'effet glassmorphism. L'élément a besoin d'un arrière-plan semi-transparent pour que l'effet soit visible. blur est le filtre de fond le plus courant pour le verre dépoli. Incluez toujours le préfixe -webkit- pour le support Safari. Combinez avec des bordures semi-transparentes et des box-shadows subtils pour un aspect verre poli. La performance peut être un problème avec de grandes zones floues — utilisez avec parcimonie. C'est une tendance définissante du design UI moderne (iOS, macOS, Windows Acrylic).
.glass {
background: rgba(255, 255, 255, 0.2);
backdrop-filter: blur(10px) saturate(180%);
-webkit-backdrop-filter: blur(10px) saturate(180%);
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 16px;
padding: 24px;
}
.glass-dark {
background: rgba(0, 0, 0, 0.4);
backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.1);
}Filtres SVG (référence url)
CSS filter: url(#id) référence les filtres SVG pour des effets au-delà des fonctions intégrées. Le filtre 'gooey' crée une fusion blob-like des éléments (populaire pour les animations de chargement et l'UI organique). feGaussianBlur + feColorMatrix avec un multiplicateur alpha élevé crée l'effet gooey en affûtant les bords flous. feTurbulence + feDisplacementMap crée des effets ondulés/distordus. Les filtres SVG sont puissants mais peuvent être gourmands en performance. Ils permettent des effets impossibles avec CSS seul : morphing liquide, déplacement, éclairage et compositing personnalisé.
<!-- Define SVG filter -->
<svg style="display:none">
<filter id="gooey">
<feGaussianBlur in="SourceGraphic" stdDeviation="10" />
<feColorMatrix values="
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 20 -10" />
</filter>
</svg>
<!-- Apply via CSS -->
.gooey-container {
filter: url(#gooey);
}
<!-- Displacement map for wavy text -->
<filter id="wavy">
<feTurbulence baseFrequency="0.02" numOctaves="3" />
<feDisplacementMap in="SourceGraphic" scale="10" />
</filter>Animations de Filtres
Les filtres peuvent être animés et transitionnés en douceur. L'effet pulse-glow combine brightness et drop-shadow pour une lueur néon. Le grayscale-vers-couleur au survol est une interaction classique de galerie. Les transitions de filtres sont accélérées par GPU et plus performantes que l'animation de box-shadow ou background-color. Cependant, animer blur ou des filtres complexes peut être coûteux — testez sur mobile. Le hue-rotate piloté par défilement est un effet amusant mais peut causer des problèmes de performance sur les longues pages ; utilisez will-change: filter pour suggérer au navigateur l'optimisation.
@keyframes pulse-glow {
0%, 100% {
filter: brightness(1) drop-shadow(0 0 5px #3498db);
}
50% {
filter: brightness(1.3) drop-shadow(0 0 20px #3498db);
}
}
.glow-button {
animation: pulse-glow 2s ease-in-out infinite;
}
/* Hover filter transition */
.gallery img {
filter: grayscale(100%);
transition: filter 0.3s ease;
}
.gallery img:hover {
filter: grayscale(0%);
}
/* Color shift on scroll (with JS) */
window.addEventListener("scroll", () => {
const hue = window.scrollY * 0.5;
document.body.style.filter = `hue-rotate(${hue}deg)`;
});mix-blend-mode & background-blend-mode
mix-blend-mode détermine comment les pixels d'un élément se mélangent avec le contenu derrière lui. multiply assombrit (bon pour les ombres et filigranes) ; screen éclaircit (bon pour les lueurs) ; difference crée des effets psychédéliques ; overlay combine multiply et screen pour le contraste. background-blend-mode mélange plusieurs couches d'arrière-plan (images et gradients) sur le même élément. Les modes de fusion sont essentiels pour le compositing créatif, les effets duotone et les superpositions texte-sur-image. isolation: isolate crée un nouveau contexte de fusion pour contenir les effets de blend.
/* mix-blend-mode: how element blends with backdrop */
.overlay {
mix-blend-mode: multiply; /* darken */
}
.overlay-screen {
mix-blend-mode: screen; /* lighten */
}
.overlay-difference {
mix-blend-mode: difference; /* invert */
}
/* Common blend modes: multiply, screen, overlay,
darken, lighten, color-dodge, color-burn,
hard-light, soft-light, difference, exclusion,
hue, saturation, color, luminosity */
/* background-blend-mode: blend background layers */
.gradient-texture {
background-image: url(texture.png),
linear-gradient(45deg, red, blue);
background-blend-mode: multiply;
}Container Queries
Bases des Container Queries
Les container queries permettent aux composants de répondre à la taille de leur conteneur plutôt qu'au viewport. container-type: inline-size fait de l'élément un conteneur de requête basé sur sa dimension inline (largeur). La règle @container applique des styles quand le conteneur respecte la condition. C'est révolutionnaire pour le design basé sur les composants — un composant carte s'adapte qu'il soit dans une barre latérale ou une zone principale pleine largeur, indépendamment de la taille d'écran. Cela résout la limitation fondamentale des media queries, qui ne répondent qu'à la taille du viewport.
/* Define a container */
.card-container {
container-type: inline-size;
/* or: container-type: size; (both dimensions) */
}
/* Query the container's size */
@container (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 1fr 2fr;
}
}
@container (max-width: 399px) {
.card {
display: flex;
flex-direction: column;
}
}Conteneurs Nommés
Les conteneurs nommés permettent de cibler des conteneurs spécifiques quand plusieurs sont imbriqués. container-name donne au conteneur une étiquette ; @container name (condition) interroge uniquement ce conteneur. Cela évite les conflits quand les composants sont imbriqués avec différents contextes de conteneur. Le raccourci container combine nom et type : container: panel / inline-size. Les conteneurs nommés sont essentiels pour les dispositions complexes où plusieurs container queries indépendants coexistent. Sans noms, @container interroge le conteneur ancêtre le plus proche.
/* Name a container for specific queries */
.sidebar {
container-type: inline-size;
container-name: sidebar;
}
.main-content {
container-type: inline-size;
container-name: main;
}
/* Query specific container by name */
@container sidebar (min-width: 300px) {
.widget { display: grid; grid-template-columns: 1fr 1fr; }
}
@container main (min-width: 600px) {
.article { columns: 2; }
}
/* Shorthand: container: name / type */
.panel {
container: panel / inline-size;
}Unités de Container Query
Les unités de container query (cqw, cqh, cqmin, cqmax) sont comme les unités viewport (vw, vh) mais relatives au conteneur de requête au lieu du viewport. 1cqw = 1% de la largeur du conteneur. Cela permet une typographie et un espacement véritablement responsives au composant — le texte évolue avec la largeur du composant, pas l'écran. Combiné avec clamp(), vous obtenez une typographie fluide qui s'adapte à la taille du conteneur avec des bornes min/max. C'est idéal pour les design systems où les composants doivent fonctionner dans divers contextes de disposition. Note : cqh/cqmin/cqmax nécessitent container-type: size (les deux dimensions).
.card {
container-type: inline-size;
}
.card-title {
/* cqw: 1% of container width */
font-size: 5cqw;
/* cqh: 1% of container height (needs size type) */
padding: 2cqh;
/* cqmin: 1% of smaller container dimension */
margin: 2cqmin;
/* cqmax: 1% of larger container dimension */
border-radius: 1cqmax;
}
/* Fluid typography that responds to container */
.headline {
font-size: clamp(1rem, 8cqw, 3rem);
}Container Style Queries
Les container style queries (expérimental, Chromium uniquement en 2025) permettent d'interroger les valeurs de propriétés personnalisées sur un conteneur, pas seulement les dimensions. Cela permet un rendu conditionnel basé sur le style : un composant peut changer d'apparence selon une variable --theme définie sur son conteneur. container-type: style (ou aucun container-type nécessaire pour les style queries) active cela. C'est puissant pour le theming — définissez une variable sur un parent et tous les enfants s'adaptent. Le support complet navigateur est encore en attente ; utilisez avec amélioration progressive ou des vérifications @supports.
/* Query custom property values on container */
.card-wrapper {
container-type: style;
container-name: card;
}
@container card style(--theme: dark) {
.card {
background: #1a1a1a;
color: #fff;
}
}
@container card style(--theme: light) {
.card {
background: #fff;
color: #333;
}
}
/* Set the theme variable */
<div class="card-wrapper" style="--theme: dark">
<div class="card">...</div>
</div>Pattern de Composant Responsive
Ce pattern crée un composant véritablement réutilisable qui s'adapte à son placement. La carte produit montre une disposition verticale dans les conteneurs étroits, horizontale en moyen, et une grille 3 colonnes en large. Le même composant fonctionne dans une barre latérale (étroit), une grille (moyen) ou un hero (large) sans aucune logique conditionnelle basée sur les props. C'est le cas d'usage killer des container queries — des composants véritablement indépendants du contexte. Combiné avec les unités de container query pour la typographie, vous obtenez des composants entièrement auto-adaptatifs.
/* Component that adapts to any container */
.product-card {
container-type: inline-size;
container-name: product;
}
.product-card .layout {
display: flex;
flex-direction: column;
gap: 1rem;
}
/* Medium container: horizontal layout */
@container product (min-width: 350px) {
.product-card .layout {
flex-direction: row;
}
.product-card .image {
width: 40%;
}
}
/* Large container: full feature layout */
@container product (min-width: 600px) {
.product-card .layout {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
}
.product-card .actions {
display: flex;
flex-direction: column;
}
}Scroll Snap & Animations Pilotées par Défilement
Bases du Scroll Snap
Scroll snap crée un défilement magnétique qui aligne les éléments sur des points d'ancrage. scroll-snap-type: x/y définit l'axe ; mandatory force l'ancrage (atterrit toujours sur un point) ; proximity ancre seulement quand proche. scroll-snap-align: start/center/end définit où l'enfant s'ancre dans le conteneur. Les sections pleine page (comme des diapositives de présentation) utilisent y mandatory avec des sections 100vh. Les carrousels horizontaux utilisent x mandatory. Testez toujours sur appareils tactiles — l'ancrage mandatory peut sembler restrictif si le contenu est plus haut que le viewport. Utilisez proximity pour un comportement plus indulgent.
/* Container with scroll snapping */
.gallery {
scroll-snap-type: x mandatory;
overflow-x: auto;
display: flex;
gap: 1rem;
}
/* Children snap to positions */
.gallery section {
scroll-snap-align: start;
flex: 0 0 100%;
height: 300px;
}
/* Vertical snapping */
.full-page {
scroll-snap-type: y mandatory;
height: 100vh;
overflow-y: scroll;
}
.full-page section {
scroll-snap-align: start;
height: 100vh;
}Scroll Snap avec Padding
scroll-padding décale les points d'ancrage du bord du conteneur — utile quand vous avez des en-têtes fixes ou voulez une marge autour des éléments ancrés. scroll-snap-stop: always empêche le défilement rapide de sauter plusieurs éléments (force l'ancrage un à la fois). scroll-snap-align: center ancre les éléments au centre du conteneur, créant un effet cover-flow. Ces propriétés offrent un contrôle fin sur le comportement d'ancrage. Pour les carrousels d'images, combinez avec scroll-behavior: smooth pour des transitions animées entre les ancres.
.carousel {
scroll-snap-type: x mandatory;
scroll-padding: 0 20px; /* offset snap points */
overflow-x: auto;
display: flex;
gap: 1rem;
padding: 0 20px;
}
.carousel .item {
scroll-snap-align: start;
scroll-snap-stop: always; /* don't skip items */
flex: 0 0 80%;
}
/* Center-aligned snapping */
.carousel-center .item {
scroll-snap-align: center;
flex: 0 0 60%;
}Animations Pilotées par Défilement (animation-timeline)
Les animations pilotées par défilement (CSS uniquement, pas de JS !) lient les animations à la position de défilement. animation-timeline: scroll() lie l'animation à la progression du défilement de page (0% en haut, 100% en bas). animation-timeline: view() la lie à l'entrée/sortie de l'élément dans le viewport. animation-range définit quand l'animation commence/finit par rapport au défilement (entry, exit, cover, contain). Cela permet des barres de progression de défilement, des révélations au défilement et des effets parallaxe sans JavaScript ni écouteurs d'événements de défilement. Supporté dans Chrome 115+, amélioration progressive recommandée pour les autres navigateurs.
/* Animate as user scrolls */
@keyframes fade-in {
from { opacity: 0; transform: translateY(50px); }
to { opacity: 1; transform: translateY(0); }
}
.reveal {
animation: fade-in linear;
animation-timeline: view();
animation-range: entry 0% cover 40%;
}
/* Progress bar based on scroll position */
.progress-bar {
position: fixed;
top: 0; left: 0;
height: 4px;
background: #3498db;
width: 100%;
transform-origin: left;
animation: grow linear;
animation-timeline: scroll();
}
@keyframes grow {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}Plages de View Timeline
Les plages de view timeline contrôlent exactement quand l'animation se produit. 'entry' est quand l'élément entre dans le viewport ; 'exit' quand il quitte ; 'cover' s'étend du début d'entry à la fin d'exit ; 'contain' est quand l'élément est entièrement visible. Les pourcentages affinent dans chaque plage. animation-range: entry 10% entry 90% signifie que l'animation va de 10% dans entry à 90% dans entry. Pour les en-têtes sticky, scroll() avec une plage en pixels (0 200px) anime selon la distance de défilement absolue. Cela remplace les gestionnaires de défilement JavaScript complexes par du CSS déclaratif.
/* Element animates as it enters viewport */
@keyframes slide-up {
from { opacity: 0; transform: translateY(100px); }
to { opacity: 1; transform: translateY(0); }
}
.section {
animation: slide-up linear both;
animation-timeline: view();
/* Ranges: entry, exit, cover, contain */
animation-range: entry 10% entry 90%;
}
/* Sticky header that shrinks on scroll */
.header {
position: sticky;
top: 0;
animation: shrink linear both;
animation-timeline: scroll();
animation-range: 0 200px;
}
@keyframes shrink {
to { padding: 0.5rem 1rem; font-size: 0.9em; }
}scroll-behavior & smooth scroll
scroll-behavior: smooth sur html (ou tout conteneur de défilement) fait que la navigation par liens d'ancrage et scrollIntoView() s'animent en douceur au lieu de sauter. C'est un remplacement en une ligne des bibliothèques JavaScript de défilement fluide. Respectez toujours prefers-reduced-motion — certains utilisateurs souffrent du mal des transports, donc désactivez le défilement fluide pour eux. Le scroll-snap-type: proximity (vs mandatory) se combine bien avec le défilement fluide pour un ressenti naturel. scrollIntoView avec block: 'start'/'center'/'end' contrôle l'alignement vertical de la cible.
/* Smooth scrolling for anchor links */
html {
scroll-behavior: smooth;
}
/* With scroll snap */
html {
scroll-behavior: smooth;
scroll-snap-type: y proximity;
}
/* Target specific elements */
.container {
scroll-behavior: smooth;
overflow-y: auto;
}
/* JavaScript: scroll to element */
<script>
document.querySelector(".section-3")
.scrollIntoView({ behavior: "smooth", block: "start" });
/* Scroll to top */
window.scrollTo({ top: 0, behavior: "smooth" });
</script>
/* Respect reduced motion */
@media (prefers-reduced-motion: reduce) {
html { scroll-behavior: auto; }
}Compteurs CSS
Compteur de Base
Les compteurs CSS numérotent automatiquement les éléments sans JavaScript. counter-reset initialise un compteur (sur le parent ou tout ancêtre). counter-increment l'incrémente (généralement sur l'élément numéroté). counter(name) affiche la valeur actuelle dans content. Le compteur gère automatiquement la numérotation dans tout le document. C'est idéal pour numéroter les titres, éléments de liste, figures ou tout contenu séquentiel. Les compteurs sont limités à l'élément où ils sont réinitialisés et à ses descendants.
/* Initialize counter on parent */
body {
counter-reset: section;
}
/* Increment and display */
h2::before {
counter-increment: section;
content: "Section " counter(section) ": ";
color: #3498db;
font-weight: bold;
}
/* Result: Section 1: Introduction, Section 2: Methods... */Compteurs Imbriqués
Les compteurs imbriqués créent une numérotation hiérarchique (1.1, 1.2, 2.1, etc.). Réinitialisez le sous-compteur sur le titre parent (counter-reset: section sur h2). Chaque h2 commence un nouveau chapitre et réinitialise le compteur de section. Chaque h3 incrémente le compteur de section dans le chapitre courant. La propriété content combine plusieurs appels counter() avec des séparateurs. Cela reflète la façon dont les livres et documents techniques sont numérotés. Les compteurs se propagent naturellement selon la structure DOM et les points de réinitialisation.
body {
counter-reset: chapter;
}
h2 {
counter-reset: section;
counter-increment: chapter;
}
h2::before {
content: "Chapter " counter(chapter) ". ";
}
h3 {
counter-increment: section;
}
h3::before {
content: counter(chapter) "." counter(section) " ";
}
/* Result: Chapter 1. / 1.1 / 1.2 / Chapter 2. / 2.1 ... */Styles de Compteur
counter() accepte un argument de style : decimal (par défaut), decimal-leading-zero (01, 02), lower/upper-alpha (a/b ou A/B), lower/upper-roman (i/ii ou I/II). @counter-style définit des styles de compteur personnalisés avec des symboles cycliques, des systèmes additifs ou une notation symbolique. system: cyclic répète les symboles ; system: additive crée des systèmes de type chiffres romains. Les styles de compteur personnalisés sont puissants pour les listes internationalisées, les puces personnalisées ou la numérotation décorative. Le support navigateur de @counter-style est bon dans les navigateurs modernes.
/* Different number styles */
ol {
counter-reset: item;
list-style: none;
}
li::before {
counter-increment: item;
/* decimal, decimal-leading-zero, lower-alpha,
upper-alpha, lower-roman, upper-roman */
content: counter(item, upper-roman) ". ";
}
/* Leading zeros: 01, 02, 03... */
li::before {
content: counter(item, decimal-leading-zero) ". ";
}
/* Custom @counter-style */
@counter-style thumbs {
system: cyclic;
symbols: "👍" "👎";
suffix: " ";
}
.thumbs-list { list-style-type: thumbs; }Fonction counters() (Imbriquée)
La fonction counters() (pluriel) retourne le chemin complet du compteur comme une chaîne, avec les niveaux séparés par le délimiteur spécifié. Cela gère automatiquement les portées de compteurs imbriquées — chaque ol imbriqué crée une nouvelle portée de compteur. counters(nested, '.') produit 1, 1.1, 1.1.1 pour les listes profondément imbriquées. C'est différent de counter() qui ne montre que le niveau actuel. Utilisez counters() pour la numérotation de type plan des listes imbriquées, tables des matières ou menus hiérarchiques. La chaîne séparatrice peut être n'importe quel caractère (. , - > etc.).
/* counters() creates full path string */
ol {
counter-reset: nested;
list-style: none;
}
li::before {
counter-increment: nested;
/* counters() returns all levels separated by a string */
content: counters(nested, ".") " - ";
font-weight: bold;
}
/* For nested <ol> elements:
1 - Top level
1.1 - Nested
1.1.1 - Deeper
2 - Top level again
*/Compteur pour Figures & Tableaux
Les compteurs sont parfaits pour numéroter automatiquement les figures, tableaux et équations dans la documentation. Réinitialisez par chapitre (counter-reset sur h2) pour que la numérotation recommence à chaque chapitre. Le pseudo-élément ::before sur figcaption/caption préfixe le numéro. Cela assure une numérotation cohérente et automatique qui se met à jour quand le contenu est réorganisé. Pour les références croisées (« voir Figure 3 »), les compteurs CSS ne peuvent pas aider directement — vous auriez besoin de JS ou d'ancres HTML. Mais pour la numérotation d'affichage, c'est une solution propre et sans maintenance.
body {
counter-reset: figure table;
}
figure figcaption::before {
counter-increment: figure;
content: "Figure " counter(figure) ": ";
font-weight: bold;
color: #2c3e50;
}
table caption::before {
counter-increment: table;
content: "Table " counter(table) ": ";
font-weight: bold;
color: #2c3e50;
}
/* Reset figure counter per chapter */
h2 {
counter-reset: figure;
}Styles d'Impression
Bases de @media print
@media print applique des styles uniquement à l'impression. Masquez la navigation, les publicités, les barres latérales et les éléments interactifs qui n'ont pas de sens sur papier. Utilisez !important pour remplacer les styles inline. print-color-adjust: exact force les navigateurs à imprimer les couleurs d'arrière-plan et les images (sinon elles sont supprimées pour économiser l'encre). Utilisez pt (points) pour les tailles de police d'impression, pas px ou rem. Définissez width à 100% et supprimez margins/padding pour une zone imprimable maximale. Testez toujours avec Aperçu avant impression (Ctrl+P).
@media print {
/* Hide non-essential elements */
nav, footer, .sidebar, .ads, .no-print {
display: none !important;
}
/* Ensure colors print */
* {
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
/* Set base font for print */
body {
font-size: 12pt;
color: #000;
background: #fff;
}
/* Expand content to full width */
.content {
width: 100%;
margin: 0;
padding: 0;
}
}Sauts de Page
Les propriétés de saut de page contrôlent où le contenu se divise entre les pages. break-before: page force une nouvelle page avant un élément (utilisez pour les chapitres). break-inside: avoid empêche de diviser les tableaux, figures ou blocs de code entre les pages. break-after: avoid-page garde un titre avec le contenu suivant. orphans et widows contrôlent les lignes minimales aux limites de page (orphans = bas, widows = haut). Les propriétés break-* sont le standard moderne ; page-break-* sont des alias legacy. Tous les navigateurs ne supportent pas toutes les propriétés également — testez minutieusement.
@media print {
/* Force page break before */
h1, h2 {
page-break-before: always;
break-before: page; /* modern syntax */
}
/* Avoid breaking inside */
table, figure, pre, blockquote {
page-break-inside: avoid;
break-inside: avoid;
}
/* Keep with next (heading stays with content) */
h2, h3, h4 {
page-break-after: avoid;
break-after: avoid-page;
}
/* Avoid orphan/widow lines */
p {
orphans: 3; /* min lines at bottom of page */
widows: 3; /* min lines at top of page */
}
}Règle @page
@page configure la page imprimée elle-même : size (A4, letter, landscape ou dimensions personnalisées) et margins. Les pseudo-classes :first, :left, :right stylisent des pages spécifiques — essentiel pour l'impression de livres avec des marges différentes pour la reliure. Les pages nommées (@page cover) permettent à différentes sections d'avoir différentes configurations de page ; assignez avec la propriété page sur un élément. Les marges de page créent la zone imprimable. Note : le support @page varie selon le navigateur — Chrome supporte bien size et margins ; Firefox a un support limité. Pour l'impression professionnelle, considérez des outils dédiés comme Prince XML.
/* Set page size and margins */
@page {
size: A4; /* or: letter, landscape, 8.5in 11in */
margin: 2cm;
}
/* First page different */
@page :first {
margin-top: 5cm; /* extra space for letterhead */
}
/* Left and right pages (for binding) */
@page :left { margin-left: 3cm; margin-right: 1.5cm; }
@page :right { margin-left: 1.5cm; margin-right: 3cm; }
/* Named pages for different sections */
@page cover {
margin: 0;
}
.cover-page {
page: cover;
}Liens Adaptés à l'Impression
Sur papier, les liens sont inutiles sans leurs URLs. La fonction attr(href) dans content affiche l'URL après chaque texte de lien. Excluez les liens d'ancrage internes (#) et les liens javascript:. De même, abbr[title]::after montre l'expansion complète des abréviations. Cela assure que les documents imprimés conservent l'information que les hyperliens fournissent à l'écran. Utilisez une police plus petite et atténuée pour les URLs afin de les distinguer du texte de corps. Pour les longues URLs, considérez word-break: break-all pour éviter le débordement.
@media print {
/* Show URL after links */
a[href]::after {
content: " (" attr(href) ")";
font-size: 0.9em;
color: #555;
}
/* Don't show URL for internal links */
a[href^="#"]::after,
a[href^="javascript:"]::after {
content: "";
}
/* Abbreviations: show full title */
abbr[title]::after {
content: " (" attr(title) ")";
}
}En-tête & Pied de Page d'Impression
Les boîtes de marge @page (@top-center, @bottom-center, etc.) placent du contenu dans les marges de page — idéal pour les numéros de page, en-têtes et pieds de page. counter(page) est la page actuelle ; counter(pages) est le total. Cependant, le support navigateur est très limité (principalement Prince XML et WeasyPrint ; Chrome/Firefox ne supportent pas les boîtes de marge). Le repli utilise des éléments position: fixed qui se répètent sur chaque page imprimée dans certains navigateurs. Pour des en-têtes/pieds de page d'impression fiables entre navigateurs, la génération PDF côté serveur (Puppeteer, wkhtmltopdf) est souvent plus fiable que CSS @page.
@page {
margin: 2cm 3cm;
/* Page counter in footer */
@bottom-center {
content: "Page " counter(page) " of " counter(pages);
font-size: 10pt;
color: #666;
}
/* Document title in header */
@top-center {
content: "My Document Title";
font-size: 10pt;
color: #666;
}
}
/* Note: @page margin boxes have limited browser
support. Chrome doesn't support them.
Use fixed-position elements as fallback: */
@media print {
.print-footer {
position: fixed;
bottom: 0;
width: 100%;
text-align: center;
font-size: 10pt;
}
}Mode Sombre & Schémas de Couleur
prefers-color-scheme
prefers-color-scheme: dark détecte la préférence de mode sombre OS/navigateur de l'utilisateur. Définissez les variables de thème dans :root pour le mode clair, puis remplacez-les dans la media query sombre. Utiliser des variables CSS signifie que vous changez seulement les valeurs des variables — tous les composants se mettent à jour automatiquement. C'est l'approche standard pour le mode sombre. La media query supporte aussi 'light' et 'no-preference'. Testez en basculant le mode sombre OS ou en utilisant l'onglet Rendering de Chrome DevTools (Emulate CSS prefers-color-scheme).
/* Light mode (default) */
:root {
--bg: #ffffff;
--text: #1a1a1a;
--surface: #f5f5f5;
--border: #e0e0e0;
--accent: #3498db;
}
/* Dark mode */
@media (prefers-color-scheme: dark) {
:root {
--bg: #1a1a1a;
--text: #e0e0e0;
--surface: #2a2a2a;
--border: #404040;
--accent: #5dade2;
}
}
body {
background: var(--bg);
color: var(--text);
}Bascule de Thème Manuelle
Pour une bascule de thème manuelle, utilisez un attribut data-theme sur <html> qui remplace la préférence système. Stockez le choix de l'utilisateur dans localStorage pour qu'il persiste. Au chargement de la page, vérifiez localStorage avant le rendu pour éviter un flash de mauvais thème (FOUC). color-scheme: light dark indique au navigateur de rendre les éléments UI natifs (barres de défilement, contrôles de formulaire) dans le schéma approprié. Pour la meilleure UX, par défaut à la préférence système quand aucun choix enregistré n'existe : vérifiez matchMedia('(prefers-color-scheme: dark)') comme repli.
/* Default to system preference, allow override */
:root {
color-scheme: light dark;
}
/* Manual dark mode via data attribute */
[data-theme="dark"] {
--bg: #1a1a1a;
--text: #e0e0e0;
}
[data-theme="light"] {
--bg: #ffffff;
--text: #1a1a1a;
}
/* Toggle button */
<button onclick="toggleTheme()">Toggle Theme</button>
<script>
function toggleTheme() {
const current = document.documentElement.dataset.theme;
const next = current === "dark" ? "light" : "dark";
document.documentElement.dataset.theme = next;
localStorage.setItem("theme", next);
}
// Load saved preference
const saved = localStorage.getItem("theme");
if (saved) document.documentElement.dataset.theme = saved;
</script>Propriété color-scheme
La propriété color-scheme indique au navigateur quels schémas de couleur la page supporte, affectant les éléments UI natifs : barres de défilement, contrôles de formulaire (inputs, boutons, dropdowns), couleur d'arrière-plan/canvas par défaut et la couleur ::placeholder. Sans elle, les contrôles de formulaire peuvent apparaître clairs même en mode sombre (décalage jarring). Définissez color-scheme: light dark sur :root pour laisser les éléments natifs s'adapter automatiquement. C'est un correctif en une ligne qui améliore considérablement le polish du mode sombre. C'est séparé de votre theming de variables CSS — cela n'affecte que le rendu natif du navigateur.
:root {
/* Tell browser this page supports both schemes */
color-scheme: light dark;
}
/* Force light only */
.light-only {
color-scheme: light;
}
/* Force dark only */
.dark-only {
color-scheme: dark;
}
/* This affects native UI: scrollbars, form controls,
default colors (canvas, text), and form elements */
input, textarea, select {
/* Will use dark form controls in dark mode */
color-scheme: dark;
}Images & Médias en Mode Sombre
Les images nécessitent un traitement spécial en mode sombre. Les diagrammes à fond blanc peuvent être inversés avec filter: invert(1) hue-rotate(180deg) — le hue-rotate empêche la distorsion des couleurs. Les photos de personnes ne doivent jamais être inversées. Réduisez légèrement la brightness pour moins de fatigue oculaire. Pour les logos et icônes, utilisez <picture> avec des sources media-query pour servir des versions optimisées pour le sombre. Les SVG avec currentColor s'adaptent automatiquement. Pour les images d'arrière-plan, fournissez des alternatives en mode sombre via les media queries. Testez toujours les images dans les deux modes pour la lisibilité.
@media (prefers-color-scheme: dark) {
/* Invert images that are essentially white-background */
img[src*="logo"],
img[src*="diagram"] {
filter: invert(1) hue-rotate(180deg);
}
/* Reduce brightness of photos */
img.photo {
filter: brightness(0.85);
}
/* Don't invert photos with people */
img[src*="photo"]:not(.invertable) {
filter: none;
}
}
/* Use dark-mode-friendly SVG */
<picture>
<source srcset="logo-dark.svg"
media="(prefers-color-scheme: dark)">
<img src="logo-light.svg" alt="Logo">
</picture>Transition de Thème Fluide
Ajouter des transitions de couleur à tous les éléments crée une animation de bascule de thème fluide. Cependant, cela peut causer un flash de couleurs animées au chargement initial de la page. La solution : ajoutez une classe .no-transition à <html> pendant les bascules de thème et au chargement initial, puis retirez-la après une frame. Respectez toujours prefers-reduced-motion pour désactiver les transitions pour les utilisateurs qui demandent un mouvement réduit. Soyez sélectif — transitionner toutes les propriétés peut impacter la performance. Ne transitionnez que les propriétés liées à la couleur (background-color, color, border-color, box-shadow).
/* Transition colors when theme changes */
* {
transition: background-color 0.3s ease,
color 0.3s ease,
border-color 0.3s ease;
}
/* But not during initial load (prevent flash) */
.no-transition * {
transition: none !important;
}
<script>
// Disable transitions during theme switch
function toggleTheme() {
document.documentElement.classList.add("no-transition");
document.documentElement.dataset.theme = newTheme;
// Re-enable after switch
requestAnimationFrame(() => {
document.documentElement.classList.remove("no-transition");
});
}
</script>
/* Respect reduced motion */
@media (prefers-reduced-motion: reduce) {
* { transition: none !important; }
}Fonctions CSS Approfondi
clamp(), min(), max()
clamp(min, preferred, max) est le saint Graal de la typographie et de l'espacement fluides — il évolue avec la valeur préférée mais ne dépasse jamais les bornes min/max. min() choisit la plus petite valeur (idéal pour les max-width responsives). max() choisit la plus grande valeur (idéal pour les tailles minimales). Celles-ci éliminent de nombreuses media queries en fournissant une mise à l'échelle fluide continue. La valeur préférée dans clamp utilise typiquement des unités viewport (vw, vh) ou des unités conteneur (cqw). C'est l'approche moderne du design responsive sans breakpoints.
/* clamp(min, preferred, max) */
h1 {
font-size: clamp(1.5rem, 5vw, 3rem);
/* Never smaller than 1.5rem, never larger than 3rem,
preferred is 5vw */
}
/* min(): use the smaller value */
.container {
width: min(100% - 2rem, 1200px);
/* Full width minus padding, but max 1200px */
}
/* max(): use the larger value */
.hero {
font-size: max(2rem, 4vw);
/* At least 2rem, grows with viewport */
}
/* Combining for responsive padding */
.card {
padding: clamp(1rem, 3vw, 2rem);
}calc() Avancé
calc() effectue des calculs avec des unités mixtes (px, %, em, vw, etc.). L'addition et la soustraction nécessitent des espaces autour de l'opérateur (calc(100% - 20px), pas calc(100%-20px)). La multiplication et la division ne fonctionnent qu'avec des nombres, pas des longueurs (calc(10px * 2) est valide ; calc(10px * 10px) ne l'est pas). calc() peut être imbriqué mais les parenthèses fonctionnent aussi. Combiné avec les variables CSS, calc() permet des design systems dynamiques et calculés. C'est essentiel pour les dispositions responsives qui combinent des dimensions fixes et fluides.
/* Mixed units */
.sidebar {
width: calc(100% - 250px); /* full width minus fixed sidebar */
height: calc(100vh - 60px); /* viewport minus header */
}
/* Nested calc */
.element {
margin: calc(calc(100% - 50px) / 2);
/* Simplified: */
margin: calc((100% - 50px) / 2);
}
/* With CSS variables */
:root { --gap: 20px; }
.grid {
gap: calc(var(--gap) * 2);
}
/* Math operations: + - * / */
.padding {
padding: calc(1rem + 2px);
width: calc(50% - 10px);
}Fonction attr()
attr() récupère les valeurs d'attributs HTML, le plus couramment utilisé dans content pour les pseudo-éléments. C'est la base des tooltips CSS uniquement (attribut data-tooltip → content ::after). attr() fonctionne de façon fiable seulement dans la propriété content. Utiliser attr() pour d'autres propriétés (width, color, etc.) avec conversion de type (attr(data-size px)) fait partie de CSS Values Level 5 mais a un support navigateur minimal. Pour l'instant, utilisez des variables CSS pour les valeurs dynamiques depuis HTML : définissez style='--size: 100px' et utilisez var(--size).
/* Display attribute values */
a[href]::after {
content: attr(href);
}
/* data attributes for tooltips */
.tooltip::after {
content: attr(data-tooltip);
display: none;
position: absolute;
}
.tooltip:hover::after {
display: block;
}
/* HTML: <div class="tooltip" data-tooltip="Help text">?</div> */
/* Note: attr() for non-content properties is experimental */
/* This doesn't work widely yet: */
/* .box { width: attr(data-width px); } */var() avec Replis
var() accepte un repli comme second argument, utilisé quand la variable n'est pas définie. Les replis peuvent se chaîner : var(--a, var(--b, var(--c, default))). Cela permet l'amélioration progressive et le theming multi-niveaux. Une valeur de variable vide (--defined: ;) est toujours « définie », donc le repli ne se déclenchera pas — cela permet des patterns CSS conditionnels. Les replis peuvent inclure n'importe quelle valeur CSS valide, y compris calc() et d'autres fonctions. Utilisez des replis pour les variables de thème optionnelles qui pourraient ne pas être définies dans tous les contextes.
/* Single fallback */
color: var(--text-color, #333);
/* Chained fallbacks */
color: var(--text, var(--default-text, black));
/* Fallback in shorthand */
background: var(--bg, white) url(image.png);
/* Fallback with calc */
width: calc(100% - var(--sidebar, 250px));
/* Check if variable is set */
:root {
--defined: ; /* empty space = valid value */
}
.conditional {
--use-default: var(--defined, initial);
/* If --defined is empty, --use-default = initial */
}Fonctions gradient
Les gradients CSS créent des transitions en douceur entre les couleurs sans images. linear-gradient (direction + couleurs), radial-gradient (du centre vers l'extérieur) et conic-gradient (rotation autour d'un point) sont les trois types. Les arrêts durs (même pourcentage pour deux couleurs) créent des bandes nettes. repeating-linear-gradient crée des patterns comme des rayures. Les gradients peuvent être superposés avec plusieurs arrière-plans (séparés par virgules, premier = couche supérieure). Les gradients coniques permettent des camemberts et roues chromatiques en CSS pur. Les gradients sont indépendants de la résolution et plus performants que les fichiers image.
/* Linear gradient */
.bg { background: linear-gradient(45deg, #3498db, #e74c3c); }
.bg2 { background: linear-gradient(to right, red, orange, yellow); }
/* Radial gradient */
.radial { background: radial-gradient(circle, white, blue); }
.radial2 { background: radial-gradient(circle at top left, #fff, #000); }
/* Conic gradient */
.pie { background: conic-gradient(red 0% 30%, blue 30% 70%, green 70% 100%); }
/* Repeating gradients */
.stripes { background: repeating-linear-gradient(45deg, #ccc 0 10px, #fff 10px 20px); }
/* Hard color stops (sharp edges) */
.hard { background: linear-gradient(to right, #000 50%, #fff 50%); }
/* Multiple backgrounds */
.multi {
background:
linear-gradient(rgba(0,0,0,0.5), transparent),
url(photo.jpg);
}Variables CSS
Définition & Utilisation des Variables
Les propriétés personnalisées CSS (variables) sont définies avec --name et utilisées avec var(). Déclarez-les sur :root pour un accès global. Contrairement aux variables Sass, elles sont live — modifier une variable via JavaScript met à jour instantanément chaque élément qui l'utilise.
:root {
--primary: #3498db;
--spacing: 16px;
--radius: 8px;
}
.button {
background: var(--primary);
padding: var(--spacing);
border-radius: var(--radius);
}Valeurs de Repli
var() accepte un second argument comme repli quand la variable est indéfinie. Les replis peuvent s'imbriquer, vous permettant de chaîner les valeurs par défaut. Pour les navigateurs qui ne supportent pas les propriétés personnalisées, déclarez une valeur normale d'abord, puis remplacez avec var().
.box {
color: var(--brand, #333);
background: var(--bg, var(--default-bg, white));
}
/* Provide fallback for older browsers */
.element {
color: #333;
color: var(--text-color, #333);
}Interaction JavaScript
JavaScript lit les variables via getComputedStyle().getPropertyValue() et les définit avec setProperty(). Cela rend le theming à l'exécution trivial — basculez quelques variables pour restyler toute l'application.
// Read a variable
const color = getComputedStyle(document.documentElement)
.getPropertyValue('--primary');
// Set a variable on an element
document.documentElement.style.setProperty('--primary', '#e74c3c');
// Toggle a theme
document.documentElement.setAttribute('data-theme', 'dark');Portée & Héritage
Les propriétés personnalisées héritent, donc une variable définie sur :root se propage à chaque élément. La redéfinir sur .card la remplace pour ce sous-arbre uniquement. Cette portée permet le theming au niveau du composant sans guerres de spécificité.
:root { --size: 16px; }
.card {
--size: 20px; /* Overrides only within .card */
font-size: var(--size);
}
.card .text { font-size: var(--size); } /* 20px */
.other { font-size: var(--size); } /* 16px */Variables Responsives
Redéfinissez les variables dans les media queries pour faire répondre toute la disposition aux breakpoints sans réécrire les règles. Changez une variable et chaque élément qui l'utilise s'adapte — bien plus propre que de remplacer chaque propriété individuellement.
:root {
--container-width: 1200px;
--font-size: 18px;
}
@media (max-width: 768px) {
:root {
--container-width: 100%;
--font-size: 16px;
}
}
.container { max-width: var(--container-width); }
body { font-size: var(--font-size); }Animations & Keyframes
@keyframes & Raccourci Animation
@keyframes définit les états de début (from/0%) et de fin (to/100%) d'une animation. Le raccourci animation combine name, duration, timing-function, delay, iteration-count, direction, fill-mode et play-state. forwards conserve l'état final.
@keyframes slide-in {
from { transform: translateX(-100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
.element {
animation: slide-in 0.5s ease-out forwards;
}
/* Shorthand: name duration timing delay count direction fill-mode */
.bounce {
animation: bounce 1s cubic-bezier(0.68, -0.55, 0.27, 1.55) 0s infinite alternate;
}Transitions
Les transitions interpolent en douceur entre les valeurs de propriétés quand elles changent. Spécifiez quelles propriétés transitionnent et leur durée/timing. transition: all est pratique mais peut nuire à la performance — préférez lister des propriétés spécifiques.
.button {
background: blue;
transition: background 0.3s ease, transform 0.2s ease-out;
}
.button:hover {
background: darkblue;
transform: scale(1.05);
}
/* Transition all changed properties */
.card { transition: all 0.3s ease; }Fonctions de Timing
Les fonctions de timing contrôlent la courbe d'accélération. ease-out commence vite et ralentit (bon pour les entrées) ; ease-in commence lentement et accélère (bon pour les sorties). cubic-bezier vous permet de créer des courbes personnalisées. steps() crée un effet discret.
/* Built-in */
.ease-linear { transition: all 1s linear; }
.ease-out { transition: all 1s ease-out; }
/* Custom cubic-bezier(x1, y1, x2, y2) */
.custom { transition: all 1s cubic-bezier(0.68, -0.55, 0.27, 1.55); }
/* Steps */
.steps { transition: all 1s steps(5, end); }Événements d'Animation
JavaScript peut écouter animationstart, animationiteration (se déclenche à chaque boucle) et animationend. Contrôlez la lecture avec la propriété animation-play-state (paused/running). Combinez avec animationend pour chaîner les animations.
const el = document.querySelector('.animate');
el.addEventListener('animationstart', () => console.log('Started'));
el.addEventListener('animationiteration', () => console.log('Looped'));
el.addEventListener('animationend', () => console.log('Finished'));
// Pause and resume
el.style.animationPlayState = 'paused';
el.style.animationPlayState = 'running';Performance : transform & opacity
Animez uniquement transform et opacity pour une performance 60fps — ils s'exécutent sur le GPU sans déclencher de layout. Animer width, height, top ou margin force le recalcul de layout à chaque frame. Utilisez will-change avec parcimonie pour suggérer au navigateur.
/* GOOD: GPU-accelerated, cheap */
.fade { transition: opacity 0.3s; }
.move { transition: transform 0.3s; }
/* BAD: triggers layout/paint, expensive */
.resize { transition: width 0.3s, height 0.3s; }
/* Hint the browser to optimize */
.card { will-change: transform; }Transforms 3D
Transforms 2D
Les transforms 2D déplacent, font pivoter, redimensionnent et distordent les éléments sans affecter la disposition environnante. Les transforms sont composités sur le GPU, les rendant performantes pour l'animation. L'ordre compte : rotate puis translate se déplace le long de l'axe pivoté.
.box { transform: translate(50px, 20px); }
.box { transform: rotate(45deg); }
.box { transform: scale(1.5); }
.box { transform: skew(20deg, 10deg); }
/* Combined — order matters */
.combo { transform: translate(100px, 0) rotate(90deg) scale(1.2); }Transforms 3D & Perspective
Les transforms 3D ajoutent rotateX, rotateY, rotateZ, translateZ et scaleZ. perspective sur un parent donne à tous les enfants un point de fuite partagé — des valeurs plus basses exagèrent l'effet 3D. transform-style: preserve-3d maintient les éléments imbriqués en 3D.
.scene { perspective: 1000px; }
.card {
transform: rotateY(45deg);
transform-style: preserve-3d;
}
/* Perspective on the element itself */
.self { transform: perspective(800px) rotateX(30deg); }
/* Transform origin */
.pivot { transform-origin: top left; transform: rotate(45deg); }Effet de Carte Retournée
La carte retournée classique utilise preserve-3d sur un conteneur, avec des faces avant et arrière positionnées en absolu. backface-visibility: hidden cache le dos de chaque face. La face arrière est pré-pivotée de 180deg pour qu'elle s'affiche quand le conteneur se retourne.
.card { perspective: 1000px; }
.inner {
position: relative;
transform-style: preserve-3d;
transition: transform 0.6s;
}
.card:hover .inner { transform: rotateY(180deg); }
.front, .back {
position: absolute;
backface-visibility: hidden;
}
.back { transform: rotateY(180deg); }Cube avec 6 Faces
Un cube 3D est construit à partir de six faces, chacune translatée de 50px (la moitié de la largeur du cube) vers l'extérieur le long de son axe. preserve-3d maintient les faces positionnées dans l'espace 3D. Animez le transform du cube pour le faire pivoter.
.cube {
position: relative;
width: 100px; height: 100px;
transform-style: preserve-3d;
transform: rotateX(-20deg) rotateY(30deg);
}
.face { position: absolute; width: 100px; height: 100px; }
.front { transform: translateZ(50px); }
.back { transform: rotateY(180deg) translateZ(50px); }
.right { transform: rotateY(90deg) translateZ(50px); }
.left { transform: rotateY(-90deg) translateZ(50px); }
.top { transform: rotateX(90deg) translateZ(50px); }
.bottom { transform: rotateX(-90deg) translateZ(50px); }Matrix & Performance
matrix() et matrix3d() expriment n'importe quel transform comme une matrice unique — utile pour calculer les transforms en JavaScript. translateZ(0) ou will-change: transform forcent l'accélération GPU, améliorant la fluidité de l'animation. Évitez de surutiliser les layers.
/* matrix(a, b, c, d, e, f) encodes translate, rotate, scale, skew */
.transformed { transform: matrix(1, 0, 0, 1, 100, 50); }
/* 3D matrix */
.cube { transform: matrix3d(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1); }
/* Hardware acceleration hint */
.gpu { transform: translateZ(0); }CSS Grid Avancé
Zones de Modèle Grid
grid-template-areas nomme visuellement les cellules de la grille, rendant l'intention de disposition évidente. Chaque ligne entre guillemets représente une ligne de grille ; les noms identiques s'étendent sur les cellules. Les cellules vides utilisent un point (.). Les zones doivent former des rectangles — les formes en L sont invalides.
.layout {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
gap: 16px;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }minmax & auto-fit
repeat(auto-fit, minmax(200px, 1fr)) crée une grille responsive sans media queries : les colonnes font au moins 200px et s'étirent pour remplir la ligne. auto-fit réduit les pistes vides ; auto-fill les garde réservées.
.grid {
display: grid;
/* Columns auto-fit, each at least 200px, sharing leftover space */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
}
/* Fixed number that wraps */
.wrap {
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}Alignement Grid
L'alignement Grid fonctionne à deux niveaux : le conteneur (justify/align-items et justify/align-content) et l'élément (justify/align-self). justify-* contrôle l'axe inline, align-* l'axe block. place-items: center est un raccourci pour les deux.
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
justify-items: center;
align-items: center;
justify-content: space-between;
align-content: center;
}
.item {
justify-self: end;
align-self: start;
}Étendue & Placement par Ligne
Placez les éléments par numéro de ligne de grille (1 / 3 signifie de la ligne 1 à la ligne 3) ou par étendue (span 2). Les lignes négatives comptent depuis la fin (-1 est la dernière ligne). grid-column: 1 / -1 fait s'étendre un élément sur toute la largeur.
.grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
}
.header { grid-column: 1 / -1; } /* full width */
.sidebar { grid-column: 1 / 3; } /* columns 1-2 */
.main { grid-column: span 2; } /* span 2 columns */
.tall { grid-row: 1 / span 2; } /* span 2 rows */Subgrid
subgrid permet à une grille enfant d'hériter des définitions de piste parentes, pour que les colonnes ou lignes s'alignent parfaitement entre les grilles imbriquées. Sans subgrid, les grilles imbriquées définissent leurs propres pistes et peuvent se désaligner. Supporté dans tous les navigateurs modernes depuis 2023.
.card {
display: grid;
grid-template-rows: auto 1fr auto;
/* Inherit column tracks from parent */
grid-template-columns: subgrid;
grid-column: span 3;
}
.parent {
display: grid;
grid-template-columns: repeat(6, 1fr);
}Fonctions CSS
calc()
calc() effectue des calculs sur des unités mixtes (px, %, vw, em, rem). Entourez toujours + et - d'espaces (calc(100%-20px) échoue ; calc(100% - 20px) fonctionne). La multiplication et la division nécessitent qu'un côté soit un nombre sans unité.
.sidebar {
width: calc(100% - 250px);
padding: calc(16px + 2vw);
font-size: calc(14px + 0.5vw);
}
/* Nested calc */
.full { width: calc(calc(100% - 20px) / 2); }
/* With variables */
.box { margin: calc(var(--gap) * 2); }clamp()
clamp() borne une valeur entre un minimum et un maximum, avec une valeur préférée au milieu. C'est la façon la plus propre de construire une typographie et un espacement fluides — la valeur évolue mais ne descend jamais en dessous ou au-dessus des bornes.
/* clamp(MIN, PREFERRED, MAX) */
h1 {
font-size: clamp(1.5rem, 4vw, 3rem);
}
.sidebar {
width: clamp(200px, 25vw, 400px);
}
.padding {
padding: clamp(1rem, 2vw + 1rem, 2rem);
}min() & max()
min() retourne le plus petit argument ; max() retourne le plus grand. Contrairement à clamp (qui prend exactement trois valeurs), min/max acceptent n'importe quel nombre d'arguments. Utilisez min() pour plafonner une valeur et max() pour plancher une valeur.
/* Picks the smallest/largest of comma-separated values */
.box {
width: min(100% - 32px, 800px);
font-size: max(16px, 2vw);
}
/* With multiple units */
.responsive {
padding: min(5vw, 2rem);
margin: max(1rem, 3vw);
}var() avec Replis
Le second argument de var() est utilisé seulement quand la propriété personnalisée est indéfinie. Pour les valeurs invalides, la propriété revient à sa valeur héritée ou initiale. Imbriquez les appels var() pour chaîner les replis.
.button {
background: var(--btn-bg, #007bff);
color: var(--text, var(--default-text, black));
width: var(--width, 100%);
}color-mix() & fonctions de couleur
color-mix() mélange deux couleurs dans un espace colorimétrique spécifié (srgb, oklch, lab). C'est la façon moderne de dériver des teintes et nuances depuis une couleur de marque. La syntaxe de couleur relative (mot-clé from) vous permet d'ajuster des canaux individuels.
/* Mix two colors */
.muted { color: color-mix(in srgb, red 30%, blue); }
/* Adjust relative lightness */
.lighter { background: color-mix(in oklch, var(--brand) 70%, white); }
.darker { background: color-mix(in oklch, var(--brand) 70%, black); }
/* Relative color syntax (newest) */
.tint { background: oklch(from var(--brand) calc(l + 0.1) c h); }Animations Pilotées par Défilement
Bases d'animation-timeline
animation-timeline: scroll(root) lie une animation à la position de défilement de la page — au fur et à mesure que l'utilisateur défile, l'animation progresse. Aucun JavaScript nécessaire. C'est bien plus fluide que les écouteurs d'événements de défilement.
@keyframes grow {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
.progress-bar {
animation: grow linear;
animation-timeline: scroll(root);
transform-origin: left;
}Timeline view()
view() crée une timeline liée à un élément entrant et quittant le viewport. animation-range contrôle quelle portion de l'entrée déclenche l'animation. Parfait pour les effets de révélation au défilement sans IntersectionObserver.
@keyframes reveal {
from { opacity: 0; transform: translateY(40px); }
to { opacity: 1; transform: translateY(0); }
}
.card {
animation: reveal linear;
animation-timeline: view();
animation-range: entry 0% entry 100%;
}Barre de Progression Liée au Défilement
Une barre de progression fixe qui se remplit au fur et à mesure que vous défilez la page. animation-timeline: scroll(root) mappe le défilement de page à la plage d'animation 0-100%. transform-origin: 0 50% fait que la barre croît depuis la gauche.
body { min-height: 200vh; }
.progress {
position: fixed;
top: 0; left: 0;
height: 4px;
width: 100%;
background: linear-gradient(to right, #6366f1, #ec4899);
transform-origin: 0 50%;
animation: scale-x linear;
animation-timeline: scroll(root);
}
@keyframes scale-x {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}Timelines de Défilement Nommées
Quand vous devez lier une animation à un élément défilable spécifique (pas le root), définissez scroll-timeline-name sur le conteneur et référencez-le dans animation-timeline. scroll-timeline-axis choisit quel axe suivre (block/inline/x/y).
.scroll-container {
scroll-timeline-name: --cards;
scroll-timeline-axis: block;
overflow-y: scroll;
height: 400px;
}
.card {
animation: fade-in linear;
animation-timeline: --cards;
}
@keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}Ajustements de Plage de Vue
animation-range affine quand l'animation s'exécute par rapport à la visibilité de l'élément. cover 0% à cover 100% s'étend depuis l'entrée de l'élément jusqu'à sa sortie complète. contain 0% à 100% s'étend seulement quand il est entièrement à l'intérieur.
.image {
animation: parallax linear;
animation-timeline: view();
animation-range: cover 0% cover 100%;
}
@keyframes parallax {
from { transform: translateY(-20%); }
to { transform: translateY(20%); }
}
/* Only animate while in view */
.pulse {
animation: pulse 1s infinite;
animation-timeline: view();
animation-range: contain 0% contain 100%;
}Couches CSS
Définir @layer
@layer regroupe les styles dans des couches de cascade nommées. L'ordre dans la ligne de déclaration définit la priorité : les couches ultérieures gagnent sur les précédentes, indépendamment de la spécificité du sélecteur. Cela apporte un ordre prévisible aux grandes feuilles de style.
@layer reset, base, components, utilities;
@layer reset {
* { margin: 0; padding: 0; box-sizing: border-box; }
}
@layer base {
body { font-family: sans-serif; line-height: 1.6; }
}
@layer utilities {
.hidden { display: none !important; }
}Priorité des Couches
Dans les couches, les règles normales de spécificité s'appliquent. Mais entre les couches, les couches ultérieures gagnent toujours — une seule classe dans components bat un ID dans base. Les styles non couche prennent priorité sur tous les styles en couches.
@layer base, components;
@layer base {
/* Even though this is more specific, base loses */
div.button { color: black; }
}
@layer components {
.button { color: blue; } /* This wins */
}
/* Unlayered styles always beat layered styles */
.button { color: red; }Importer dans les Couches
@import ... layer(name) place une feuille de style entière dans une couche nommée. C'est essentiel pour dompter le CSS tiers : mettez Bootstrap dans une couche vendor, et vos styles personnalisés (dans une couche ultérieure ou non couche) gagneront toujours.
@import url("reset.css") layer(reset);
@import url("bootstrap.css") layer(vendor);
@layer reset, vendor, custom;
@layer custom {
.btn { background: hotpink; }
}Couches Imbriquées
Les couches peuvent s'imbriquer, créant une hiérarchie. framework.theme fait référence à la sous-couche theme à l'intérieur de framework. Les couches imbriquées suivent les mêmes règles de priorité : dans framework, theme bat base.
@layer framework {
@layer base, theme;
@layer base {
.btn { padding: 8px; }
}
@layer theme {
.btn { color: navy; }
}
}
/* Reference nested layer */
@layer framework.theme {
.btn { color: hotpink; }
}Logique Conditionnelle de Couche
Les blocs @layer peuvent s'imbriquer dans @media et @supports, pour que l'appartenance à une couche s'adapte aux conditions. Cela garde les styles spécifiques à une fonctionnalité organisés dans leur couche plutôt que de fuiter dans l'espace non couche.
@layer base, components;
@media (max-width: 600px) {
@layer components {
.nav { flex-direction: column; }
}
}
@supports (display: grid) {
@layer components {
.layout { display: grid; }
}
}Filtres de Fond
Bases de backdrop-filter
backdrop-filter applique un filtre au contenu derrière un élément, créant des effets de verre dépoli. Incluez toujours le préfixe -webkit- pour Safari. Combinez avec un arrière-plan semi-transparent pour que le flou soit visible.
.glass {
background: rgba(255, 255, 255, 0.2);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 12px;
}Filtres Multiples
Chaînez plusieurs filtres séparés par des espaces : blur, brightness, contrast, grayscale, hue-rotate, invert, opacity, saturate, sepia. Chacun s'applique au fond. Associez avec un arrière-plan teinté pour orienter l'ambiance.
.vibrant {
backdrop-filter: blur(8px) saturate(180%) brightness(1.1);
}
.dark-glass {
background: rgba(0, 0, 0, 0.4);
backdrop-filter: blur(12px) grayscale(50%);
}Modes de Fusion
mix-blend-mode contrôle comment un élément fusionne avec le contenu en dessous (séparé de backdrop-filter). multiply assombrit, screen éclaircit, difference inverse. Soyez prudent avec la lisibilité du texte.
.overlay {
background: rgba(255, 0, 100, 0.3);
backdrop-filter: blur(4px);
mix-blend-mode: multiply;
}
.difference {
background: white;
mix-blend-mode: difference;
backdrop-filter: invert(1);
}Performance & Replis
backdrop-filter est gourmand en GPU, surtout avec de grands rayons de flou. Fournissez un repli d'arrière-plan solide pour les navigateurs sans support, puis améliorez avec @supports. Évitez d'animer backdrop-filter — cela peut causer des saccades sévères.
/* Fallback for unsupported browsers */
.glass {
background: rgba(255, 255, 255, 0.9);
}
/* Progressive enhancement */
@supports (backdrop-filter: blur(10px)) {
.glass {
background: rgba(255, 255, 255, 0.2);
backdrop-filter: blur(10px);
}
}Carte Glassmorphism
Une carte glassmorphism classique combine un arrière-plan translucide, un flou de fond, une bordure lumineuse subtile (simulant la réflexion de bord) et une ombre douce. Le filtre saturate booste les couleurs vues à travers le verre.
.card {
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(16px) saturate(180%);
-webkit-backdrop-filter: blur(16px) saturate(180%);
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 16px;
padding: 24px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
}Snippets CSS associés
Copy-paste ready code for common tasks.
Centrer un div avec Flexbox et Grid
Centrer des éléments horizontalement et verticalement avec Flexbox, Grid et le positionnement absolu.
Sélecteurs CSS et pseudo-classes
Cibler des éléments avec pseudo-classes, pseudo-éléments et sélecteurs d'attribut.
CSS Grid
Mise en page Grid.
Flexbox
Mise en page en boîte flexible.
Animation
Animations CSS keyframe.
Transitions
Effets de transition CSS.
Variables CSS
Propriétés personnalisées.
Media queries
Points de rupture responsives.
Pseudo-classes et pseudo-éléments
Pseudo-classes et pseudo-éléments.
Design responsive
Techniques de mise en page responsive.
Mode sombre
Commutation de thème sombre.
Barre de défilement personnalisée
Styliser les barres de défilement.
Dégradés
Dégradés linéaires et radiaux.
Effets d'ombre
box-shadow et text-shadow.
Filtres
Effets de filtre CSS.
Transformations
Transformations 2D/3D.
Was this helpful?