131 votes

Comment fonctionnent les marges négatives en CSS et pourquoi (margin-top:-5 != margin-bottom:5) ?

Une astuce courante pour le positionnement vertical des éléments consiste à utiliser le CSS suivant :

.item {
    position:absolute;
    top:50%;
    margin-top:-8px; /* half of height */
    height: 16px;
}

Voici ce que l'on voit dans la vue métrique comme dans Chrome :

enter image description here

Cependant, aucune marge visuelle n'est représentée lorsque vous passez le curseur sur l'élément, c'est-à-dire que la marge se trouve "à l'extérieur" de la bordure et peut être visualisée. Mais les marges négatives n'apparaissent pas. Comment se présentent-elles et qu'est-ce qui les rend différentes ?

Pourquoi est-ce que margin-top:-8px pas la même chose que margin-bottom:8px ?

Alors comment fonctionnent les marges négatives et quelle est l'intuition qui les sous-tend ? Comment font-elles pour " remonter " (dans le cas de la marge négative) ? margin-top < 0 ) un article ?

109voto

o.v. Points 11173

Les marges négatives sont valides en css et la compréhension de leur comportement (conforme) est principalement basée sur l'élément suivant modèle de boîte et l'effondrement des marges. Bien que certains scénarios soient plus complexes, un grand nombre d'erreurs courantes peuvent être évitées après avoir étudié la spécification.

Par exemple, le rendu de votre code d'exemple est guidé par la spécification css telle que décrite dans le document calcul des hauteurs et des marges pour les éléments non remplacés positionnés de manière absolue .

Si je devais faire une représentation graphique, je choisirais probablement quelque chose comme ceci (pas à l'échelle) :

negative top margin

Le site boîte de marge perdue 8px sur la partie supérieure, mais cela n'affecte pas l'efficacité de l'opération. boîtes de contenu et de rembourrage . Comme votre élément est positionné de manière absolue, le fait de le déplacer de 8px vers le haut ne perturbe pas davantage la mise en page ; ce n'est pas toujours le cas avec du contenu statique en flux continu.

Bonus :

Il faut toujours convaincre que lire les spécifications est le site (par opposition à des articles comme celui-ci ) ? Je vois que vous essayez de centrer verticalement l'élément, alors pourquoi devez-vous définir l'option margin-top:-8px; et non margin-top:-50%; ?

Eh bien, le centrage vertical en CSS est plus difficile qu'il ne devrait l'être . Lorsque vous réglez même top ou fond marges en %, la valeur est calculée comme suit un pourcentage toujours relatif à la largeur du bloc contenant . Il s'agit d'un piège assez courant et la bizarrerie est rarement décrite en dehors des documents du W3.

1 votes

Essayez de définir margin-top : -50% et l'élément sort de l'écran.

0 votes

Alors pourquoi devez-vous définir margin-top:-8px ; et non margin-top:-50%; ? C'est ce qui a été dit dans la réponse ci-dessus, qui n'est pas la solution pour margin-top:-8px ; parce que l'élément est positionné de manière absolue. Si vous voulez déplacer quelque chose à la moitié de sa hauteur, utilisez transform comme : transform : translateY(-50%) ; cela fonctionnerait également sur la hauteur dynamique. margin-top:-50% prendrait cet élément à 50% en négatif de la hauteur du parent et non à sa propre hauteur. Donc, ajustez toujours les éléments absolus avec transform.

0 votes

@AtulRajput Je pense que la question portait spécifiquement sur la différence entre margin-top:-XXpx vs margin-bottom:XXpx . En ce qui concerne les valeurs basées sur le pourcentage, j'ai cherché à faire référence à la spécification décrivant que les marges verticales basées sur le pourcentage sont calculées en tant que pourcentage par rapport à l'indice de référence. largeur du bloc contenant. C'était très peu intuitif pour moi ! Vous avez raison de dire que translateY les transformations permettent souvent d'obtenir l'effet désiré, mais elles ont aussi leurs propres particularités, comme la création de nouveaux contextes d'empilement qui peuvent entrer en conflit avec les z-index souhaités (et, selon l'IIRC, elles fonctionnent parfois de manière peu intuitive avec des transformations imbriquées).

95voto

Ana Points 19473

Je vais essayer de l'expliquer visuellement :

/**
 * explaining margins
 */

body {
  padding: 3em 15%
}

.parent {
  width: 50%;
  width: 400px;
  height: 400px;
  position: relative;
  background: lemonchiffon;
}

.parent:before,
.parent:after {
  position: absolute;
  content: "";
}

.parent:before {
  top: 0;
  bottom: 0;
  left: 50%;
  border-left: dashed 1px #ccc;
}

.parent:after {
  left: 0;
  right: 0;
  top: 50%;
  border-top: dashed 1px #ccc;
}

.child {
  width: 200px;
  height: 200px;
  background: rgba(200, 198, 133, .5);
}

ul {
  padding: 5% 20px;
}

.set1 .child {
  margin: 0;
  position: relative;
}

.set2 .child {
  margin-left: 75px;
  position: relative;
}

.set3 .child {
  margin-left: -75px;
  position: relative;
}

/* position absolute */

.set4 .child {
  top: 50%;
  left: 50%;
  margin: 0;
  position: absolute;
}

.set5 .child {
  top: 50%;
  left: 50%;
  margin-left: 75px;
  position: absolute;
}

.set6 .child {
  top: 50%; /* level from which margin-top starts 
    - downwards, in the case of a positive margin
    - upwards, in the case of a negative margin 
    */
  left: 50%; /* level from which margin-left starts 
    - towards right, in the case of a positive margin
    - towards left, in the case of a negative margin    
    */
  margin: -75px;
  position: absolute;
}

<!-- content to be placed inside <body>…</body> -->
<h2><code>position: relative;</code></h2>
<h3>Set 1</h3>
<div class="parent set 1">
  <div class="child">
    <pre>
.set1 .child {
  margin: 0;
  position: relative;
}
        </pre>
  </div>
</div>

<h3>Set 2</h3>
<div class="parent set2">
  <div class="child">
    <pre>
.set2 .child {
  margin-left: 75px;
  position: relative;
}
        </pre>
  </div>
</div>

<h3>Set 3</h3>
<div class="parent set3">
  <div class="child">
    <pre>
.set3 .child {
  margin-left: -75px;
  position: relative;
}
        </pre>
  </div>
</div>

<h2><code>position: absolute;</code></h2>

<h3>Set 4</h3>
<div class="parent set4">
  <div class="child">
    <pre>
.set4 .child {
  top: 50%;
  left: 50%;
  margin: 0;
  position: absolute;
}
        </pre>
  </div>
</div>

<h3>Set 5</h3>
<div class="parent set5">
  <div class="child">
    <pre>
.set5 .child {
  top: 50%;
  left: 50%;
  margin-left: 75px;
  position: absolute;
}
        </pre>
  </div>
</div>

<h3>Set 6</h3>
<div class="parent set6">
  <div class="child">
    <pre>
.set6 .child {
  top: 50%;
  left: 50%;
  margin: -75px;
  position: absolute;
}
        </pre>
  </div>
</div>

42voto

David Hedlund Points 66192

La marge est l'espacement à l'extérieur de votre élément, tout comme le remplissage est l'espacement à l'intérieur de votre élément.

La définition de la marge inférieure indique la distance que vous souhaitez avoir en dessous du bloc actuel. La définition d'une marge supérieure négative indique que vous souhaitez un espacement négatif au-dessus de votre bloc. L'espacement négatif peut en soi être un concept déroutant, mais de la même manière qu'une marge supérieure positive pousse le contenu vers le bas, une marge supérieure négative tire le contenu vers le haut.

2 votes

+1 J'aime votre réponse. Elle peut être améliorée en injectant les mots onset et offset . C'est vrai que tant de gens utilisent toujours le mot offset ( négatif ) quand ils veulent dire onset ( positif ). Ce message s'autodétruira si vous mettez à jour votre réponse. A la vôtre !

2 votes

Qu'en est-il margin-bottom: -8px; ? Pourquoi le margin-bottom:-8px pas la même chose que margin-top:-8px ?

0 votes

Que se passe-t-il si vous utilisez à la fois une marge supérieure négative et une marge inférieure négative ? Sera-t-elle poussée vers le bas ou vers le haut ?

31voto

schellmax Points 1830

De bons points déjà faits ici, mais alors qu'il y a beaucoup d'informations sur comment le rendu des marges est effectué par le navigateur, le pourquoi n'a pas encore trouvé de réponse :

"Pourquoi margin-top:-8px n'est pas la même chose que margin-bottom:8px ?"

ce que nous pourrions également demander est :

Pourquoi une marge inférieure positive ne "remonte" pas les éléments précédents, alors qu'une marge supérieure positive "descend" les éléments suivants ?

donc ce que nous voyons c'est qu'il y a différence dans le rendu des marges selon le côté sur lequel elles sont appliquées - les marges supérieures (et gauches) sont différentes des marges inférieures (et droites).

Les choses deviennent plus claires lorsqu'on examine (de manière simplifiée) la manière dont les styles sont appliqués par le navigateur : les éléments sont rendus de haut en bas dans la fenêtre d'affichage, en commençant par le coin supérieur gauche (tenons-nous-en à un rendu vertical pour l'instant, en gardant à l'esprit que le rendu horizontal est traité de la même manière).

Considérons le html suivant :

<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>

De manière analogue à leur position dans le code, ces trois boîtes apparaissent empilées "de haut en bas" dans le navigateur ( Pour garder les choses simples, nous ne considérerons pas ici la order propriété du module css3 'flex-box'. ). Ainsi, lorsque les styles sont appliqués à la case 3, les positions des éléments précédents (pour les cases 1 et 2) ont déjà été déterminées et ne doivent plus être modifiées pour des raisons de vitesse de rendu.

imaginez maintenant une marge supérieure de -10px pour la boîte 3. au lieu de décaler vers le haut tous les éléments précédents pour gagner de l'espace, le navigateur va simplement pousser la boîte 3 vers le haut, de sorte qu'elle est rendue au-dessus (ou en dessous, en fonction de l'indice z) de tous les éléments précédents. même si les performances n'étaient pas un problème, déplacer tous les éléments vers le haut pourrait signifier les décaler hors de la fenêtre d'affichage, et donc la position de défilement actuelle devrait être modifiée pour que tout soit à nouveau visible.

Il en va de même pour la marge inférieure de la case 3, qu'elle soit négative ou positive : au lieu d'influencer les éléments déjà évalués, seul un nouveau "point de départ" pour les éléments à venir est déterminé. ainsi, la définition d'une marge inférieure positive poussera la case 3 vers le haut. suivant des éléments vers le bas ; un élément négatif les poussera vers le haut.

0 votes

LA MEILLEURE réponse. Celle-ci explique également le "pourquoi", alors que les autres réponses n'expliquent que le "comment".

1 votes

Cette réponse m'a aidé à mieux comprendre le pourquoi. Merci @schellmax

31voto

Rich Bradshaw Points 33598

Une marge supérieure de -8px signifie qu'il sera 8px plus haut que s'il n'avait pas de marge.

Une marge inférieure de 8px signifie que la chose qui se trouve en dessous sera 8px plus bas que si elle n'avait pas de marge.

1 votes

J'essayais juste de garder les choses simples, mais je suis d'accord, c'est probablement la plus mal écrite de mes réponses !

3 votes

Je pense que la réponse est plutôt bonne. Pas besoin de réponses très techniques que la moitié d'entre nous ne comprend pas.

1 votes

Qu'en est-il margin-bottom: -8px; ? Pourquoi le margin-bottom:-8px pas la même chose que margin-top:-8px ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X