Qu’est-ce que le box model ?
Le box model CSS est le concept fondamental derrière chaque mise en page sur le web. Il décrit comment chaque élément HTML est rendu sous la forme d’une boîte rectangulaire composée de quatre couches distinctes : le contenu (content), le remplissage (padding), la bordure (border) et la marge (margin). Que vous stylisiez un simple paragraphe ou que vous construisiez un tableau de bord complexe, le box model détermine l’espace occupé par un élément et sa relation avec ses voisins.
Imaginez cela comme un cadre photo. La photo elle-même est le contenu. Le passe-partout autour de la photo est le padding. Le cadre est la bordure. Et l’espace entre ce cadre et le suivant sur le mur est la marge. Chaque élément d’une page web fonctionne exactement ainsi : des boîtes imbriquées dans d’autres boîtes.
Les quatre couches
Le Contenu (Content) est la couche la plus interne — le texte, l’image, la vidéo ou tout autre média contenu dans l’élément. Sa taille est définie par width et height (ou par le contenu lui-même si ceux-ci ne sont pas spécifiés).
Le Padding se situe entre le contenu et la bordure. Il ajoute de l’espace à l’intérieur de l’élément pour éviter que le texte ne colle aux bords. Le padding est transparent par défaut, laissant ainsi apparaître la couleur ou l’image de fond de l’élément.
La Bordure (Border) enveloppe le padding et le contenu. Elle possède une largeur, un style et une couleur. Les bordures peuvent être décoratives ou structurelles — elles constituent le bord visible qui sépare l’élément du monde extérieur.
La Marge (Margin) est la couche la plus externe. Elle repousse les autres éléments. Contrairement au padding, la marge est toujours transparente et se situe à l’extérieur de la bordure de l’élément. Les marges sont l’outil principal pour contrôler l’espacement entre les éléments.
box-sizing: content-box vs border-box
La propriété box-sizing modifie la manière dont le navigateur interprète width et height.
Avec la valeur par défaut, content-box, la largeur et la hauteur que vous définissez s’appliquent uniquement à la zone de contenu. Le padding et la bordure sont ajoutés en supplément. Ainsi, un div avec width: 200px, padding: 20px et une bordure de 4px s’affichera en réalité avec une largeur de 248px. C’est contre-intuitif et c’est la source la plus courante de bugs de mise en page pour les débutants.
Avec border-box, la largeur et la hauteur incluent le padding et la bordure. Le même div avec width: 200px, padding: 20px et une bordure de 4px conserve exactement une largeur de 200px — la zone de contenu se réduit pour laisser de la place. C’est ainsi que la plupart des développeurs s’attendent à ce que le dimensionnement fonctionne, et c’est pourquoi un reset global comme celui-ci est une pratique standard :
/* reset.css */
*,
*::before,
*::after {
box-sizing: border-box;
}
Border-box rend les mises en page prévisibles. Vous définissez une largeur, et l’élément la respecte. Plus besoin de faire du calcul mental pour comprendre pourquoi vos colonnes sont plus larges que prévu. Utilisez-le partout et oubliez ces maux de tête.
Block vs inline vs inline-block
Chaque élément possède un comportement d’affichage par défaut qui détermine la manière dont il s’intègre dans la mise en page.
Les éléments Block commencent sur une nouvelle ligne et s’étirent pour occuper toute la largeur de leur parent. Ils s’empilent verticalement. Parmi les exemples, on trouve div, p, h1 jusqu’à h6, section, article, header, footer et ul. Les éléments Block acceptent width, height, margin sur tous les côtés ainsi que padding sur tous les côtés.
Les éléments Inline s’écoulent à l’intérieur du texte sans provoquer de retour à la ligne. Ils n’occupent que la largeur nécessaire à leur contenu. Parmi les exemples, on trouve span, a, strong, em, img et code. Les éléments Inline ignorent width et height, et les margin et padding verticaux n’affectent pas la mise en page environnante — ils se décalent visuellement mais ne poussent pas les autres éléments.
Les éléments Inline-block sont un hybride. Ils s’écoulent en ligne comme du texte, mais se comportent comme des blocs en interne — ils acceptent width, height, margin et padding sur tous les côtés. Les liens de navigation, les badges et les tags sont des cas d’utilisation classiques. Ils restent dans le flux du texte tout en vous offrant un contrôle total sur les dimensions et l’espacement.
| Propriété | Block | Inline | Inline-block |
|---|---|---|---|
| Commence sur une nouvelle ligne | Oui | Non | Non |
| Largeur/hauteur | Oui | Non | Oui |
| Marge/padding vertical | Oui | Non (visuel uniquement) | Oui |
| Marge/padding horizontal | Oui | Oui | Oui |
La propriété display
La propriété display est l’outil de mise en page le plus puissant de CSS. Elle contrôle non seulement le comportement du box model, mais aussi la manière dont un élément participe aux algorithmes de mise en page.
Les valeurs les plus courantes :
block— boîte pleine largeur, s’empile verticalement.inline— s’écoule avec le texte, sans dimensionnement via le box model.inline-block— flux en ligne avec dimensionnement via le box model.none— retire complètement l’élément de la mise en page. Il n’occupe aucun espace et n’est pas rendu.flex— transforme l’élément en conteneur flex. Les enfants deviennent des flex items avec un contrôle de mise en page unidimensionnel.grid— transforme l’élément en conteneur grid. Les enfants sont placés dans une grille bidimensionnelle.inline-flex— conteneur flex qui s’écoule en ligne.inline-grid— conteneur grid qui s’écoule en ligne.
Le CSS moderne vous propose flex et grid pour la mise en page, mais comprendre les concepts de block et inline reste essentiel car ils constituent le fondement sur lequel flex et grid s’appuient. Tout élément sans valeur de display explicite revient par défaut à block ou inline selon le type d’élément.
Calculs de largeur et de hauteur
La manière dont la largeur et la hauteur sont calculées dépend entièrement de box-sizing.
Avec content-box :
Actual width = width + padding-left + padding-right + border-left + border-right
Actual height = height + padding-top + padding-bottom + border-top + border-bottom
Avec border-box :
Actual width = width (padding and border are included)
Actual height = height (padding and border are included)
Une conséquence pratique : avec content-box, définir width: 100% sur un élément possédant du padding ou une bordure provoquera un dépassement horizontal (overflow). Avec border-box, cela fonctionne comme prévu. C’est l’un des arguments les plus forts en faveur de l’utilisation systématique de border-box.
Pour le dimensionnement à l’intérieur d’un conteneur, rappelez-vous que les pourcentages pour width se réfèrent à la largeur du contenu du parent (même avec border-box), tandis que les pourcentages pour height nécessitent que le parent ait une hauteur explicite — sinon, le pourcentage est traité comme auto.
Overflow et défilement
Lorsque le contenu est plus large que son conteneur, c’est la propriété overflow qui détermine le comportement.
overflow: visible(par défaut) — le contenu dépasse du cadre. Il reste visible mais peut chevaucher les éléments adjacents.overflow: hidden— le contenu est coupé à la bordure du cadre. Aucune barre de défilement n’apparaît, rendant le reste du contenu inaccessible.overflow: scroll— une barre de défilement s’affiche, qu’elle soit nécessaire ou non.overflow: auto— une barre de défilement n’apparaît que lorsque le contenu dépasse. C’est généralement le meilleur choix.overflow-xetoverflow-yvous permettent de contrôler indépendamment le dépassement horizontal et vertical.
La gestion de l’overflow est particulièrement cruciale pour les conteneurs à largeur fixe, les modales, les blocs de code et tout élément dont le contenu peut s’étendre. Sans cela, l’apparition de barres de défilement horizontales inattendues sur la page est fréquente.
Fusion des marges (Margin collapse)
Les marges verticales présentent une particularité qui surprend presque tous les débutants : elles fusionnent. Lorsque deux marges verticales se touchent, c’est la plus grande qui l’emporte au lieu que les deux ne s’additionnent.
/* style.css */
.box-a { margin-bottom: 30px; }
.box-b { margin-top: 20px; }
/* The gap between them is 30px, not 50px */
La fusion des marges se produit dans trois situations :
- Éléments frères adjacents — la marge inférieure de l’un et la marge supérieure du suivant fusionnent.
- Parent et premier enfant — la marge supérieure du parent fusionne avec la marge supérieure de son premier enfant (si le parent n’a ni bordure, ni padding, ni contenu pour les séparer).
- Parent et dernier enfant — même principe que précédemment, mais pour le bas.
La fusion des marges ne se produit jamais avec :
- Les marges horizontales.
- Les éléments Flex et Grid (le box model est différent à l’intérieur de ces conteneurs).
- Les éléments dont la propriété
overflowest définie sur une valeur autre quevisible. - Les éléments avec
borderoupaddingqui séparent les marges.
Comprendre la fusion des marges permet d’éviter le problème du “pourquoi cet espace n’a pas la bonne taille” qui pousse les développeurs à ajouter du padding arbitraire ou des marges négatives.
Positionnement : static, relative, absolute, fixed, sticky
La propriété position permet de sortir un élément du flux normal du document ou d’en modifier la place.
static est la valeur par défaut. L’élément se place dans le flux normal, et top, right, bottom, left et z-index n’ont aucun effet.
relative maintient l’élément dans le flux, mais vous permet de le décaler avec top, right, bottom et left. L’espace d’origine est préservé — c’est comme si vous déplaciez visuellement l’élément tout en conservant son emplacement dans la mise en page.
absolute retire complètement l’élément du flux. Il est positionné par rapport à son ancêtre positionné le plus proche — tout ancêtre dont la propriété position est définie sur relative, absolute, fixed ou sticky. Si aucun ancêtre de ce type n’existe, il utilise le viewport. Les éléments en position absolue n’affectent pas la mise en page des éléments frères ou parents.
fixed retire également l’élément du flux, mais le positionne par rapport au viewport. Il reste à la même place lors du défilement de la page. Utilisez-le pour les headers collants, les boutons d’action flottants et les modales qui doivent rester visibles.
sticky est un hybride. L’élément défile normalement jusqu’à ce qu’il atteigne un seuil (top, right, bottom ou left), puis il se “fixe” à cet endroit. C’est le remplaçant moderne des écouteurs d’événements de scroll en JavaScript. Les barres de navigation qui restent en haut de l’écran pendant le défilement en sont l’exemple classique.
/* style.css */
.sticky-nav {
position: sticky;
top: 0;
z-index: 10;
}
Z-index et contexte d’empilement
Lorsque des éléments se chevauchent, z-index détermine lequel apparaît au-dessus. Cela ne fonctionne que sur les éléments positionnés — ceux dont la propriété position est définie sur une valeur autre que static.
Cependant, z-index n’est pas un simple nombre global. Il crée ou participe à un contexte d’empilement (stacking context). Un contexte d’empilement est une couche autonome qui encapsule ses enfants. Un enfant avec un z-index: 9999 à l’intérieur d’un contexte d’empilement ayant un z-index: 1 n’apparaîtra jamais au-dessus d’un élément avec un z-index: 2 dans le contexte parent.
Les contextes d’empilement sont créés par :
- Les éléments avec
positionetz-indexdifférent deauto. - Les éléments avec
opacityinférieur à 1. - Les éléments avec
transform,filter,backdrop-filterouperspective. - Les éléments avec
isolation: isolate. - Les éléments à l’intérieur d’un conteneur flex ou grid avec un
z-index.
Comprendre les contextes d’empilement est la clé pour résoudre les problèmes du type “le z-index ne fonctionne pas”. La solution n’est presque jamais d’augmenter le nombre — elle consiste à comprendre dans quel contexte d’empilement se trouve votre élément.
Bonnes pratiques de mise en page
- Utilisez toujours
box-sizing: border-boxglobalement. Cela élimine toute une catégorie de bugs de dimensionnement. - Évitez
width: 100%avec du padding sur des éléments en content-box. Utilisez border-box à la place. - Privilégiez
max-widthplutôt quewidthpour le contenu qui ne doit pas s’étirer excessivement en largeur. - Utilisez
margin: autopour le centrage horizontal à l’intérieur de conteneurs de type block. - Utilisez
overflow: autoau lieu deoverflow: hiddenlorsque vous souhaitez des barres de défilement pour le contenu qui dépasse. - Évitez de donner des
heightfixes aux conteneurs avec du contenu dynamique — laissez-les s’adapter à la taille du contenu. - Pour l’espacement vertical, faites attention au phénomène de fusion des marges (margin collapse). Utilisez gap dans un contexte flex/grid ou du padding sur le parent.
- N’utilisez jamais
position: absolutepour la mise en page générale — cela casse le flux du document et rend le design responsive plus difficile. - Utilisez
position: stickyplutôt que JavaScript pour les headers et sidebars qui réagissent au défilement. - Gardez des contextes d’empilement (stacking contexts) peu profonds. L’accumulation de valeurs
z-indexà travers des composants profondément imbriqués devient vite confuse. - Testez vos mises en page à plusieurs largeurs. Le box model se comporte différemment lorsque la fenêtre d’affichage (viewport) rétrécit.
Erreurs courantes
- Oublier de définir
box-sizing: border-box, ce qui entraîne des largeurs inattendues. - Utiliser
widthsur des éléments inline et se demander pourquoi rien ne change. - Appliquer
marginsur des éléments inline et ne pas obtenir l’espacement attendu. - Utiliser
position: absolutesans parent positionné, ce qui projette les éléments dans le coin du viewport. - Confusion lorsque
z-indexne fonctionne pas — généralement un problème de contexte d’empilement (stacking context). - Surprise face à la fusion des marges (margin collapse) entre un élément parent et ses enfants.
- Définir une hauteur fixe sur un conteneur et constater que le contenu déborde de manière invisible.
- Utiliser
overflow: hiddenpour “réparer” la mise en page alors que le véritable problème vient d’un dimensionnement incorrect.
Quand utiliser le box model plutôt que Flexbox ou Grid
Le box model n’est pas un système de mise en page en soi — c’est le fondement sur lequel reposent tous les layouts CSS. Flexbox et Grid ne remplacent pas le box model ; ils s’appuient dessus. Chaque élément flex et chaque cellule de grille possède toujours du contenu, du padding, une bordure et une marge.
Utilisez le box model directement pour :
- Contrôler l’espacement à l’intérieur et autour d’éléments individuels.
- Définir des tailles explicites pour les cartes, les boutons, les inputs et les conteneurs.
- Comprendre pourquoi des éléments débordent ou ne s’insèrent pas correctement dans leurs parents.
Utilisez Flexbox lorsque vous devez aligner et distribuer des éléments le long d’un seul axe — barres de navigation, rangées de cartes, centrage de contenu.
Utilisez Grid lorsque vous avez besoin d’une mise en page bidimensionnelle avec des lignes et des colonnes — structures de page, tableaux de bord, galeries d’images.
Les meilleurs développeurs CSS se tournent d’abord vers le box model pour comprendre ce qui se passe, puis ajoutent une couche de flex ou de grid pour la mise en page de haut niveau. Apprendre le box model n’est pas distinct de l’apprentissage des layouts modernes — c’est le prérequis qui donne du sens à tout le reste.