Chapitre 821 minDébutant
Box model, display et position en CSS
Par Josselyn C., prof de BTS SIO. Mis à jour le .
À la fin de ce chapitre, tu sauras
- calculer la taille d'une boîte en
content-boxet enborder-box; - régler marges, bordures et espacements, et prévoir la fusion des marges ;
- choisir la valeur de
displayet deposition; - superposer avec
z-indexet centrer un élément.
5 exercices corrigés2 schémas
En CSS, chaque élément est une boîte rectangulaire faite de quatre zones emboîtées : le contenu, la marge intérieure (padding), la bordure (border) et la marge extérieure (margin) ; c'est le modèle de boîte, ou box model. Ce chapitre explique comment se calcule la taille d'une boîte, la différence entre margin et padding, la propriété display, le positionnement avec position et z-index, et les façons de centrer un élément.
Les quatre zones d'une boîte
| Zone | Propriété | Rôle | Fond |
|---|---|---|---|
| Contenu | width, height | le texte, l'image | couleur de fond de l'élément |
| Marge intérieure | padding | l'espace entre le contenu et la bordure | couleur de fond de l'élément |
| Bordure | border | le trait autour du padding | sa propre couleur |
| Marge extérieure | margin | l'espace entre la boîte et ses voisines | transparente : on voit le fond du parent |
La différence entre margin et padding, la question la plus posée sur ce chapitre, tient dans la colonne « Fond » : le padding agrandit la boîte de l'intérieur, sous son fond et sa zone cliquable ; la margin écarte la boîte des autres, à l'extérieur. Pour aérer le texte d'un bouton, c'est du padding (la zone cliquable grandit) ; pour éloigner deux cartes, de la margin (ou mieux, gap, chapitre 9).
Dans l'inspecteur, l'onglet Mise en page (Layout ou Computed) dessine ces quatre zones avec leurs valeurs, et le survol d'un élément les colore dans la page : c'est le moyen le plus rapide de comprendre un espace inattendu.
Calculer la taille d'une boîte : content-box et border-box
.carte {
width: 300px;
padding: 20px;
border: 2px solid #0f766e;
margin: 16px;
}
Quelle largeur fait la carte à l'écran ? Par défaut (box-sizing: content-box), width ne fixe que le contenu. Le padding et la bordure s'ajoutent :
- largeur visible : 300 + 2 × 20 + 2 × 2 = 344 px ;
- largeur occupée dans la page, marges comprises : 344 + 2 × 16 = 376 px.
Ce mode de calcul surprend tout le monde : tu déclares 300 px, tu obtiens 344. Deux colonnes à width: 50% avec un padding débordent et passent l'une sous l'autre. La propriété box-sizing: border-box change la règle : width inclut alors le padding et la bordure.
.carte {
box-sizing: border-box;
width: 300px; /* la boîte visible fait 300 px */
padding: 20px; /* le contenu se réduit à 300 − 40 − 4 = 256 px */
border: 2px solid #0f766e;
}
Presque tous les sites commencent donc leur feuille de style par :
*,
*::before,
*::after {
box-sizing: border-box;
}
margin, padding et border : les raccourcis
margin et padding acceptent une à quatre valeurs, dans le sens des aiguilles d'une montre en partant du haut :
| Écriture | Haut | Droite | Bas | Gauche |
|---|---|---|---|---|
padding: 1rem; | 1rem | 1rem | 1rem | 1rem |
padding: 1rem 2rem; | 1rem | 2rem | 1rem | 2rem |
padding: 1rem 2rem 3rem; | 1rem | 2rem | 3rem | 2rem |
padding: 1rem 2rem 3rem 4rem; | 1rem | 2rem | 3rem | 4rem |
Les propriétés détaillées existent aussi : margin-top, padding-left… et leurs équivalents logiques margin-block-start, padding-inline (chapitre 11).
Quelques valeurs particulières :
margin: 0 auto;centre horizontalement un bloc qui a une largeur (widthoumax-width) : les marges gauche et droite se partagent l'espace libre ;- une marge négative rapproche ou fait chevaucher les boîtes ; un padding ne peut pas être négatif.
.bordure-exemples {
border: 2px solid #0f766e; /* épaisseur, style, couleur */
border-bottom: 4px dashed #94a3b8; /* un seul côté */
border-radius: 8px; /* coins arrondis ; 50% sur un carré donne un cercle */
box-shadow: 0 2px 8px rgb(0 0 0 / 15%); /* décalage x, y, flou, couleur */
outline: 3px solid #1d4ed8; /* contour hors boîte : ne prend pas de place */
}
outline ressemble à une bordure, mais ne compte pas dans la taille de la boîte et ne décale rien : c'est pour ça qu'on l'utilise pour l'indicateur de focus.
La fusion des marges
Quand deux marges verticales se touchent, elles ne s'additionnent pas : elles fusionnent, et seule la plus grande reste.
h2 { margin-bottom: 24px; }
p { margin-top: 16px; }
Entre un <h2> et le <p> qui le suit, l'espace est de 24 px, pas de 40. La fusion se produit aussi entre un parent et son premier ou dernier enfant, si rien ne les sépare (ni bordure, ni padding) : la marge haute du premier <h2> d'une carte « sort » alors de la carte.
Elle ne se produit pas pour les marges horizontales, ni entre les éléments d'un conteneur Flexbox ou Grid. Beaucoup de développeurs évitent le problème en ne mettant que des marges basses (margin-bottom), ou en espaçant les éléments avec gap.
Largeur, hauteur et débordement
| Propriété | Usage |
|---|---|
width, height | taille fixe ; à éviter pour la hauteur d'un bloc de texte, qui doit pouvoir grandir |
max-width | largeur maximale : max-width: 65ch garde des lignes lisibles ; max-width: 100% empêche une image de déborder de son conteneur |
min-height | hauteur minimale, le contenu pouvant la dépasser |
overflow | que faire du contenu qui dépasse : visible (par défaut, il déborde), hidden (coupé), auto (barre de défilement si besoin) |
.contenu {
max-width: 70rem;
margin: 0 auto; /* centré, jamais plus large que 70rem */
padding: 0 1rem; /* de l'air sur les petits écrans */
}
.tableau-large {
overflow-x: auto; /* un grand tableau défile dans son cadre sur mobile */
}
.titre-carte {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis; /* « Initiation à l'ordinat… » */
}
La propriété display
display décide comment une boîte se place par rapport aux autres.
| Valeur | Comportement | Largeur et hauteur | Exemples par défaut |
|---|---|---|---|
block | nouvelle ligne, toute la largeur disponible | prises en compte | div, p, h1, ul, section |
inline | dans le fil du texte, sans casser la ligne | ignorées ; padding et margin verticaux ne repoussent pas les lignes | a, span, strong, em |
inline-block | dans le fil du texte, mais comme un bloc à l'intérieur | prises en compte | button, input, select |
none | l'élément disparaît : il ne prend plus de place et n'est plus lu par les lecteurs d'écran | head, éléments hidden | |
flex, grid | l'élément devient un conteneur Flexbox ou Grid pour ses enfants | (chapitre 9) |
/* Des liens de menu cliquables sur toute leur surface */
nav a {
display: inline-block;
padding: 0.75rem 1rem;
}
Sans inline-block, le padding vertical d'un lien en ligne déborderait sur les lignes voisines sans agrandir la zone de la ligne : le lien paraîtrait plus haut, mais les autres lignes ne s'écarteraient pas.
Trois façons de cacher un élément, qui ne font pas la même chose :
| Méthode | Visible | Place occupée | Lu par un lecteur d'écran |
|---|---|---|---|
display: none (ou attribut hidden) | non | non | non |
visibility: hidden | non | oui (un trou) | non |
| Classe « visuellement masqué » (ci-dessous) | non | non | oui |
/* Masqué à l'écran, mais lu par les lecteurs d'écran */
.visuellement-masque {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
border: 0;
}
Cette classe sert par exemple à donner un titre <h2> « Menu principal » que seuls les lecteurs d'écran entendent, ou à compléter un lien « Lire la suite » avec la fin cachée « de l'article sur le club lecture ».
La propriété position
position sort un élément du placement normal (le « flux ») pour le placer avec top, right, bottom, left.
| Valeur | Place dans le flux | Référence pour top, left… | Usage |
|---|---|---|---|
static | normale (par défaut) | top, left sans effet | |
relative | gardée : les voisins ne bougent pas | sa propre place normale | petit décalage ; surtout, servir de référence à un enfant absolute |
absolute | retirée : les voisins se comportent comme s'il n'existait pas | le plus proche ancêtre positionné (relative, absolute, fixed ou sticky), sinon la page | badge, icône, info-bulle posés sur un autre élément |
fixed | retirée | la fenêtre : l'élément ne bouge pas quand on fait défiler | bouton « haut de page », bandeau de consentement |
sticky | normale, puis collée quand le défilement l'atteint | son conteneur et la fenêtre | en-tête de tableau, menu qui reste visible |
Le motif le plus courant, un badge posé sur une carte :
.carte {
position: relative; /* la carte devient la référence */
}
.badge-complet {
position: absolute;
top: 0.5rem;
right: 0.5rem; /* en haut à droite de la carte, pas de la page */
}
header {
position: sticky;
top: 0; /* se colle en haut de la fenêtre au défilement */
z-index: 10;
background-color: white; /* sinon le contenu se voit à travers */
}
N'utilise pas position: absolute pour construire une mise en page entière (colonnes, grille de cartes) : le contenu ne pousse plus rien, et tout se chevauche dès que le texte s'allonge ou que l'écran rétrécit. La mise en page, c'est Flexbox et Grid.
z-index et superposition
Quand des éléments positionnés se chevauchent, z-index décide lequel passe devant : la valeur la plus grande est au-dessus. Il ne s'applique qu'aux éléments positionnés (position autre que static) et aux enfants de conteneurs Flexbox et Grid.
.menu-deroulant { position: absolute; z-index: 20; }
header { position: sticky; z-index: 10; }
Le piège : z-index agit à l'intérieur d'un contexte d'empilement. Un élément qui a un z-index (et une position), une opacity inférieure à 1 ou un transform crée un nouveau contexte : ses enfants ne peuvent pas passer au-dessus d'un élément extérieur plus haut que lui, même avec z-index: 9999. Si un z-index « ne marche pas », remonte les ancêtres dans l'inspecteur et cherche celui qui crée le contexte.
Centrer un élément en CSS
| Besoin | Solution |
|---|---|
| Centrer du texte ou des éléments en ligne dans un bloc | text-align: center; sur le bloc |
| Centrer horizontalement un bloc qui a une largeur | margin: 0 auto; (avec width ou max-width) |
| Centrer un élément horizontalement et verticalement dans son parent | sur le parent : display: grid; place-items: center; |
| Même chose, avec Flexbox | sur le parent : display: flex; justify-content: center; align-items: center; |
Centrer un élément absolute | inset: 0; margin: auto; avec une largeur et une hauteur, ou top: 50%; left: 50%; transform: translate(-50%, -50%); |
/* Un message centré au milieu d'une zone de 60 % de la hauteur de la fenêtre */
.zone-vide {
min-height: 60dvh;
display: grid;
place-items: center;
}
Le centrage vertical demande que le parent ait une hauteur plus grande que l'enfant : un bloc qui a la hauteur de son contenu n'a rien à centrer.
Exercices
Exercice 1 sur 5 Calculer la taille d'une boîte Réussi À revoir
.encart {
width: 400px;
padding: 10px 30px;
border: 5px solid #0f766e;
margin: 20px auto;
}
- Quelle est la largeur visible de
.encart(bordure comprise), avec lebox-sizingpar défaut ? - Même question avec
box-sizing: border-box. Quelle est alors la largeur du contenu ? - Quelle est la hauteur visible si le contenu fait 120 px de haut (
content-box) ? - Que fait
margin: 20px auto?
Voir la réponseMasquer la réponse de l'exercice 1
- 400 + 30 + 30 + 5 + 5 = 470 px (le padding horizontal est la deuxième valeur, 30 px de chaque côté).
- 400 px. Le contenu fait 400 − 2 × 30 − 2 × 5 = 330 px.
- 120 + 10 + 10 + 5 + 5 = 150 px (le padding vertical est la première valeur, 10 px).
- 20 px de marge en haut et en bas, et des marges gauche et droite automatiques qui centrent l'encart horizontalement dans son parent.
Tu avais trouvé ?
Exercice 2 sur 5 Margin ou padding ? Réussi À revoir
Choisis margin ou padding pour chaque besoin, et justifie.
- Agrandir la zone cliquable d'un lien du menu.
- Écarter une carte de la carte voisine.
- Éloigner le texte d'une carte de sa bordure.
- Centrer horizontalement le conteneur principal.
- Faire en sorte que le fond coloré d'un titre déborde autour du texte.
Voir la réponseMasquer la réponse de l'exercice 2
- padding : il agrandit la boîte de l'intérieur, donc sa zone cliquable (avec
display: inline-blocksur le lien). - margin (ou
gapsur le conteneur Flexbox ou Grid) : on écarte la boîte de l'extérieur. - padding : l'espace entre le contenu et la bordure.
- margin :
margin: 0 autoavec une largeur maximale. - padding : le fond s'étend sous le padding, pas sous la margin.
Tu avais trouvé ?
Exercice 3 sur 5 La fusion des marges Réussi À revoir
Quel espace vertical sépare les deux éléments dans chaque cas ?
- Un
<h2>avecmargin-bottom: 32px, suivi d'un<p>avecmargin-top: 12px. - Deux
<p>qui ont chacunmargin: 16px 0. - Les mêmes deux
<p>, enfants d'un conteneurdisplay: flex; flex-direction: column;. - Un
<p>avecmargin-bottom: 20pxsuivi d'un<p>avecmargin-top: -8px.
Voir la réponseMasquer la réponse de l'exercice 3
- 32 px : les marges fusionnent, la plus grande reste.
- 16 px : la marge basse du premier et la marge haute du second fusionnent.
- 32 px : il n'y a pas de fusion entre les éléments d'un conteneur Flexbox, les marges s'additionnent.
- 12 px : quand une marge est négative, la fusion fait la somme de la plus grande marge positive et de la plus négative, 20 + (−8).
Tu avais trouvé ?
Exercice 4 sur 5 Placer un badge Réussi À revoir
Écris le HTML et le CSS d'une carte d'atelier qui affiche, collé à 8 px du coin supérieur droit de la carte, un badge « Complet » blanc sur fond rouge #b91c1c. Les autres cartes de la page ne doivent pas bouger.
Voir la réponseMasquer la réponse de l'exercice 4
<article class="carte">
<p class="badge">Complet</p>
<h3>Initiation à l'ordinateur</h3>
<p>Mercredi 3 juin, 10 h</p>
</article>
.carte {
position: relative; /* référence du badge */
padding: 1rem;
border: 1px solid #64748b;
border-radius: 8px;
}
.badge {
position: absolute;
top: 8px;
right: 8px;
margin: 0;
padding: 0.25rem 0.5rem;
border-radius: 4px;
background-color: #b91c1c;
color: white;
font-size: 0.875rem;
font-weight: 700;
}
Sans position: relative sur .carte, le badge se placerait par rapport à la page entière. Le badge étant sorti du flux, le titre de la carte peut passer dessous s'il est long : prévois un padding-right sur la carte. Le blanc sur #b91c1c atteint 6,5:1 de contraste. Le badge est placé en premier dans le HTML pour être lu avant le titre ; tu peux aussi le mettre après, l'ordre visuel ne change pas.
Tu avais trouvé ?
Exercice 5 sur 5 Pourquoi c'est caché ? Réussi À revoir
Pour chaque cas, dis si l'élément est visible, s'il occupe de la place et s'il est lu par un lecteur d'écran.
<p hidden>Inscriptions closes</p><p style="visibility: hidden">Inscriptions closes</p><p class="visuellement-masque">Inscriptions closes</p>(classe de ce chapitre)<p style="opacity: 0">Inscriptions closes</p>
Voir la réponseMasquer la réponse de l'exercice 5
- Invisible, pas de place, non lu (
hiddenéquivaut àdisplay: none). - Invisible, occupe sa place (un trou dans la page), non lu.
- Invisible, pas de place, lu par les lecteurs d'écran.
- Invisible, occupe sa place, lu par les lecteurs d'écran, et même cliquable s'il contient un lien : à éviter pour masquer du contenu.
Tu avais trouvé ?