¿Cómo funcionan los márgenes negativos en CSS y por qué (margin-top: -5! = Margin-bottom: 5)?

108

Un truco común para los elementos de posicionamiento vertical es utilizar el siguiente CSS:

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

Cuando se ve en la vista métrica como en Chrome, esto es lo que ve:

ingrese la descripción de la imagen aquí

Sin embargo, no hay un margen visual representado cuando pasa el cursor sobre el elemento, es decir, el margen está "fuera" del borde y se puede visualizar. Pero los márgenes negativos no aparecen. ¿Cómo se ven y qué es lo que lo hace diferente?

¿Por qué margin-top:-8px no es lo mismo quemargin-bottom:8px ?

Entonces, ¿cómo funcionan los márgenes negativos y cuál es la intuición detrás de ellos? ¿Cómo 'suben' (en el caso de margin-top < 0) un artículo?

Doctor
fuente

Respuestas:

89

Los márgenes negativos son válidos en CSS y la comprensión de su comportamiento (compatible) se basa principalmente en el modelo de caja y el colapso de los márgenes. Si bien ciertos escenarios son más complejos, se pueden evitar muchos errores comunes después de estudiar la especificación.

Por ejemplo, la representación de su código de muestra está guiada por la especificación css como se describe en el cálculo de alturas y márgenes para elementos no reemplazados absolutamente posicionados .

Si tuviera que hacer una representación gráfica, probablemente iría con algo como esto (no a escala):

margen superior negativo

El cuadro de margen se pierde 8pxen la parte superior, sin embargo, esto no afecta el contenido y los cuadros de relleno . Debido a que su elemento está absolutamente posicionado, mover el elemento 8px hacia arriba no causa ninguna alteración adicional en el diseño; con contenido de flujo de entrada estático, ese no es siempre el caso.

Prima:

¿Todavía necesitas convencerte de que leer las especificaciones es el camino a seguir (a diferencia de artículos como este )? Veo que estás intentando centrar verticalmente el elemento, entonces, ¿por qué tienes que configurarlo margin-top:-8px;y no margin-top:-50%;?

Bueno, el centrado vertical en CSS es más difícil de lo que debería ser . Al establecer incluso los márgenes superior o inferior en%, el valor se calcula como un porcentaje siempre relativo al ancho del bloque contenedor . Este es un error bastante común y la peculiaridad rara vez se describe fuera de w3 docos

ov
fuente
84

Intentaré explicarlo visualmente:

/**
 * 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
fuente
33

El margen es el espacio fuera de su elemento, al igual que el relleno es el espacio dentro de su elemento.

Establecer el margen inferior indica la distancia que desea debajo del bloque actual. Establecer un margen superior negativo indica que desea un espacio negativo sobre su bloque. El espaciado negativo puede ser en sí mismo un concepto confuso, pero de la misma manera en que el margen superior positivo empuja el contenido hacia abajo, un margen superior negativo tira el contenido hacia arriba.

David Hedlund
fuente
2
+1 Me gusta tu respuesta. Se puede mejorar inyectando las palabras onsety offset. Es cierto que muchas personas siempre usan la palabra offset( negativo ) cuando quieren decir onset( positivo ). Este mensaje se autodestruirá si actualiza su respuesta. ¡Salud!
arttronics
1
¿Qué hay de margin-bottom: -8px;? ¿Por qué margin-bottom:-8pxno es lo mismo que margin-top:-8px?
Rick
27

Un margen superior de -8px significa que será 8px más alto que si tuviera un margen 0.

Un margen inferior de 8px significa que lo que está debajo estará 8px más abajo que si tuviera un margen de 0.

Rich Bradshaw
fuente
1
Solo estaba tratando de mantener las cosas simples, pero estoy de acuerdo, ¡esta es posiblemente la peor de mis respuestas escritas!
Rich Bradshaw
2
Creo que la respuesta es bastante buena. No hay uso de respuestas altamente técnicas que la mitad de nosotros no lo entendemos.
Number945
1
¿Qué hay de margin-bottom: -8px;? ¿Por qué margin-bottom:-8pxno es lo mismo que margin-top:-8px?
Rick
22

Ya se han hecho buenos puntos aquí, pero si bien hay mucha información sobre cómo el navegador logra la representación de los márgenes, el por qué aún no se ha respondido del todo:

"¿Por qué margin-top: -8px no es lo mismo que margin-bottom: 8px?"

lo que también podríamos preguntar es:

¿Por qué un margen inferior positivo no "sube" los elementos precedentes, mientras que un margen superior positivo "baja" los elementos siguientes?

así que lo que vemos es que hay una diferencia en la representación de los márgenes dependiendo del lado al que se aplican : los márgenes superior (e izquierdo) son diferentes de los inferiores (y derecho).

Las cosas se vuelven más claras cuando se tiene una mirada (simplificada) de cómo el navegador aplica los estilos: los elementos se representan de arriba hacia abajo en la ventana gráfica, comenzando en la esquina superior izquierda (sigamos con la representación vertical por ahora, teniendo en cuenta que el horizontal se trata igual).

considere el siguiente html:

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

De manera análoga a su posición en el código, estas tres cajas aparecen apiladas 'de arriba hacia abajo' en el navegador ( manteniendo las cosas simples, no consideraremos aquí la orderpropiedad del módulo css3 'flex-box' ). por lo tanto, siempre que se apliquen estilos a la casilla 3, las posiciones del elemento anterior (para las casillas 1 y 2) ya se han determinado y no deben modificarse más por el bien de la velocidad de renderizado.

ahora, imagine un margen superior de -10px para el cuadro 3. en lugar de desplazar hacia arriba todos los elementos anteriores para reunir algo de espacio, el navegador simplemente empujará el cuadro 3 hacia arriba, por lo que se representa en la parte superior (o debajo, según el índice z ) cualquier elemento anterior. incluso si el rendimiento no fuera un problema, mover todos los elementos hacia arriba podría significar desplazarlos fuera de la ventana gráfica, por lo que la posición de desplazamiento actual tendría que modificarse para que todo vuelva a estar visible.

Lo mismo se aplica a un margen inferior para el recuadro 3, tanto negativo como positivo: en lugar de influir en los elementos ya evaluados, solo se determina un nuevo "punto de partida" para los elementos futuros. así, establecer un margen inferior positivo empujará hacia abajo los siguientes elementos; uno negativo los empujará hacia arriba.

schellmax
fuente
LA MEJOR respuesta. Esta también explica el "por qué", mientras que las otras respuestas solo explican el "cómo".
Amir Hossein Ahmadi
1
Esta respuesta me ayudó a comprender mejor el por qué. Gracias @schellmax
iRamesh
3

Debido a que ha utilizado el posicionamiento absoluto y ha especificado un porcentaje superior, solo margin-top afectará la ubicación de su objeto .item. Si, en cambio, lo colocó usando bottom: 50%, entonces necesitaría margin-bottom -8px para centrarlo, y margin-top no tendría ningún efecto.

El margen afecta los límites de un elemento en términos de posicionamiento, ya sea absolutamente como en su caso, o en relación con los elementos vecinos. Imagina que ese margen es la base de tu elemento sobre el que se asienta. Por lo general, tienen el mismo tamaño, pero pueden agrandarse o reducirse en cualquiera o en todos los cuatro bordes.

Su CSS le dice al navegador que coloque la parte superior de su elemento en el margen en un punto del 50% del camino hacia abajo en la página. Sin embargo, como todos los elementos no son un solo píxel, el navegador necesita saber qué parte alinear el 50% del camino hacia abajo en la página. Para alinear la parte superior del elemento, utiliza el margen superior. De forma predeterminada, esto está en línea con la parte superior del elemento, pero puede modificarlo con CSS.

En su caso, el 50% superior daría como resultado que la parte superior del elemento comenzara en el medio de la página. Al aplicar un margen superior negativo, el navegador usa el punto 8px en el elemento desde la parte superior (es decir, la línea en el medio) como el lugar para posicionar al 50%.

Si aplica un margen positivo en la parte inferior, esto extiende la línea que el navegador usa para colocar la parte inferior lejos del elemento en sí, dando un espacio entre él y cualquier elemento adyacente debajo, o afectando dónde se coloca absolutamente si el posicionamiento se basa en El fondo.

Rob Trickey
fuente
+1. Tiene sentido ... sería genial aumentarlo con señales visuales para completar la visualización .
PhD
3

Me pregunto si esta pregunta se ha respondido bien: cómo funcionan los márgenes CSS y por qué es ese margin-top: -5; no es lo mismo que margin-bottom: 5 ;?

El margen es la distancia del entorno del elemento. margin-top dice "... distancia desde el entorno cuando medimos desde el 'lado' superior de la 'caja' del elemento y margin-bottom es la distancia desde el 'lado' inferior de la 'caja'". Luego margin-top: 5; se refiere al perímetro 'lateral' superior, -5 en ese caso; cualquier cosa que se acerque desde el 'lado' superior puede superponerse al 'lado' superior del elemento en 5, y el margen inferior: 5; significa que la distancia entre la parte inferior del elemento y el entorno es 5.

Básicamente eso, pero afectado por elementos flotantes y similares: http://www.w3.org/TR/CSS2/box.html#margin-properties .

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

Estoy para que me corrijan.

Tal vez
fuente