L'une des premières choses que beaucoup d'entre nous ont apprises lorsque nous avons appris CSS était les caractéristiques des différents éléments d'un bloc en CSS, décrits comme le «modèle de bloc CSS». L'un des éléments du modèle de bloc est la marge (marge extérieure), une zone transparente autour du bloc qui repousse les autres éléments du contenu de ce bloc. Les propriétés
margin-top
,
margin-right
,
margin-bottom
et
margin-left
ont été décrites dès CSS1, ainsi que la propriété margin margin pour un réglage simultané dans les quatre propriétés.
La marge semble assez simple, cependant, dans cet article, nous examinerons certains points sur lesquels les gens tombent lorsqu'ils l'utilisent. En particulier, comment les marges interagissent entre elles et comment l'effondrement des marges externes fonctionne réellement.
Modèle de bloc CSS
Comme pour tous les articles sur les composants du modèle CSS CSS Block, nous devons déterminer ce que nous entendons par là et comment le modèle a été classé dans différentes versions de CSS. Le modèle de bloc fait référence à la façon dont les divers composants du bloc - contenu (pad), padding (padding), border (frame) et margin (padding) - sont localisés et interagissent les uns avec les autres. Dans CSS1, le modèle de bloc a été représenté à l'aide du diagramme ASCII illustré dans l'image ci-dessous.

Les quatre propriétés de chaque côté du bloc et la propriété de marge abrégée ont été définies dans CSS1.
La spécification CSS2.1 a une illustration pour démontrer le modèle de bloc et définit également des termes que nous continuons à utiliser pour décrire différents blocs. La spécification décrit la zone de contenu, la zone de remplissage, la zone de bordure et la zone de marge, chacune étant définie par les bordures de contenu, de remplissage, de bordure et de marge, respectivement.

Il existe actuellement une spécification pour la version
Block Model 3 en tant que brouillon de travail. Lors de la définition du modèle de bloc et des
marges , cela nous ramène à CSS2, donc tout au long de l'article, nous utiliserons la définition de CSS2.
Réduire la marge
La spécification CSS1 définit non seulement les marges, mais également leur effondrement. Ce comportement est devenu une source de nombreuses déceptions. Réduire la marge est logique lorsque vous considérez qu'à cette époque, CSS était utilisé comme langage de balisage pour les documents texte. L'effondrement de la marge signifie que lorsqu'un titre avec une marge inférieure est suivi d'un paragraphe ayant une marge supérieure, ces deux retraits ne s'additionnent pas, créant un énorme écart entre les éléments.
Lorsque deux marges s'effondrent, l'espace entre les éléments devient égal au plus grand des deux retraits. La petite empreinte se termine en fait à l'intérieur de la plus grande
L'effondrement de la marge dans les situations suivantes:
- Frères et sœurs adjacents (parent seul)
- Blocs vides
- Parent et premier / dernier enfant
Éléments frères adjacents
Je commencerai la description par une démonstration de la façon dont les marges s'effondrent entre frères et sœurs adjacents. Sauf comme indiqué ci-dessous, si vous avez deux éléments affichés l'un après l'autre dans le flux normal, la marge inférieure du premier élément s'effondrera avec la marge supérieure de l'élément suivant.
Dans l'exemple CodePen ci-dessous, il existe trois éléments
div
. Pour le premier élément, les marges supérieure et inférieure sont de 50 px, pour le second - 20 px, pour le troisième - 3 em. La marge entre les deux premiers éléments est de 50 pixels, car la marge inférieure de l'élément inférieur est absorbée par la marge supérieure de l'élément supérieur. La marge entre les deux seconds éléments est de 3em, car 3em est supérieur à 20 pixels à la marge inférieure du deuxième élément.
Blocs vides
Si le bloc est vide, ses marges supérieure et inférieure peuvent s'effondrer l'une avec l'autre. Dans l'exemple CodePen suivant, le deuxième élément avec la classe
empty
(non visible, car il est vide) a une marge supérieure et inférieure de 50 pixels, cependant, l'espace entre le premier et le troisième élément n'est pas de 100 pixels, mais 50. Ceci est le résultat de l'effondrement de deux marges.
L'ajout de quelque chose au bloc (même un remplissage) entraînera l'utilisation des marges supérieure et inférieure, et non leur réduction.
Parent et premier / dernier enfant
Ce scénario d'effondrement de marge intrigue les gens plus souvent que les autres, car il n'est pas intuitif. Dans le CodePen suivant, nous avons un
div
avec le
wrapper
classe (wrapper), et j'ai défini ce
div
propriété de
outline
rouge, afin que ses bordures soient visibles. Les trois enfants ont une marge de 50 pixels. Cependant, les premier et dernier éléments sont adjacents aux bordures de l'élément wrapper; il n'y a pas de retrait de 50 pixels entre l'élément et le wrapper.
En effet, la marge de l'enfant s'effondre avec toute marge du parent de telle sorte qu'elle se termine en dehors du parent. Vous pouvez le voir si vous testez l'enfant à l'aide du panneau du navigateur du développeur. La zone surlignée en jaune est la marge.

Réduire uniquement la marge
Le dernier exemple met également en évidence quelque chose sur l'effondrement de la marge. Dans CSS2, seules les marges verticales (supérieure et inférieure) ont été conçues pour s'effondrer. Par conséquent, dans l'exemple ci-dessus, les marges de gauche et de droite ne se réduisent pas et ne se terminent pas à l'intérieur du wrapper.
Remarque: Il convient de rappeler que la marge ne s'effondre que dans la direction du bloc, par exemple entre les paragraphes.
Prévention de l'effondrement
La marge ne se réduit pas si l'élément est défini sur le positionnement absolu ou la propriété
float
. Cependant, si vous êtes dans une situation où la marge s'effondre, comment éviter cela?
L'effondrement de la marge ne se produit pas dans une situation où quelque chose se situe entre les deux.
Par exemple, les marges supérieure et inférieure d'un bloc vide ne se réduisent pas si le bloc est défini sur une bordure ou un remplissage. Dans l'exemple ci-dessous, j'ai ajouté un bloc de remplissage 1px. Maintenant, en haut et en bas du bloc, il y a une marge de 50 pixels.
C'est la logique: si un bloc vide n'a pas de bordure ou de remplissage, il devient pratiquement invisible. Par exemple, il peut s'agir d'un paragraphe vide placé dans le balisage de votre CMS. Si votre CMS a ajouté des éléments de paragraphe superflus, vous ne voudriez probablement pas qu'ils provoquent de grands retraits entre les autres paragraphes car leurs marges sont prises en compte. Ajoutez quelque chose au bloc et obtenez ces retraits.
Un comportement similaire peut être observé avec la marge du premier ou du dernier enfant dont la marge dépasse le parent. Si nous ajoutons une bordure au parent, la marge de l'enfant restera à l'intérieur.
Et encore une fois, il y a de la logique dans ce comportement. Si vous avez des éléments wrapper à des fins sémantiques qui ne sont pas affichés visuellement, vous ne voulez probablement pas qu'ils créent une grande indentation lorsqu'ils sont affichés. Cela était plus utile lorsque le Web était principalement du texte. Et ce comportement est moins utile lorsque nous utilisons des éléments de disposition.
Création d'un «contexte de mise en forme de bloc»
Le nouveau «Contexte de mise en forme des blocs» (BFC) empêchera les marges de tomber de l'élément parent. Si nous regardons à nouveau l'exemple avec le premier et le dernier enfant dont les marges sortent des limites de l'élément wrapper et définissons le wrapper pour
display: flow-root
, créant ainsi BFC, la marge des enfants restera à l'intérieur.
Pour en savoir plus sur
display: flow-root
, lisez mon article "
Comprendre la mise en page CSS et le contexte de mise en forme des blocs ". Changer la valeur de la propriété de
overflow
en
auto
aura le même effet, car il crée également un nouveau BFC, bien qu'il puisse conduire à des barres de défilement qui ne sont pas nécessaires dans certains cas
Conteneurs Flex et Grid
Les conteneurs Flex et Grid définissent le contexte de mise en forme Flex et Grid pour les enfants, afin qu'ils aient un comportement de disposition de bloc différent. L'une de ces différences est que les marges ne s'effondrent pas:
Un conteneur flex définit un nouveau contexte de mise en forme flex pour le contenu. Cela revient à définir un contexte de mise en forme de bloc, sauf que le balisage flexible est utilisé à la place du balisage de bloc. Par exemple, les flottants ne fonctionnent pas à l'intérieur d'un conteneur flexible et la marge d'un conteneur flexible ne se réduit pas avec la marge des éléments enfants.
- Flexbox niveau 1
Si nous prenons l'exemple ci-dessus et l'enveloppons avec un conteneur Flex, indiquant la direction de l'axe principal de flex-direction: colonne, il devient clair que maintenant la marge des enfants ne dépasse pas l'enveloppe. De plus, les marges entre les éléments flexibles adjacents ne se réduisent pas, nous obtenons donc une distance de 100 pixels entre les éléments flexibles, qui est la somme des marges supérieure et inférieure, qui sont de 50 pixels chacune.
Stratégies de marge pour votre site Web
En raison de l'effondrement, une bonne solution serait d'offrir un moyen cohérent de travailler avec une marge sur votre site. La chose la plus simple que vous puissiez faire est d'en faire une règle pour définir la marge uniquement sur le haut ou le bas des éléments. Dans ce cas, vous ne devriez pas rencontrer trop souvent de problèmes d'effondrement, car le côté sur lequel la marge est définie sera toujours adjacent au côté de l'autre élément sans la marge.
Remarque : Harry Roberts
a une excellente publication détaillant les raisons pour lesquelles définir la marge dans une seule direction est une bonne idée, et pas seulement en raison de la résolution de problèmes d'effondrement.
Cette approche ne résout pas le problème de la marge tombant des éléments enfants au-delà des limites du parent, que vous pouvez rencontrer. Ce problème particulier est généralement moins courant et comprendre pourquoi cela se produit peut aider à trouver une solution. La solution idéale consiste à définir les composants qui nécessitent que cela
display: flow-root
, et avec un repli (repli) pour les navigateurs plus anciens, vous pouvez utiliser le
overflow
pour créer un BFC (contexte de formatage de bloc); transformer le parent en un récipient flexible; ou même régler le rembourrage à 1px. N'oubliez pas que vous pouvez utiliser la demande de prise en charge du navigateur pour les propriétés afin de déterminer si la propriété
display: flow-root
est prise en charge afin que seuls les navigateurs plus anciens obtiennent une solution moins optimale.
Je crois que dans la plupart des cas, comprendre pourquoi les marges s'effondrent (ou non) est la clé. Cela vous permettra de déterminer comment y faire face dans chaque cas. Quelle que soit la méthode que vous choisissez, partagez ces informations avec votre équipe. Assez souvent, l'effondrement de la marge est un peu mystérieux, de sorte que les moyens de y faire face ne sont pas toujours évidents. Un commentaire dans votre code peut être approprié - vous pouvez même inclure un lien vers cet article et aider à partager les connaissances sur la réduction de la marge.
J'ai décidé de compléter cet article avec quelques données supplémentaires relatives à la marge.
Marge d'intérêt
Lorsque vous utilisez des pourcentages en CSS, il doit s'agir de pourcentages de quelque chose. La marge (ainsi que le remplissage) définie en pourcentage sera toujours calculée par rapport à la largeur de l'élément parent. Cela signifie que lorsque vous utilisez des pourcentages, vous aurez toujours une marge égale de tous les côtés autour de l'élément.
Dans l'exemple CodePen ci-dessous, j'ai un wrapper d'une largeur de 200px, à l'intérieur duquel se trouve un bloc ayant une marge = 10%. De tous les côtés, la marge est de 20 pixels, ce qui représente 10% de 200 pixels.
Marge dans un monde dépendant des flux
Tout au long de cet article, nous avons parlé des marges verticales, cependant, le CSS moderne, en règle générale, pense à l'emplacement des éléments par rapport au flux plus que par rapport aux côtés physiques. Par conséquent, lorsque nous parlons de marges verticales, nous parlons en fait de marges dans la dimension de bloc. Ces marges peuvent être supérieures ou inférieures en mode d'écriture horizontale, ou droite ou gauche en mode vertical.
Après avoir travaillé avec des directions logiques relatives au flux, il devient plus facile de parler du début et de la fin du bloc que du haut et du bas. Pour faciliter cela, une spécification des propriétés et valeurs booléennes a été introduite dans CSS. Il remplace les propriétés physiques par des propriétés liées au flux.
Si nous parlons de marge, cela nous donne les alternatives suivantes (si nous travaillons avec l'anglais ou tout autre mode enregistré horizontalement avec la direction du texte de gauche à droite).
- margin-top = margin-block-start
- margin-right = margin-inline-end
- margin-bottom = margin-block-end
- margin-left = margin-inline-start
Nous avons également deux nouvelles propriétés abrégées:
- bloc de marge
- marge en ligne
Dans l'exemple CodePen suivant, j'ai utilisé des mots clés liés au flux, puis changé le mode d'orthographe des blocs. Vous pouvez voir comment les marges suivent le flux de texte, plutôt que d'être liées aux côtés physiques.
Vous pouvez en savoir plus sur les propriétés et valeurs logiques sur
MDN ou dans mon article,
Comprendre les propriétés et valeurs logiques , sur Smashing Magazine.
En conclusion
Vous savez maintenant ce que vous devez savoir sur la marge. En bref:
- La marge peut s'effondrer. Comprendre quand cela se produit et quand cela ne vous aidera pas à résoudre les problèmes qu'ils peuvent créer.
- L'installation de marge dans une seule direction résout de nombreux problèmes qui leur sont associés.
- Comme pour toute situation CSS, partagez les décisions que vous prenez avec votre équipe et commentez votre code
- La prise en compte des mesures de bloc et de ligne au lieu des côtés physiques, haut, droit, bas et gauche vous aidera, car le Web s'oriente vers l'indépendance du mode d'écriture