Tout ce que vous devez savoir sur les marges CSS

Publié: 2022-03-10
Résumé rapide ↬ Les marges en CSS semblent assez simples à première vue. Appliqué à un élément, il forme un espace autour de l'élément, repoussant les autres éléments. Cependant, il y a plus à une marge que vous ne le pensez.

L'une des premières choses que la plupart d'entre nous avons apprises lorsque nous avons appris le CSS, ce sont les détails des différentes parties d'une boîte en CSS, décrites comme le modèle de boîte CSS. L'un des éléments du modèle de boîte est la marge, une zone transparente autour d'une boîte, qui éloignera les autres éléments du contenu de la boîte. Les propriétés margin-top , margin-right , margin-bottom et margin-left ont été décrites directement dans CSS1, ainsi que le raccourci margin pour définir les quatre propriétés à la fois.

Une marge semble être une chose assez simple, cependant, dans cet article, nous examinerons certaines des choses qui font trébucher les gens en ce qui concerne l'utilisation des marges. En particulier, nous examinerons comment les marges interagissent les unes avec les autres et comment fonctionne réellement l'effondrement des marges.

Le modèle de boîte CSS

Comme pour tous les articles sur les parties du modèle de boîte CSS, nous devons définir ce que nous entendons par là et comment le modèle a été clarifié à travers les versions de CSS. Le modèle de boîte fait référence à la façon dont les différentes parties d'une boîte - le contenu, le remplissage, la bordure et la marge - sont disposées et interagissent les unes avec les autres. Dans CSS1, le Box Model a été détaillé avec le diagramme d'art ASCII illustré dans l'image ci-dessous.

dessin d'art ascii du modèle de boîte
Représentation du modèle de boîte CSS dans CSS1

Les quatre propriétés de marge pour chaque côté de la boîte et le raccourci de margin ont tous été définis dans CSS1.

La spécification CSS2.1 a une illustration pour démontrer le modèle de boîte et définit également les termes que nous utilisons encore pour décrire les différentes boîtes. La spécification décrit la content box de padding box de border box et la margin box , chacune étant définie par les bords du contenu, le remplissage, la bordure et la marge respectivement.

schéma du modèle de boîte CSS
Description du CSS Box Model en CSS2

Il existe maintenant une spécification de modèle de boîte de niveau 3 en tant qu'ébauche de travail. Cette spécification renvoie à CSS2 pour les définitions du Box Model et des marges, c'est donc la définition CSS2 que nous utiliserons pour la majorité de cet article.

Plus après saut! Continuez à lire ci-dessous ↓

Effondrement de la marge

La spécification CSS1, telle qu'elle définit les marges, définit également que les marges verticales s'effondrent . Depuis lors, ce comportement d'effondrement est source de frustration liée aux marges. L'effondrement des marges est logique si l'on considère qu'à cette époque, CSS était utilisé comme langage de formatage de documentation. L'effondrement de la marge signifie que lorsqu'un titre avec une marge inférieure est suivi d'un paragraphe avec une marge supérieure, vous n'obtenez pas un écart énorme entre ces éléments.

Lorsque les marges s'effondrent, elles se combinent pour que l'espace entre les deux éléments devienne la plus grande des deux marges. La plus petite marge se retrouve essentiellement à l'intérieur de la plus grande.

Les marges s'effondrent dans les situations suivantes :

  • Frères et sœurs adjacents
  • Boîtes complètement vides
  • Parent et premier ou dernier élément enfant

Examinons tour à tour chacun de ces scénarios, avant d'examiner les éléments qui empêchent les marges de s'effondrer dans ces scénarios.

Frères et sœurs adjacents

Ma description initiale de l'effondrement des marges est une démonstration de la façon dont les marges entre frères et sœurs adjacents s'effondrent. En dehors des situations mentionnées ci-dessous, si vous avez deux éléments qui s'affichent l'un après l'autre dans un 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 y a trois éléments div . Le premier a une marge supérieure et inférieure de 50 pixels. Le second a une marge supérieure et inférieure de 20 pixels. Le troisième a une marge supérieure et inférieure de 3em. La marge entre les deux premiers éléments est de 50 pixels, car la plus petite marge supérieure est combinée avec la plus grande marge inférieure. La marge entre les deux deuxièmes éléments de 3em, car 3em est supérieure aux 20 pixels en bas du deuxième élément.

Voir le Pen [Marges : frères et sœurs adjacents](https://codepen.io/rachelandrew/pen/OevMPo) de Rachel Andrew.

Voir les marges du stylo : frères et sœurs adjacents par Rachel Andrew.

Boîtes complètement vides

Si une boîte est vide, ses marges supérieure et inférieure peuvent s'effondrer l'une avec l'autre. Dans l'exemple CodePen suivant, l'élément avec une classe 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 de 50. Cela est dû à l'effondrement des deux marges. L'ajout de quoi que ce soit à cette boîte (même le rembourrage) entraînera l'utilisation des marges supérieure et inférieure et ne s'effondrera pas.

Voir le Pen [Marges : cases vides](https://codepen.io/rachelandrew/pen/JQLGMr) de Rachel Andrew.

Voir les Pen Margins : cases vides de Rachel Andrew.

Parent et premier ou dernier élément enfant

C'est le scénario d'effondrement des marges qui surprend le plus souvent les gens, car il ne semble pas particulièrement intuitif. Dans le CodePen suivant, j'ai un div avec une classe de wrapper, et j'ai donné à ce div un outline en rouge afin que vous puissiez voir où il se trouve. Les trois éléments enfants ont tous une marge de 50 pixels. Cependant, le premier et le dernier élément affleurent les bords de l'emballage ; il n'y a pas de marge de 50 pixels entre l'élément et le wrapper.

Voir le Pen [Marges : marge sur le premier et le dernier enfant](https://codepen.io/rachelandrew/pen/BgrKGp) de Rachel Andrew.

Voir les marges du stylo : marge sur le premier et le dernier enfant par Rachel Andrew.

En effet, la marge sur l'enfant s'effondre avec toute marge sur le parent se retrouvant ainsi à l'extérieur du parent. Vous pouvez le voir si vous inspectez le premier enfant à l'aide de DevTools. La zone jaune en surbrillance est la marge.

L'élément avec une marge en surbrillance jaune qui s'affiche en dehors du parent
DepvTools peut vous aider à voir où se termine votre marge

Seuls les marges de bloc s'effondrent

Le dernier exemple met également en évidence quelque chose à propos de l'effondrement des marges. Dans CSS2, seules les marges verticales sont spécifiées pour s'effondrer - c'est-à-dire les marges supérieure et inférieure d'un élément si vous êtes en mode d'écriture horizontal. Ainsi, les marges gauche et droite ci-dessus ne s'effondrent pas et ne se retrouvent pas à l'extérieur de l'emballage.

Remarque : Il convient de rappeler que les marges ne s'effondrent que dans le sens du bloc, comme entre les paragraphes.

Choses qui empêchent la marge de s'effondrer

Les marges ne s'effondrent jamais si un élément a un positionnement absolu ou est flottant. Cependant, en supposant que vous avez rencontré l'un des endroits où les marges s'effondrent décrites ci-dessus, comment pouvez-vous empêcher ces marges de s'effondrer ?

La première chose qui cesse de s'effondrer, ce sont les situations où il y a quelque chose entre les éléments en question.

Par exemple, une boîte complètement vide de contenu ne réduira pas ses marges supérieure et inférieure si une bordure ou un rembourrage lui est appliqué. Dans l'exemple ci-dessous, j'ai ajouté 1px de rembourrage à la boîte. Il y a maintenant une marge de 50 pixels au-dessus et au-dessous de la boîte.

Voir le Pen [Marges : les cases vides avec rembourrage ne s'effondrent pas](https://codepen.io/rachelandrew/pen/gNeMpg) de Rachel Andrew.

Voir les marges du stylo : les cases vides avec rembourrage ne s'effondrent pas par Rachel Andrew.

Cela a une logique derrière cela, si la boîte est complètement vide sans bordure ni remplissage, elle est essentiellement invisible. Il peut s'agir d'un élément de paragraphe vide ajouté au balisage par votre CMS. Si votre CMS ajoutait des éléments de paragraphe redondants, vous ne voudriez probablement pas qu'ils provoquent de grands écarts entre les autres paragraphes en raison du respect de leurs marges. Ajoutez n'importe quoi à la boîte et vous obtiendrez ces lacunes.

Un comportement similaire peut être observé avec des marges sur le premier ou le dernier enfant qui s'effondrent à travers le parent. Si nous ajoutons une bordure au parent, les marges des enfants restent à l'intérieur.

Voir le stylo [Marges : la marge sur le premier et le dernier enfant ne s'effondre pas si le parent a une bordure](https://codepen.io/rachelandrew/pen/vqRKKX) par Rachel Andrew.

Voir les marges du stylo : la marge du premier et du dernier enfant ne s'effondre pas si le parent a une bordure de Rachel Andrew.

Encore une fois, il y a une certaine logique dans le comportement. Si vous avez des éléments d'habillage à des fins sémantiques qui ne s'affichent pas visuellement, vous ne voulez probablement pas qu'ils introduisent de grands écarts dans l'affichage. Cela avait beaucoup de sens lorsque le Web était principalement composé de texte. Il est moins utile en tant que comportement lorsque nous utilisons des éléments pour mettre en page une conception.

Création d'un contexte de formatage de bloc

Un nouveau contexte de formatage de bloc (BFC) empêchera également la marge de s'effondrer à travers l'élément conteneur. Si nous regardons à nouveau l'exemple du premier et du dernier enfant, se retrouvant avec leurs marges à l'extérieur du wrapper, et donnons au wrapper display: flow-root , créant ainsi un nouveau BFC, les marges restent à l'intérieur.

Voir le stylo [Marges : un nouveau contexte de formatage de bloc contient des marges](https://codepen.io/rachelandrew/pen/VJXjEp) de Rachel Andrew.

Voir les marges du stylo : un nouveau contexte de formatage de bloc contient des marges par Rachel Andrew.

Pour en savoir plus sur display: flow-root , lisez mon article « Understanding CSS Layout And The Block Formatting Context ». Changer la valeur de la propriété overflow en auto aura le même effet, car cela crée également un nouveau BFC, bien que cela puisse également créer des barres de défilement que vous ne vouliez pas dans certains scénarios.

Conteneurs flexibles et en grille

Les conteneurs Flex et Grid établissent des contextes de formatage Flex et Grid pour leurs enfants, de sorte qu'ils ont un comportement différent pour bloquer la mise en page. L'une de ces différences est que les marges ne s'effondrent pas :

« Un conteneur flexible établit un nouveau contexte de formatage flexible pour son contenu. Cela revient à établir un contexte de formatage de bloc, sauf que la disposition flexible est utilisée à la place de la disposition de bloc. Par exemple, les flottants n'empiètent pas sur le conteneur flexible, et les marges du conteneur flexible ne s'effondrent pas avec les marges de son contenu.

— Flexbox Niveau 1

Si nous prenons l'exemple ci-dessus et transformons le wrapper en conteneur flexible, en affichant les éléments avec flex-direction: column , vous pouvez voir que les marges sont maintenant contenues par le wrapper. De plus, les marges entre les éléments flexibles adjacents ne s'effondrent pas les unes avec les autres, nous nous retrouvons donc avec 100 pixels entre les éléments flexibles, le total des 50 pixels en haut et en bas des éléments.

Voir le stylo [Marges : les marges sur les éléments flexibles ne s'effondrent pas](https://codepen.io/rachelandrew/pen/mZxreL) de Rachel Andrew.

Voir les marges du stylo : les marges sur les éléments flexibles ne s'effondrent pas par Rachel Andrew.

Stratégies de marge pour votre site

En raison de l'effondrement des marges, il est judicieux de trouver une manière cohérente de gérer les marges sur votre site. La chose la plus simple à faire est de définir uniquement des marges en haut ou en bas des éléments. De cette façon, vous ne devriez pas rencontrer trop souvent des problèmes d'effondrement des marges car le côté avec une marge sera toujours adjacent à un côté sans marge.

Remarque : Harry Roberts a un excellent article détaillant les raisons pour lesquelles définir des marges dans une seule direction est une bonne idée, et pas seulement pour résoudre les problèmes d'effondrement des marges.

Cette solution ne résout pas les problèmes que vous pourriez rencontrer avec des marges sur les enfants qui s'effondrent à travers leur parent. Ce problème particulier a tendance à être moins courant, et savoir pourquoi il se produit peut vous aider à trouver une solution. Une solution idéale à cela est de donner aux composants qui le nécessitent un display: flow-root , comme solution de repli pour les anciens navigateurs, vous pouvez utiliser le overflow pour créer un BFC, transformer le parent en un conteneur flexible ou même introduire un seul pixel de rembourrage. N'oubliez pas que vous pouvez utiliser des requêtes de fonctionnalité pour détecter la prise en charge de display: flow-root afin que seuls les anciens navigateurs obtiennent une solution moins optimale.

La plupart du temps, je trouve que savoir pourquoi les marges s'effondrent (ou non) est l'élément clé. Vous pourrez ensuite déterminer au cas par cas comment y faire face. Quoi que vous choisissiez, assurez-vous de partager ces informations avec votre équipe. Très souvent, l'effondrement des marges est un peu mystérieux, donc la raison de faire des choses pour le contrer peut ne pas être évidente ! Un commentaire dans votre code est très utile - vous pouvez même créer un lien vers cet article et aider à partager les connaissances sur l'effondrement des marges.

J'ai pensé que je compléterais cet article avec quelques autres informations liées à la marge.

Marges en pourcentage

Lorsque vous utilisez un pourcentage en CSS, il doit s'agir d'un pourcentage de quelque chose. Les marges (et le remplissage) définies à l'aide de pourcentages seront toujours un pourcentage de la taille en ligne (largeur en mode d'écriture horizontal) du parent. Cela signifie que vous aurez un rembourrage de taille égale tout autour de l'élément lorsque vous utilisez des pourcentages.

Dans l'exemple CodePen ci-dessous, j'ai un emballage de 200 pixels de large, à l'intérieur se trouve une boîte qui a une marge de 10%, la marge est de 20 pixels de tous les côtés, soit 10% de 200.

Voir le Pen [Marges : marges en pourcentage](https://codepen.io/rachelandrew/pen/orqzrP) de Rachel Andrew.

Voir les marges du stylo : marges en pourcentage par Rachel Andrew.

Marges dans un monde relatif aux flux

Nous avons parlé de marges verticales tout au long de cet article, cependant, le CSS moderne a tendance à penser les choses de manière relative plutôt que physique. Par conséquent, lorsque nous parlons de marges verticales, nous parlons en fait de marges dans la dimension du bloc. Ces marges seront en haut et en bas si nous sommes en mode d'écriture horizontal, mais seraient à droite et à gauche dans un mode d'écriture vertical écrit de gauche à droite.

Une fois que vous travaillez avec des directions logiques et relatives de flux, il devient plus facile de parler de début et de fin de bloc, plutôt que de haut et de bas. Pour faciliter cela, CSS a introduit la spécification Logical Properties and Values. Cela mappe les propriétés relatives des flux sur les propriétés physiques.

Pour les marges, cela nous donne les mappages suivants (si nous travaillons en anglais ou tout autre mode d'écriture horizontal avec une direction de 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 nouveaux raccourcis qui permettent de définir les deux blocs à la fois ou les deux en ligne.

  • margin-block
  • margin-inline

Dans l'exemple CodePen suivant, j'ai utilisé ces mots-clés relatifs au flux, puis modifié le mode d'écriture de la boîte, vous pouvez voir comment les marges suivent la direction du texte plutôt que d'être liées au haut, à la droite, au bas et à la gauche physiques.

Voir le Pen [Margins: flow relative margins](https://codepen.io/rachelandrew/pen/BgrQRj) de Rachel Andrew.

Voir le Pen Margins: flow relative margins par Rachel Andrew.

Vous pouvez en savoir plus sur les propriétés et les valeurs logiques sur MDN ou dans mon article "Comprendre les propriétés et les valeurs logiques" ici sur Smashing Magazine.

Envelopper

Vous savez maintenant l'essentiel de ce qu'il y a à savoir sur les marges ! En bref:

  • L'effondrement de la marge est une chose. Comprendre pourquoi cela se produit et quand cela ne vous aidera pas à résoudre les problèmes que cela peut causer.
  • Définir des marges dans une seule direction ne résout que de nombreux maux de tête liés aux marges.
  • Comme pour tout en CSS, partagez avec votre équipe les décisions que vous prenez et commentez votre code.
  • Penser aux dimensions de bloc et en ligne plutôt qu'au haut, à droite, au bas et à gauche physiques vous aidera à mesure que le Web évolue vers un mode d'écriture agnostique.