¿Por qué no funciona: 0 funciona en elementos absolutamente posicionados en relación con el cuerpo?

Puede ver en el siguiente código que h1 empuja hacia abajo el cuerpo y que el bloque absolutamente posicionado. .absolute no se pega a la parte superior. Pero también puede ver que el mismo bloque está pegado a la parte superior de su .wrapper principal. ¿Por qué?

No estoy preguntando cómo hacer ese truco; Sé cómo, por ejemplo, el margen de relleno en lugar de h1, o clearfix para padres, y así sucesivamente.

Estoy interesado en una sola cosa: ¿por qué el margen de h1 empuja hacia abajo el body , pero no está presionando hacia .wrapper ? ¿ .wrapper ?

 body { position: relative; margin: 0; padding: 0; overflow: hidden; background-color: silver; } .absolute { position: absolute; top: 0; left: 0; width: 50px; height: 50px; background-color: darkblue; } .wrapper { position: relative; overflow:hidden; width: 50%; height: 200px; overflow: hidden; background-color: yellow; } .wrapper > .absolute { background-color: darkcyan; } 
 

Some title

Some title

OK, intentaré ser más claro. Si hace clic en el enlace a continuación, puede ver mi JSFiddle. Hay background-color: silver en la etiqueta del body . Cuando miro en el inspector de código, veo que la etiqueta del cuerpo comienza ligeramente más baja debido al margen h1. Pero background-color comienza en la parte superior. Esto significa que el inspector de código me está mintiendo, y el cuerpo comienza desde arriba. ¿Pero por qué, entonces, un elemento absolutamente posicionado que es un hijo directo del body no comienza en la parte superior?

JSFiddle

Como se mencionó, el bloque que contiene el elemento de posición absoluta de alto nivel es el body , ya que el body está relativamente posicionado. Cuando el margen de la h1 colapsa con el del body , esto hace que el margen afecte al body y, a su vez, al elemento absolutamente posicionado que contiene. Por el contrario, si el body no estaba relativamente posicionado, el elemento absolutamente posicionado estaría anclado al bloque contenedor inicial, y se adheriría a la parte superior de la ventana no afectado por ningún margen efectivo en el body (porque el body ya no es su bloque contenedor).

En cuanto a por qué el fondo plateado sangra más allá del elemento del body , eso es por diseño :

3.11.1. El fondo del canvas y el elemento raíz

El fondo del elemento raíz se convierte en el fondo del canvas y su área de pintura de fondo se extiende para cubrir todo el canvas. Sin embargo, cualquier imagen se dimensiona y coloca en relación con el elemento raíz como si se hubiera pintado solo para ese elemento. (En otras palabras, el área de posicionamiento de fondo se determina como para el elemento raíz). El elemento raíz no pinta este fondo nuevamente, es decir, el valor utilizado de su fondo es transparente.

3.11.2. El fondo del canvas y el elemento HTML

Para documentos cuyo elemento raíz es un elemento HTML HTML o un elemento html XHTML: si el valor calculado de ‘background-image’ en el elemento raíz es ‘none’ y su ‘background-color’ es ‘transparent’, los agentes de usuario deben en su lugar propagar los valores calculados de las propiedades de fondo del primer elemento hijo del body HTML BODY o XHTML de ese elemento. Los valores utilizados de las propiedades de fondo de ese elemento BODY son sus valores iniciales, y los valores propagados se tratan como si se especificaran en el elemento raíz. Se recomienda que los autores de documentos HTML especifiquen el fondo del canvas para el elemento BODY lugar del elemento HTML .

El color de fondo predeterminado del elemento raíz siempre es transparent , por lo que establecer un color de fondo en el elemento html evita que el fondo plateado se desangre del elemento del body (y verá que el inspector no le está mintiendo):

 html { background-color: white; } body { position: relative; margin: 0; padding: 0; overflow: hidden; background-color: silver; } .absolute { position: absolute; top: 0; left: 0; width: 50px; height: 50px; background-color: darkblue; } .wrapper { position: relative; overflow:hidden; width: 50%; height: 200px; overflow: hidden; background-color: yellow; } .wrapper > .absolute { background-color: darkcyan; } 
 

Some title

Some title

Es porque colapsa los márgenes . Cómo deshabilitarlo, puede leer algunos artículos / respuestas, por ejemplo, esto .
Está utilizando overflow: hidden para .wrapper , e inhabilita los márgenes de colapso para este bloque. De la especificación :

Los márgenes de una caja con ‘desbordamiento’ que no sea ‘visible’ no colapsan con los márgenes de sus hijos.

Pero parece que el overflow: hidden no funciona para , porque si configuro
height: 0 / max-height: 0 tampoco funciona:

 body { height: 0; max-height: 0; } 
 
Some test text

Esta es otra instancia del fenómeno conocido como margin-collapsing .

Trataré de explicar lo que está sucediendo:

Cuando mueve div.absolute con position absolute, lo saca del flujo del contenido. Esto hace que el primer h1 actúe como el primer hijo de su padre, que es el body en este caso.

El margen de la h1 se colapsa fuera del cuerpo, debido al colapso del margen. Es por eso que top: 0; no está en la esquina superior izquierda de la ventana gráfica. Está en la parte superior izquierda del body .

Si necesita hacer que esto funcione, agregue un html {position: relative; overflow: hidden:} html {position: relative; overflow: hidden:} .

Este es un comportamiento interesante con poca documentación en línea (al menos en una búsqueda básica).

Comenzaré diciendo que no sé la razón por la cual la caja absolutamente posicionada no se alinea con la esquina del body , como se esperaría. Pero aquí hay algunas observaciones:

  1. El posicionamiento esperado funciona en IE11. La brecha existe en Chrome y FF.

  2. Si elimina la position: relative del body , el posicionamiento esperado funciona (como se probó en Chrome, FF e IE11). manifestación

  3. Si aplica solo padding 1px al body , también funciona en el navegador cruzado. manifestación

  4. Si agrega un borde al body , también funciona. manifestación


ACTUALIZAR

Como una adición rápida a la respuesta aceptada de @ BoltClock , este problema podría haberse ilustrado y comprendido fácilmente simplemente al agregar un color de fondo al elemento raíz en el código original …

 html { background-color: red; } 

manifestación

… y eliminando el margen predeterminado en la h1 :

 h1 { margin: 0; } 

manifestación

Esto se debe a que h1 tiene un margen predeterminado, que mantiene el body separado de h1 y su hermano. .absolute .

Entonces, todo lo que tiene que hacer es restablecer el margen en h1 , como lo hizo para el body :

fragmento con cada margen restablecido

 body { position: relative; margin: 0; padding: 0; overflow: hidden; background-color: silver; } h1 { margin: 0; /*if you want to see full text, put this into the flow*/ position:relative; z-index:1; } .absolute { position: absolute; top: 0; left: 0; width: 50px; height: 50px; background-color: darkblue; } .wrapper { position: relative; overflow: hidden; width: 50%; height: 200px; overflow: hidden; background-color: yellow; } .wrapper > .absolute { background-color: darkcyan; } 
 

Some title

Some title