Retour au cours

frontend / css

Box model

Leçon 21 exercice

Explication

Ce que vous allez apprendre

  • Identifier les quatre couches du box model : contenu, padding, bordure, marge
  • Comprendre pourquoi width ne correspond pas toujours à la largeur réellement affichée
  • Appliquer box-sizing: border-box pour rendre les dimensions prévisibles
  • Reconnaître le phénomène de fusion de marges (margin collapsing) et savoir quand il ne s'applique pas
  • Distinguer outline de border dans leur impact sur la mise en page

Dans quel contexte ?

Un développeur fixe width: 300px sur une carte produit .carte-produit dans boutique.css, avec padding: 20px et border: 5px solid. En comparant avec la maquette Figma, la carte affichée s'avère 50px plus large que prévu, cassant l'alignement de la grille de trois colonnes. La cause : sans box-sizing: border-box, le padding et la bordure s'ajoutent PAR-DESSUS les 300px au lieu d'être inclus dedans.

Étape 1 : tout élément est une boîte

C'est l'un des concepts les plus fondamentaux de CSS : chaque élément HTML, quel que soit son contenu, est traité par le navigateur comme une boîte rectangulaire. Retenez bien cette image avant tout le reste.

Étape 2 : quatre couches imbriquées

Cette boîte est composée de quatre couches, comme des poupées russes : le contenu au centre, entouré du padding (l'espace intérieur), puis de la bordure, puis enfin de la marge (l'espace extérieur qui la sépare des autres boîtes).

Étape 3 : le piège qui déroute tout le monde

Voici le premier piège classique. Par défaut, fixer width: 300px sur un élément ne concerne QUE le contenu : le padding et la bordure s'ajoutent PAR-DESSUS, rendant la boîte réellement affichée plus large que prévu.

Étape 4 : la solution devenue quasi universelle

Voici comment on corrige ça : box-sizing: border-box, appliqué globalement dès le début du projet, change la règle du jeu pour que width inclue désormais le padding et la bordure. Les dimensions deviennent enfin prévisibles, ce qui explique pourquoi cette ligne apparaît en tête de presque tous les projets CSS modernes.

box-sizingwidth inclut...Largeur réelle si width:300px; padding:20px; border:5px
content-box (défaut)Le contenu seul350px (300 + 40 padding + 10 border)
border-boxContenu + padding + bordure300px exactement

Bonne pratique

Placez * { box-sizing: border-box; } tout en haut de votre feuille de style, dès le début du projet. C'est l'une des rares règles CSS qui font consensus sur pratiquement tous les projets modernes.

Étape 5 : un second piège, la fusion de marges

Il reste un autre comportement surprenant à connaître. Quand deux blocs empilés verticalement ont chacun une marge (l'un en bas, l'autre en haut), l'espace final entre eux n'est PAS la somme des deux marges, mais seulement la plus grande des deux — un phénomène appelé "margin collapsing", qui existe depuis les débuts de CSS.

Piège fréquent

.bloc-1 { margin-bottom: 30px; } suivi de .bloc-2 { margin-top: 20px; } ne produit pas 50px d'espace entre les deux, mais 30px (le maximum des deux). Ce comportement disparaît dès que l'un des deux parents est un conteneur flex ou grid : bon réflexe à garder si l'espacement semble incohérent.

Étape 6 : une confusion fréquente, outline vs border

Ces deux propriétés se ressemblent visuellement, mais se comportent très différemment. La bordure occupe de l'espace et pousse le contenu, alors que l'outline se dessine PAR-DESSUS sans jamais rien décaler autour.

Et ensuite ?

C'est justement pour cette raison qu'on utilise outline pour les indicateurs de focus au clavier : elle n'a aucun impact sur la mise en page environnante. Une fois le box model maîtrisé, la prochaine étape consiste à choisir les bonnes unités de mesure et de couleur.

Commandes & code

Box model

Chaque élément est une boîte rectangulaire composée de quatre couches concentriques.

css
/*
    ┌─────────────────────────────┐
    │           margin             │
    │  ┌─────────────────────┐    │
    │  │        border         │    │
    │  │  ┌───────────────┐  │    │
    │  │  │    padding     │  │    │
    │  │  │  ┌─────────┐  │  │    │
    │  │  │  │ content  │  │  │    │
    │  │  │  └─────────┘  │  │    │
    │  │  └───────────────┘  │    │
    │  └─────────────────────┘    │
    └─────────────────────────────┘
*/

.boite {
    width: 300px;
    padding: 20px;
    border: 5px solid #333;
    margin: 10px;
}
/* box-sizing: content-box (défaut) -> largeur RÉELLE affichée =
   300 (width) + 40 (padding) + 10 (border) = 350px, hors margin */
css
/* box-sizing: border-box -> width INCLUT padding + border : bien plus prévisible */
* {
    box-sizing: border-box;
}

.boite {
    width: 300px;
    padding: 20px;
    border: 5px solid #333;
    /* largeur affichée = exactement 300px, content réduit en interne */
}
css
/* Fusion de marges verticales (margin collapsing) : piège classique */
.bloc-1 { margin-bottom: 30px; }
.bloc-2 { margin-top: 20px; }
/* espace RÉEL entre les deux : 30px (le max des deux), pas 50px ! */

/* Ne se produit qu'entre marges verticales de blocs en flux normal.
   N'arrive PAS si : flex/grid container, overflow != visible,
   padding/border non nul entre les deux, position absolute/fixed. */

/* Raccourcis de padding/margin/border : sens horaire depuis le haut */
.espacements {
    padding: 10px;                    /* les 4 côtés */
    padding: 10px 20px;               /* vertical horizontal */
    padding: 10px 20px 15px;          /* haut horizontal bas */
    padding: 10px 20px 15px 5px;      /* haut droite bas gauche */

    /* Logical properties : suivent le sens d'écriture (i18n RTL/LTR) */
    padding-inline: 20px;   /* gauche+droite en LTR, inversé en RTL */
    padding-block: 10px;    /* haut+bas */
    margin-inline-start: 8px;
}
css
/* outline vs border : outline ne participe PAS au box model, ne décale rien */
.focusable:focus {
    outline: 2px solid blue;
    outline-offset: 2px; /* espace entre la bordure et l'outline */
}

/* display influence directement le box model */
.inline { display: inline; }        /* width/height/margin vertical ignorés */
.block { display: block; }          /* respecte tout le box model */
.inline-block { display: inline-block; } /* comme inline, mais respecte width/height */

Résumé

  • box-sizing: border-box (posé globalement) rend width prévisible en incluant padding/border.
  • Les marges verticales fusionnent entre blocs en flux normal : ce n'est pas un bug.
  • outline ne fait pas partie du box model, contrairement à border.
  • Les logical properties (margin-inline, padding-block...) s'adaptent au sens d'écriture.

Exercices pratiques

1 disponible
1

Mission : réparer une grille de trois cartes qui déborde

Objectif : Diagnostiquer un débordement de largeur causé par le box model par défaut, puis corriger sans changer les valeurs de width, padding ou border.

Contexte

Sur boutique.css, trois .carte-produit sont posées côte à côte dans un conteneur de 960px avec width: 300px, padding: 20px et border: 5px solid #333 chacune, sans aucune règle box-sizing définie nulle part dans le fichier. La troisième carte passe systématiquement à la ligne suivante, alors que 3 x 300px = 900px devrait largement tenir dans 960px.

Résoudre l’exercice →