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

108

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

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

Lorsque vous le voyez dans la vue métrique comme dans Chrome, voici ce que vous voyez:

entrez la description de l'image ici

Cependant, il n'y a pas de marge visuelle représentée lorsque vous survolez l'élément, c'est-à-dire que la marge est «à l'extérieur» de la bordure et peut être visualisée. Mais les marges négatives n'apparaissent pas. À quoi ressemblent-ils et qu'est-ce qui le rend différent?

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

Alors, comment fonctionnent les marges négatives et quelle est l'intuition derrière elles. Comment font-ils «remonter» (en cas de margin-top < 0) un objet?

Doctorat
la source

Réponses:

89

Les marges négatives sont valides en css et la compréhension de leur comportement (conforme) repose principalement sur le modèle de boîte et la réduction des marges. Bien que certains scénarios soient plus complexes, de nombreuses erreurs courantes peuvent être évitées après avoir étudié les spécifications.

Par exemple, le rendu de votre exemple de code est guidé par la spécification css, comme décrit dans le 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, j'irais probablement avec quelque chose comme ça (pas à l'échelle):

marge supérieure négative

La zone de marge est perdue 8pxen haut, mais cela n'affecte pas le contenu et les zones de remplissage . Parce que votre élément est positionné de manière absolue, le déplacement de l'élément 8px vers le haut ne cause aucune autre perturbation de la disposition; avec du contenu statique en flux, ce n'est pas toujours le cas.

Prime:

Vous avez encore besoin de convaincre que la lecture des spécifications est la voie à suivre (par opposition à des articles comme celui-ci )? Je vois que vous essayez de centrer verticalement l'élément, alors pourquoi devez-vous définir margin-top:-8px;et non margin-top:-50%;?

Eh bien, le centrage vertical en CSS est plus difficile qu'il ne devrait l'être . Lors de la définition des marges supérieures ou inférieures en%, la valeur est calculée en pourcentage toujours par rapport à la largeur du bloc conteneur . C'est plutôt un écueil courant et la bizarrerie est rarement décrite en dehors de w3 docos

ov
la source
84

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>

Ana
la source
33

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 souhaitée sous le 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 juste la façon dont la marge supérieure positive pousse le contenu vers le bas, une marge supérieure négative tire le contenu vers le haut.

David Hedlund
la source
2
+1 J'aime ta réponse. Il peut être amélioré en injectant les mots onsetet offset. C'est vrai que beaucoup 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. À votre santé!
arttronics
1
Et quoi margin-bottom: -8px;? Pourquoi n'est-ce margin-bottom:-8pxpas la même chose que margin-top:-8px?
Rick
27

Une marge supérieure de -8px signifie qu'elle sera 8px plus élevée que si elle avait 0 marge.

Une marge inférieure de 8px signifie que la chose en dessous sera 8px plus bas que si elle avait 0 marge.

Rich Bradshaw
la source
1
J'essayais juste de garder les choses simples, mais je suis d'accord, c'est peut-être la pire réponse de mes réponses!
Rich Bradshaw
2
Je pense que la réponse est plutôt bonne. Aucune utilisation de réponses hautement techniques que la moitié d'entre nous ne comprend pas.
Numéro945
1
Et quoi margin-bottom: -8px;? Pourquoi n'est-ce margin-bottom:-8pxpas la même chose que margin-top:-8px?
Rick
22

bons points déjà soulevés ici, mais bien qu'il y ait beaucoup d'informations sur la façon dont le rendu des marges est accompli par le navigateur, le pourquoi n'est pas encore tout à fait répondu:

"Pourquoi margin-top: -8px est-il différent de margin-bottom: 8px?"

ce que nous pourrions également demander, c'est:

Pourquoi une marge inférieure positive ne «saute-t-elle pas» sur les éléments précédents, alors qu'une marge supérieure positive «renverse» les éléments suivants?

donc ce que nous voyons, c'est qu'il y a une différence dans le rendu des marges selon le côté auquel elles sont appliquées - les marges du haut (et de gauche) sont différentes de celles du bas (et de droite).

les choses deviennent plus claires lorsqu'on regarde (simplifié) comment les styles sont appliqués par le navigateur: les éléments sont rendus de haut en bas dans la fenêtre, en commençant dans le coin supérieur gauche (restons fidèles au rendu vertical pour le moment, en gardant à l'esprit que l'horizontale est traitée de la même manière).

considérez 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 cases apparaissent empilées «de haut en bas» dans le navigateur ( pour simplifier les choses, nous ne considérerons pas ici la orderpropriété du module css3 «flex-box» ). ainsi, chaque fois que des styles sont appliqués à la boîte 3, les positions des éléments précédents (pour les boîtes 1 et 2) ont déjà été déterminées et ne devraient plus être modifiées pour des raisons de vitesse de rendu.

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

il en va de même pour une marge inférieure pour la case 3, à la fois négative et positive: au lieu d'influencer des éléments déjà évalués, seul un nouveau «point de départ» pour les éléments à venir est déterminé. ainsi définir une marge inférieure positive poussera les éléments suivants vers le bas; un négatif les poussera vers le haut.

schellmax
la source
LA MEILLEURE réponse. Celui-ci explique également le «pourquoi», tandis que les autres réponses n'expliquent que le «comment».
Amir Hossein Ahmadi
1
Cette réponse m'a aidé à mieux comprendre pourquoi. Merci @schellmax
iRamesh
3

Étant donné que vous avez utilisé le positionnement absolu et spécifié un pourcentage supérieur, seule la marge supérieure affectera l'emplacement de votre objet .item. Si à la place vous le positionniez en utilisant bottom: 50%, alors vous auriez besoin de margin-bottom -8px pour le centrer, et margin-top n'aurait aucun effet.

La marge affecte les limites d'un élément en termes de positionnement, soit absolument comme dans votre cas, soit par rapport aux éléments voisins. Imaginez que la marge soit le fondement de votre élément sur lequel il repose. Ils sont généralement de la même taille, mais peuvent être agrandis ou plus petits sur l'un ou l'ensemble des quatre bords.

Votre CSS indique au navigateur de positionner le haut de votre élément, la marge à un point situé à 50% du bas de la page. Cependant, comme tous les éléments ne sont pas un seul pixel, le navigateur a besoin de savoir quelle partie doit s'aligner sur 50% du bas de la page. Pour aligner le haut de l'élément, il utilise la marge supérieure. Par défaut, cela correspond au haut de l'élément, mais vous pouvez le modifier avec CSS.

Dans votre cas, les 50% supérieurs entraîneraient le début du haut de l'élément au milieu de la page. En appliquant une marge supérieure négative, le navigateur utilise le point 8px dans l'élément à partir du haut (c'est-à-dire la ligne au milieu de celui-ci) comme emplacement à 50%.

Si vous appliquez une marge positive vers le bas, cela prolonge la ligne que le navigateur utilise pour positionner le bas à l'écart de l'élément lui-même, ce qui laisse un espace entre celui-ci et tout élément adjacent ci-dessous, ou affecte l'endroit où il est placé absolument si le positionnement est basé sur le fond.

Rob Trickey
la source
+1. Cela a du sens ... ce serait formidable de l'augmenter avec des indices visuels afin de compléter la visualisation .
PhD
3

Je me demande si on a bien répondu à cette question: comment fonctionnent les marges css et pourquoi est-ce que margin-top: -5; n'est pas la même chose que margin-bottom: 5 ;?

La marge correspond à la distance par rapport aux environs de l'élément. margin-top dit "... la distance par rapport aux environs lorsque nous mesurons à partir du" côté "supérieur de la" boîte "de l'élément et la marge inférieure étant la distance du" côté "inférieur de la" boîte "". Puis margin-top: 5; concerne le périmètre «latéral» supérieur, -5 dans ce cas; tout ce qui s'approche du «côté» supérieur peut chevaucher le «côté» supérieur de l'élément de 5, et la marge inférieure: 5; signifie que la distance entre le «côté» inférieur de l'élément et l'entourage est de 5.

Fondamentalement, cela, mais affecté par les éléments flottants et autres: http://www.w3.org/TR/CSS2/box.html#margin-properties .

http://coding.smashingmagazine.com/2009/07/27/the-definitive-guide-to-using-negative-margins/

Je tiens à être corrigé.

Peut être
la source