Le modèle de boîte en CSS : margin, padding, border et box-sizing
En CSS, chaque élément de la page est une boîte rectangulaire. Un paragraphe, un titre, une image, une section : tous obéissent au même schéma, que l'on appelle le modèle de boîte (box model en anglais). Ce modèle empile quatre couches autour de votre contenu : le contenu lui-même, la marge intérieure (padding), la bordure (border) et la marge extérieure (margin). C'est probablement la notion la plus rentable de tout l'apprentissage du CSS : le jour où je l'ai vraiment comprise, la moitié de mes problèmes de mise en page ont disparu. Dans cet article, je vous la détaille couche par couche, avec des valeurs que j'ai mesurées dans Chrome pendant la rédaction pour que vous puissiez vérifier chaque affirmation chez vous.
Rappel sur les éléments de type block
Par défaut, un élément de type block comme un paragraphe occupe toute la largeur disponible, et sa hauteur s'adapte à son contenu. Vous pouvez lui imposer des dimensions avec les propriétés width et height. Si la différence entre les éléments block et inline reste floue pour vous, je vous conseille de relire mon article sur les éléments inline et block avant de continuer.
Autre chose que vous avez peut-être déjà remarquée : même sans écrire la moindre ligne de CSS, il existe de petits espaces autour de vos blocs. Ce ne sont pas des bugs, ce sont les styles par défaut du navigateur. Pour les visualiser, donnez une couleur de fond au body et une autre au paragraphe :
<body>
<p>Un paragraphe avec les marges par défaut du navigateur.</p>
</body>body {
background-color: lightblue;
}
p {
background-color: white;
}Le fond blanc du paragraphe ne touche jamais les bords de la fenêtre. J'ai mesuré ces espaces dans Chrome pendant la rédaction : le body porte une marge par défaut de 8 pixels sur les quatre côtés, et un paragraphe porte une marge de 16 pixels en haut et en bas (soit 1 em avec la taille de police par défaut). Ces valeurs par défaut sont déjà du modèle de boîte en action : si le point d'entrée du CSS vous manque encore, commencez par donner du style à une page grâce au CSS.
Margin, la marge extérieure
La propriété margin écarte la boîte des éléments qui l'entourent. La forme la plus simple applique la même valeur aux quatre côtés :
p {
background-color: white;
margin: 100px;
}Avec ce code, le paragraphe s'écarte de 100 pixels de tout ce qui l'entoure. Redimensionnez la fenêtre de votre navigateur : la marge reste constante, c'est la largeur du contenu qui s'adapte.
Des marges différentes pour chaque côté
La propriété raccourcie accepte jusqu'à quatre valeurs, séparées par des espaces. La première s'applique en haut, puis on tourne dans le sens des aiguilles d'une montre : haut, droite, bas, gauche.
p {
margin: 10px 20px 30px 40px;
}J'ai vérifié cette règle en interrogeant les styles calculés dans Chrome : ce code produit bien margin-top à 10 px, margin-right à 20 px, margin-bottom à 30 px et margin-left à 40 px. Avec seulement deux valeurs, la première s'applique en haut et en bas, la seconde à droite et à gauche : margin: 15px 25px; donne, mesures à l'appui, 15 px en haut et en bas, 25 px à droite et à gauche.
Vous pouvez aussi cibler un seul côté avec les propriétés spécifiques margin-top, margin-right, margin-bottom et margin-left. Le code suivant donne exactement le même résultat que la version raccourcie à quatre valeurs :
p {
margin-top: 10px;
margin-right: 20px;
margin-bottom: 30px;
margin-left: 40px;
}Un piège classique : la fusion des marges verticales
Quand deux blocs se suivent verticalement, leurs marges ne s'additionnent pas : la plus grande des deux gagne. J'ai fait le test pendant la rédaction avec un premier bloc en margin-bottom: 40px; suivi d'un second en margin-top: 60px; : l'écart mesuré entre les deux est de 60 pixels, pas 100. C'est ce qu'on appelle la fusion des marges (margin collapsing). Retenez simplement que le phénomène existe : il vous évitera de longues minutes de perplexité devant un espacement qui refuse de grandir.
Padding, la marge intérieure
Le padding fonctionne exactement comme le margin : une propriété raccourcie qui accepte de une à quatre valeurs, et des propriétés spécifiques padding-top, padding-right, padding-bottom et padding-left. La différence est sa position : le padding écarte le contenu de la bordure, à l'intérieur de la boîte. La couleur de fond de l'élément recouvre le padding, alors qu'elle ne recouvre jamais le margin.
p {
background-color: white;
padding: 50px;
}Avec ce code, le texte s'écarte de 50 pixels des bords de son propre fond blanc. Si la place vient à manquer en largeur, le texte passe simplement à la ligne : le padding ne se réduit pas.
Border, la frontière entre les deux marges
La bordure s'insère entre le padding et le margin, sans jamais modifier leurs valeurs. J'ai détaillé ses nombreuses options (épaisseur, style, couleur, coins arrondis) dans l'article sur les bordures et les ombres en CSS, je ne les répète donc pas ici. Ce qu'il faut retenir pour le modèle de boîte : la bordure a une épaisseur, et cette épaisseur compte dans l'encombrement de l'élément, comme nous allons le mesurer tout de suite.
La question qui fâche : quelle est la largeur totale ?
Prenons une boîte apparemment simple :
.carte {
width: 300px;
padding: 20px;
border: 5px solid black;
}Quelle largeur occupe-t-elle à l'écran ? Intuitivement, on répond 300 pixels. C'est faux. Dans le comportement historique du CSS, la propriété width ne dimensionne que le contenu. Le padding et la bordure s'ajoutent autour. J'ai mesuré cette boîte dans Chrome pendant la rédaction : elle occupe 350 pixels de large, soit 300 de contenu, plus 20 de padding de chaque côté, plus 5 de bordure de chaque côté. Ce comportement par défaut s'appelle box-sizing: content-box, et c'est bien la valeur que le navigateur applique quand on ne précise rien (vérifié aussi dans les styles calculés).
Ce calcul mental permanent est pénible, et il devient franchement piégeux avec les largeurs en pourcentage. Toujours mesuré pendant la rédaction : dans un conteneur de 400 pixels, un enfant en width: 100%; avec 20 px de padding et 5 px de bordure atteint 450 pixels. Il déborde de son propre parent de 50 pixels.
La solution moderne : box-sizing: border-box
La propriété box-sizing change ce que width et height mesurent. Avec la valeur border-box, width désigne la largeur totale, bordure comprise : le navigateur retranche lui-même le padding et la bordure pour calculer la place du contenu.
.carte {
box-sizing: border-box;
width: 300px;
padding: 20px;
border: 5px solid black;
}Même boîte, même mesure dans Chrome : cette fois elle occupe exactement 300 pixels à l'écran, et le contenu dispose de 250 pixels (300 moins deux fois 20 de padding et deux fois 5 de bordure). Et le cas du pourcentage est réglé : dans le même conteneur de 400 pixels, l'enfant en width: 100%; mesure 400 pixels tout compris. Plus de débordement.
C'est pour cette raison que la quasi-totalité des feuilles de style modernes commencent par appliquer border-box à tous les éléments. Vous croiserez ce petit bloc, ou une variante, dans presque tous les projets :
*,
*::before,
*::after {
box-sizing: border-box;
}Je vous conseille de l'adopter dès maintenant dans vos exercices. Vous raisonnerez toujours sur la largeur visible de vos boîtes, celle que vous voyez à l'écran, et vos calculs de mise en page deviendront honnêtes : trois colonnes de 33 % restent trois colonnes de 33 %, quel que soit leur padding.
Ce qu'il faut retenir
- Tout élément est une boîte en quatre couches : contenu, padding, border, margin.
- margin et padding acceptent de une à quatre valeurs (haut, droite, bas, gauche, dans le sens des aiguilles d'une montre) et existent en versions spécifiques par côté.
- Les marges verticales de deux blocs qui se suivent fusionnent : la plus grande gagne (40 px et 60 px donnent 60 px d'écart, mesuré).
- Par défaut (content-box), padding et bordure s'ajoutent à width : 300 px de width deviennent 350 px à l'écran.
- Avec box-sizing: border-box, width devient la largeur totale visible : c'est le réglage standard des projets modernes.
La suite logique de cet article, c'est d'apprendre à dimensionner et positionner précisément ces boîtes : rendez-vous dans l'article sur les dimensions et le positionnement en CSS.
Et quand vous voudrez aligner plusieurs boîtes côte à côte proprement, flexbox vous attendra.
J'espère que ce cours vous a plu. Si un point reste flou, laissez-moi un commentaire et j'y répondrai. Sam.