margenes - margin collapse css
CSS: soluciĆ³n limpia al problema de colapso de margen cuando se flota un elemento (7)
Ejemplo HTML + CSS:
<html>
<body style="padding: 0; margin: 0;">
<div style="float: right;">first</div>
<div style="margin-top: 2em;">second</div>
</body>
</html>
Comportamiento deseado: el first
div flota en la parte superior derecha de la ventana. Comportamiento real: flota 2em por debajo de la posición deseada. Motivo: colapso del margen .
A pesar de identificar el problema, las soluciones que se me ocurren son como hackers:
- cambie
body
estilo delbody
almargin: -1px 0 0 0; border-top: 1px solid;
margin: -1px 0 0 0; border-top: 1px solid;
. - inserte
<div style="height: 1px; margin-bottom: -1px;"></div>
antesfirst
- inserte el
<div>
entre elfirst
y elsecond
¿Hay una manera limpia e idiomática de evitar este problema?
SOLUCIÓN
agregar overflow: auto;
o overflow: hidden;
o overflow: scroll;
tanto html
como body
tag
SI QUIERES SABER POR QUÉ
Crear el contexto de formato de bloque (BFC) en body
etiqueta de body
.
Por qué no funciona si agrego overflow: hidden;
solo al body
?
Aquí es por qué:
Los flotantes, elementos absolutamente posicionados, bloquean contenedores (como bloques en línea, celdas de tabla y leyendas de tablas) que no son cuadros de bloques y bloquean cuadros con ''desbordamiento'' que no sean ''visibles'' ( excepto cuando ese valor se ha propagado a la ventana gráfica ) establecer nuevos contextos de formato de bloque para sus contenidos.
Los UA deben aplicar el conjunto de propiedades ''overflow'' en el elemento raíz a la ventana gráfica.
Cuando el elemento raíz es un elemento HTML "HTML" o un elemento "html" XHTML, y ese elemento tiene un elemento HTML "BODY" o un elemento "body" XHTML como elemento secundario, los agentes de usuario deben aplicar la propiedad ''overflow'' desde el primer elemento secundario de ese tipo hasta la ventana gráfica, si el valor en el elemento raíz es ''visible'' .
El valor ''visible'' cuando se usa para la ventana gráfica debe interpretarse como ''auto''.
El elemento a partir del cual se propaga el valor debe tener un valor utilizado para ''desbordamiento'' de ''visible'' .
the first such child element
y The element from which the value is propagated
refieren a body
etiqueta física en este caso.
En otras palabras, si agrega overflow: hidden;
o overflow: auto;
o overflow: scroll;
al body
mientras el valor de la propiedad de overflow
de html
es visible
, el valor de la propiedad de overflow
del body
( hidden
o auto
o scroll
) se propagará a la ventana gráfica. De acuerdo con la primera cita del W3C, el body
no establecería un nuevo contexto de formato de bloque.
Sin embargo, si agrega overflow: hidden;
o overflow: auto;
o overflow: scroll;
a html
, el valor de overflow
de ''cuerpo'' no se propagaría y, por lo tanto, establecería un nuevo contexto de formato de bloque.
Agregar float: left;
a la segunda div.
Agregar overflow: hidden;
para el body
debería resolver tu problema. Define un nuevo contexto de formato de bloque como se describe en este artículo: La magia del desbordamiento: oculta .
Demostración de jsFiddle (la etiqueta de body
se agrega automáticamente por jsFiddle, es por eso que no la he incluido en el marcado HTML)
ACTUALIZACIÓN (gracias a @clairesuzy): esta solución no funciona si el body
tiene padding: 0
. Hasta que pueda encontrar una mejor manera, solo puedo sugerir agregar un envoltorio alrededor de los dos divs (al menos merezco ahora @ Marcel''s downwote :)), que aún creo que es más limpio que las soluciones publicadas por el OP. Normalmente, siempre agrego un envoltorio alrededor de materia flotante (hace que sea más fácil manejar navegadores antiguos la mayor parte del tiempo), la mayoría de las veces no necesita ser agregado deliberadamente, porque es lógico y semánticamente necesario.
Entonces, por ahora, puedo pensar en esto:
<body style="padding: 0; margin: 0;">
<div id="container" style="overflow: hidden;">
<div style="float: right;">first</div>
<div style="margin-top: 2em;">second</div>
</div>
</body>
ACTUALIZACIÓN 2 : Después de pensarlo bien, y leer comentarios, realmente creo que el overflow: hidden
(o cualquier otra cosa que no sea overflow: visible
) en el contenedor es la solución correcta. La única excepción en que no funcionó para mí es configurarlo en el elemento del body
, que de todos modos es una situación muy rara. En estas situaciones raras, puede intentar usar position: absolute; top: 0; right: 0;
position: absolute; top: 0; right: 0;
en lugar de flotar
Otra solución posible: también he encontrado esa display: inline-block; width: 100%;
configuración display: inline-block; width: 100%;
display: inline-block; width: 100%;
en el body
funciona de hecho.
En el div
principal, agregue este #parent {padding 1px 0; }
#parent {padding 1px 0; }
este fue un gran problema para mí y me llevó para siempre encontrar una solución. Vi en una publicación como 2 años y esto solucionó el colapso.
Las especificaciones W3C describen esto sobre los márgenes de colapso:
"En esta especificación, la expresión que colapsa los márgenes significa que los márgenes adyacentes (no hay contenido no vacío, relleno o áreas de borde, o espacio separado para separarlos) de dos o más recuadros (que pueden estar uno junto al otro o anidados) se combinan para formar un solo margen ".
http://www.w3.org/TR/CSS21/box.html#collapsing-margins
La mejor forma de lidiar con los márgenes colapsables es simplemente agregar un píxel al margen superior o inferior del elemento que tiene el margen contraído.
si el margen se derrumbaba en la parte superior ... entonces:
#element-with-collapsed-margin {
padding-top:1px;
}
o border-top arreglaría esto también
#element-with-collapsed-margin {
border-top:1px solid transparent;
}
si su margen inferior está contraído, debería agregar relleno al fondo: 1px; o borde superior: 1px sólido transparente;
básicamente, cualquier borde o relleno en la parte superior o inferior impedirá que los márgenes colapsen cuando los tenga uno encima del otro o incluso cuando tenga elementos anidados dentro de otro que tengan un colapso de margen
buena referencia:
http://reference.sitepoint.com/css/collapsingmargins
..
Otro truco que puedes usar cuando overflow:hidden
no es adecuado:
.clr:before, .clr:after {
display: table;
content: " ";
clear: both;
font-size: 0;
}
Este fragmento tiene el efecto secundario de contener todas las carrozas también.
Puede ser extraño, pero en las versiones nuevas de Chrome y Mozilla puede lograr el comportamiento deseado (el primer div se encuentra en la parte superior derecha) agregando wrapper div con borde
<html>
<body style="padding: 0; margin: 0;">
<div style="border: 1px solid black">
<div style="float: right;">first</div>
<div style="margin-top: 2em;">second</div>
</div>
</body>
</html>