Maîtriser toutes les unités de mesure : absolues, relatives à la police, au viewport, au conteneur et au contexte pour des layouts robustes et fluides.
Les unités se divisent en deux grandes familles :
UNITÉS CSS — CLASSIFICATION COMPLÈTE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ┌─────────────────────────────────────────────────────┐ │ UNITÉS ABSOLUES │ │ Tailles fixes, identiques quelle que soit la cible │ │ │ │ px cm mm in pt pc │ └─────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────┐ │ UNITÉS RELATIVES │ │ Tailles calculées par rapport à un référent │ │ │ │ ┌── Font-Relative ──┐ ┌── Viewport ──┐ │ │ │ em rem ch ex │ │ vh vw │ │ │ └───────────────────┘ │ vmin vmax │ │ │ │ svh lvh dvh │ │ │ ┌── Container ─────┐ └──────────────┘ │ │ │ cqi cqw cqb │ │ │ └──────────────────┘ ┌── Autres ────┐ │ │ │ fr % │ │ │ └──────────────┘ │ └─────────────────────────────────────────────────────┘
Classification complète des unités CSS
| Unité | Signification | Équivalence | Usage principal |
|---|---|---|---|
px |
Pixel CSS (unité angulaire) | 1px = 1/96 de pouce | Borders, ombres, taille de police fixe, layout pixel-perfect |
cm |
Centimètre | 1cm = 96/2.54 px ≈ 37.8px | Impression (print stylesheets) |
mm |
Millimètre | 1mm = 1/10 cm ≈ 3.78px | Impression fine |
in |
Pouce (inch) | 1in = 2.54cm = 96px | Impression (US/UK) |
pt |
Point | 1pt = 1/72 in ≈ 1.33px | Typographie d'impression, PDF |
pc |
Pica | 1pc = 12pt ≈ 16px | Mise en page éditoriale |
/* px — L'unité absolue de référence pour le web */
.border { border: 1px solid #333; }
.ombre { box-shadow: 0 2px 8px rgba(0,0,0,0.2); }
/* cm, mm, in — Uniquement pour l'impression */
@media print {
.marge-page { margin: 2cm; }
.ligne { height: 0.5mm; }
}
/* pt — Typographie d'impression / PDF */
.font-print { font-size: 12pt; }
/* pc — Rarement utilisé en web */
.titre-édito { font-size: 1.5pc; }
em est relatif à la
taille de police du parent (ou de l'élément lui-même
pour font-size). rem est toujours
relatif à la taille de police racine (root, soit
<html>).
Démo interactive em vs rem
Parent (font-size: 20px)
/* Si html { font-size: 16px; } et .parent { font-size: 20px; } */
.enfant-em { font-size: 1.2em; } /* 20px × 1.2 = 24px (parent) */
.enfant-rem { font-size: 1.2rem; } /* 16px × 1.2 = 19.2px (racine) */
/* ⚠️ Le piège em : si un enfant est dans un parent déjà em,
les em s'accumulent (effet boule de neige) */
父 { font-size: 1.2em; } /* 16 × 1.2 = 19.2px */
子 { font-size: 1.2em; } /* 19.2 × 1.2 = 23.04px ! */
孙 { font-size: 1.2em; } /* 23.04 × 1.2 = 27.65px ! */
/* rem ne s'accumule JAMAIS — toujours depuis la racine */
父 { font-size: 1.2rem; } /* 19.2px */
子 { font-size: 1.2rem; } /* 19.2px (pas de multiplication) */
孙 { font-size: 1.2rem; } /* 19.2px (toujours la même) */
| Critère | em |
rem |
|---|---|---|
| Relatif à… | Taille du parent (ou de soi-même) | Taille racine (<html>) |
| Effet boule de neige | Oui — s'accumule | Non — toujours constant |
Pour les padding/margin |
Relatif à la police de l'élément | Relatif à la police racine |
| Usage idéal | Composants modulaires internes | Échelle globale, typographie |
| Piège principal | Empilement imprévisible | Moins de contextualisation |
| Unité | Relative à | Usage |
|---|---|---|
ch |
Largeur du glyphe "0" de la police courante | Largeur max de colonnes de texte (60-80ch idéal) |
ex |
Hauteur x-height (hauteur des minuscules) | Alignement vertical, rarement utilisé |
/* ch — Idéal pour la lisibilité du texte */
.colonne-texte {
max-width: 65ch; /* ~65 caractères par ligne = confort de lecture */
line-height: 1.6;
}
/* ex — Usage niche : alignement vertical */
.icone {
vertical-align: 0.3ex; /* Ajustement fin par rapport au texte */
| Unité | Relative à | Variante |
|---|---|---|
vw |
1% de la largeur du viewport | Viewport Width |
vh |
1% de la hauteur du viewport | Viewport Height (inclut barre mobile) |
vmin |
1% du plus petit côté (w ou h) | Utile pour les écrans paysage/portrait |
vmax |
1% du plus grand côté (w ou h) | Occuper tout l'espace disponible |
svh |
1% de la hauteur viewport "small" (sans barre) | Safe viewport height |
lvh |
1% de la hauteur viewport "large" (avec barre) | Large viewport height |
dvh |
1% de la hauteur viewport dynamique (courante) | Dynamic viewport height — recommandé |
Démo vh vs dvh
100vh inclut la barre d'adresse du navigateur, donc le
contenu déborde. Utilise 100dvh (dynamique) qui tient
compte de la barre en temps réel.
/* ❌ Problématique sur mobile */
.hero {
height: 100vh; /* Inclut la barre → dépassement */
}
/* ✅ Solution moderne */
.hero {
height: 100dvh; /* S'adapte en temps réel à la barre */
}
/* Fallback pour les navigateurs anciens */
@supports not (height: 100dvh) {
.hero { height: 100vh; }
}
/* Titre responsive avec vw */
.titre-hero {
font-size: clamp(1.5rem, 4vw, 3rem);
/* Min: 1.5rem | Préféré: 4vw | Max: 3rem */
}
| Unité | Relative à | Usage |
|---|---|---|
cqw |
1% de la largeur du conteneur | Composants responsives internes |
cqh |
1% de la hauteur du conteneur | Layout interne du composant |
cqi |
1% du plus petit côté du conteneur | Échelle du composant |
cqb |
1% du bloc du conteneur | Dimension du bloc conteneur |
/* Les unités de conteneur nécessitent container-type */
.card-wrapper {
container-type: inline-size;
}
.card {
padding: 2cqw; /* 2% de la largeur du conteneur */
font-size: 4cqi; /* Taille de police adaptative */
}
@container (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 1fr 2fr;
}
}
| Unité | Contexte | Usage idéal |
|---|---|---|
fr |
Espace restant dans un Grid | Colonnes de grille flexibles, proportions |
% |
Bloc conteneur parent (width/height) ou inline (padding/margin) | Largeurs proportionnelles, padding/margin |
/* fr — Unité de grille : distribue l'espace restant */
.layout {
display: grid;
grid-template-columns: 200px 1fr 300px;
/* Sidebar fixe | Contenu flexible | Aside fixe */
}
/* % — Par rapport au bloc conteneur */
.colonne {
width: 33.33%; /* 1/3 de la largeur du parent */
}
/* ⚠️ Les % pour padding/margin sont relatifs à la LARGEUR du conteneur
même pour padding-top/bottom (pas la hauteur !) */
.box {
padding: 10%; /* 10% de la largeur du parent, pas de la hauteur */
}
fr ne peut être utilisé
que dans un grid. % peut être utilisé
partout mais ne tient pas compte de l'espace occupé par les éléments
adjacents. fr soustrait d'abord les colonnes fixes, puis
distribue le reste.
Échelle typographique fluide
/* Définir une échelle globale avec rem sur :root */
:root {
font-size: 16px; /* Base = 1rem = 16px */
}
/* Échelle de taille avec rem — tout est cohérent */
.texte-xs { font-size: 0.75rem; } /* 12px */
.texte-sm { font-size: 0.875rem; } /* 14px */
.texte-base { font-size: 1rem; } /* 16px */
.texte-lg { font-size: 1.125rem; } /* 18px */
.texte-xl { font-size: 1.25rem; } /* 20px */
.texte-2xl { font-size: 1.5rem; } /* 24px */
.texte-3xl { font-size: 2rem; } /* 32px */
.texte-4xl { font-size: 2.5rem; } /* 40px */
/* Les marges et paddings suivent la même échelle */
.espace-xs { padding: 0.25rem; } /* 4px */
.espace-sm { padding: 0.5rem; } /* 8px */
.espace-md { padding: 1rem; } /* 16px */
.espace-lg { padding: 1.5rem; } /* 24px */
.espace-xl { padding: 2rem; } /* 32px */
/* Avantage : changer la taille de base de :root
redimensionne TOUT le site en une seule ligne */
Page avec sidebar
/* Layout moderne combinant unités absolues et relatives */
.page {
display: grid;
grid-template-columns: 260px 1fr; /* px pour le fixe, fr pour le flexible */
min-height: 100dvh; /* viewport dynamique */
gap: 1.5rem; /* rem pour l'espacement */
}
.sidebar {
padding: 1.5rem; /* rem */
font-size: 0.875rem; /* rem — texte un peu plus petit */
}
.contenu {
padding: 2rem 3rem; /* rem */
max-width: 75ch; /* ch — 75 caractères max par ligne */
}
/* Le header utilise em pour ses éléments internes */
.header-nav {
font-size: 0.9rem; /* rem */
}
.header-nav .btn {
padding: 0.5em 1.2em; /* em — espace proportionnel au texte */
font-size: 0.85rem; /* rem */
border: 2px solid currentColor; /* px — toujours pour les bordures */
}
Section héro sans média query
/* Un hero qui s'adapte sans aucune media query */
.hero {
min-height: 100dvh; /* Pleine hauteur dynamique */
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
padding: 2rem clamp(1rem, 5vw, 4rem); /* Fluid horizontal padding */
}
.hero h1 {
font-size: clamp(2rem, 6vw, 4.5rem); /* Min 32px → Préféré 6vw → Max 72px */
line-height: 1.1;
margin-bottom: 1rem;
}
.hero p {
font-size: clamp(1rem, 2.5vw, 1.5rem);/* Texte secondaire fluide */
max-width: 60ch; /* Lisibilité */
margin-bottom: 2rem;
}
.hero .btn-cta {
padding: clamp(0.75rem, 2vw, 1.2rem) clamp(1.5rem, 4vw, 3rem);
font-size: clamp(1rem, 2vw, 1.25rem);
border-radius: 8px;
}
Carte adaptative
/* Le composant s'adapte à son conteneur, pas au viewport */
.carte-wrapper {
container-type: inline-size;
container-name: carte;
}
.carte {
padding: 4cqi; /* 4% du conteneur */
font-size: 3.5cqi; /* Typographie fluide du conteneur */
display: grid;
gap: 2cqi;
}
/* Quand le conteneur atteint 400px, passage en layout horizontal */
@container carte (min-width: 400px) {
.carte {
grid-template-columns: 1fr 2fr;
align-items: center;
}
}
/* Avantage : même composant dans deux conteneurs de tailles différentes
s'adapte indépendamment dans chaque cas */
/* ❌ Piège : padding em = relatif à la police DE L'ÉLÉMENT */
.titre {
font-size: 2rem; /* 32px (relatif à la racine) */
padding: 0.5em; /* 16px (relatif à 32px = sa propre police !) */
}
/* ✅ Solution : être cohérent ou utiliser des variables */
.titre {
font-size: 2rem;
padding: 0.5rem; /* 8px (relatif à la racine, cohérent) */
}
/* OU utiliser em intentionnellement pour un espace proportionnel */
.badge {
font-size: 0.8rem;
padding: 0.4em 0.8em; /* Espace proportionnel au texte du badge */
}
/* ❌ Sur mobile, la barre d'adresse réduit la hauteur visible */
.hero {
height: 100vh; /* Déborde ! Le contenu est masqué par la barre */
}
/* ✅ Solution moderne */
.hero {
min-height: 100dvh; /* S'adapte dynamiquement */
}
/* ✅ Solution avec fallback */
.hero {
min-height: 100vh;
min-height: 100dvh; /* Écrase si supporté */
}
/* ❌ Les % sont toujours relatifs à la LARGEUR, même pour top/bottom */
.bloc {
padding-top: 10%; /* 10% de la LARGEUR du parent, pas la hauteur ! */
padding-bottom: 10%;
}
/* Si le parent est 800px de large → padding-top = 80px
même si la hauteur du parent n'est que de 200px */
/* ✅ Pour un padding proportionnel à la hauteur, utilise
une combinaison de padding-top/bottom avec aspect-ratio */
.bloc {
aspect-ratio: 16 / 9;
padding: 5%;
}
/* ❌ % inclut le gap dans le calcul, fr non */
.grille {
display: grid;
grid-template-columns: 1fr 1fr 1fr; /* 3 colonnes égales, gap déduit */
gap: 1rem;
}
/* Avec % : les gaps ne sont pas déduits */
.grille-pct {
display: grid;
grid-template-columns: 33.33% 33.33% 33.33%; /* Déborde à cause du gap ! */
gap: 1rem;
}
/* ✅ Toujours préférer fr dans les grilles */
px — ces
éléments sont décoratifs et la précision pixel est souhaitable.
rem —
permet une échelle modifiable depuis :root.
rem pour la cohérence, em si l'espace
doit être proportionnel au texte.
ch — 60-80ch
pour une lecture confortable.
fr — gère l'espace
restant automatiquement.
% ou
fr (avec grow).
dvh (pas
vh).
cqi/cqw
avec Container Queries.
cm, mm,
pt.
ex,
pc (rarement utiles).
0.25rem = 4px) et n'utiliser que des multiples.
ARBE DE DÉCISION — QUELLE UNITÉ CHOISIR ?
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
C'est quoi ?
│
├── BORDER / OUTLINE / OMBRE
│ └── → px (toujours)
│
├── TAILLE DE POLICE
│ ├── Globale / échelle du site ? → rem
│ ├── Proportionnelle au parent ? → em
│ ├── Responsive fluide ? → clamp(vw, rem, rem)
│ └── Impression ? → pt
│
├── PADDING / MARGIN
│ ├── Cohérence globale ? → rem
│ ├── Proportionnel au texte ? → em
│ ├── Fluid ? → clamp()
│ └── Impression ? → cm / mm
│
├── LARGEUR / HAUTEUR
│ ├── Fixe et précise ? → px
│ ├── Proportionnelle au parent ? → %
│ ├── Colonne de grille ? → fr
│ ├── Plein écran ? → 100dvh / 100dvw
│ ├── Texte max ? → ch
│ └── Composant encapsulé ? → cqw / cqi
│
├── ESPACEMENT ENTRE ÉLÉMENTS
│ └── → rem (ou em si proportionnel)
│
└── IMPRESSION (print)
├── Marges page ? → cm
├── Lignes ? → mm
└── Texte ? → pt
Guide de décision pour choisir la bonne unité CSS
Défi : Convertir un layout px en layout responsive
Transforme ce layout rigide en layout moderne et responsive :
/* ❌ LAYOUT RIGIDE — à transformer */
.page { width: 1200px; }
.sidebar { width: 250px; float: left; }
.contenu { width: 900px; float: left; }
.titre { font-size: 32px; }
.texte { font-size: 16px; }
.marge { padding: 20px; }
.bordure { border: 2px solid #333; }
.ligne { max-width: 600px; }
Solution :
/* ✅ LAYOUT MODERNE — responsive et fluide */
.page {
display: grid;
grid-template-columns: 260px 1fr;
gap: 1.5rem;
}
.sidebar { padding: 1.5rem; }
.contenu { padding: 2rem; }
.titre { font-size: 2rem; } /* rem : échelle modifiable */
.texte { font-size: 1rem; } /* rem : base */
.marge { padding: 1.25rem; } /* rem : cohérent */
.bordure { border: 2px solid #333; } /* px : correct pour les bordures */
.ligne { max-width: 40ch; } /* ch : lisibilité du texte */
Projet : Système de design d'unités
Crée un fichier tokens.css qui définit un système
complet d'unités :
/* tokens.css — Système d'unités */
:root {
/* === ÉCHELLE TYPOGRAPHIQUE === */
--text-xs: 0.75rem; /* 12px */
--text-sm: 0.875rem; /* 14px */
--text-base: 1rem; /* 16px */
--text-lg: 1.125rem; /* 18px */
--text-xl: 1.25rem; /* 20px */
--text-2xl: 1.5rem; /* 24px */
--text-3xl: 2rem; /* 32px */
--text-4xl: 2.5rem; /* 40px */
--text-5xl: 3rem; /* 48px */
/* === PAS D'ESPACEMENT (base: 4px) === */
--space-1: 0.25rem; /* 4px */
--space-2: 0.5rem; /* 8px */
--space-3: 0.75rem; /* 12px */
--space-4: 1rem; /* 16px */
--space-5: 1.25rem; /* 20px */
--space-6: 1.5rem; /* 24px */
--space-8: 2rem; /* 32px */
--space-10: 2.5rem; /* 40px */
--space-12: 3rem; /* 48px */
--space-16: 4rem; /* 64px */
/* === LARGEURS DE CONTENEUR === */
--container-sm: 640px;
--container-md: 768px;
--container-lg: 1024px;
--container-xl: 1280px;
/* === BORDURES === */
--border-thin: 1px;
--border-medium: 2px;
--border-thick: 4px;
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-full: 9999px;
}
/* Usage : */
.card { padding: var(--space-6); border-radius: var(--radius-md); }
.titre { font-size: var(--text-2xl); margin-bottom: var(--space-4); }
.texte { font-size: var(--text-base); line-height: 1.6; }
.bouton {
padding: var(--space-2) var(--space-5);
border: var(--border-medium) solid currentColor;
border-radius: var(--radius-full);
}
Contraintes :
0.25rem (4px).
font-size de :root.
Quiz rapide
em et
rem ?
100vh pose problème sur mobile ?fr peut-il être utilisé dans un
display: flex ?
1in en pixels ?% pour padding-top sont-ils
trompeurs ?
em est relatif à la police du parent (s'accumule),
rem est relatif à la police racine (constante).
vh, réduisant la hauteur visible.
dvh corrige ce problème.
ch — environ 60-80ch pour une lecture confortable.
fr est réservé aux grilles CSS (display: grid).
1in = 96px (définition du CSS).% pour padding sont toujours relatifs à la
largeur du parent, même pour
padding-top et padding-bottom.
cqi ou cqw (unités de conteneur,
nécessitent container-type).
px — les bordures sont un cas d'utilisation idéal
pour les unités absolues.
clamp() :
font-size: clamp(1.5rem, 4vw, 3rem);
rem — pour la cohérence et la maintenabilité.┌─────────────────────────────────────────────────────────────────┐ │ CHEAT SHEET — UNITÉS CSS │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ABSOLUES (tailles fixes) : │ │ ───────────────────────── │ │ px = 1/96in ≈ 1px → bordures, ombres, outline │ │ cm = 37.795px → impression │ │ mm = 3.7795px → impression fine │ │ in = 96px → impression (US) │ │ pt = 1.333px → typographie impression │ │ pc = 16px → éditorial (rare) │ │ │ │ FONT-RELATIVES : │ │ ───────────────── │ │ em = police du parent → composants modulaires │ │ rem = police racine → échelle globale │ │ ch = largeur "0" → max-width colonnes texte │ │ ex = x-height → alignement (rare) │ │ │ │ VIEWPORT : │ │ ───────── │ │ vw = 1% largeur écran → titres fluides │ │ vh = 1% hauteur écran → ⚠️ inclut barre mobile │ │ dvh = 1% hauteur dynamique→ ✅ recommandé pour hauteur │ │ svh = hauteur small → hauteur sans barre │ │ lvh = hauteur large → hauteur avec barre │ │ vmin/vmax = min/max → éléments proportionnels │ │ │ │ CONTENEUR : │ │ ────────── │ │ cqi/cqw = conteneur → composants encapsulés │ │ │ │ GRILLE : │ │ ─────── │ │ fr = espace restant → colonnes de grille │ │ % = largeur du parent → largeurs flexibles │ │ │ │ ACCOLADE : │ │ clamp(min, préféré, max) → taille fluide avec bornes │ │ │ │ RÈGLES D'OR : │ │ ───────────── │ │ 1. px pour les bordures et ombres │ │ 2. rem pour la typographie et l'espacement global │ │ 3. em pour les composants modulaires internes │ │ 4. fr pour les grilles │ │ 5. dvh pour la hauteur pleine écran │ │ 6. ch pour la largeur max du texte │ │ 7. clamp() pour les tailles fluides │ │ 8. Jamais de px pour les espacements (sauf imprression) │ └─────────────────────────────────────────────────────────────────┘
Résumé complet de toutes les unités CSS et leurs cas d'usage