css - que - margen superior no funciona con claro: ambos
que es margin y padding en css (8)
<div style="float: left;">Left</div>
<div style="float: right;">Right</div>
<div style="clear: both; margin-top: 200px;">Main Data</div>
¿Por qué el margin:top
para ''Datos principales'' no funciona en el código anterior?
A veces, una combinación de posición relativa y margen puede resolver este tipo de problemas.
Utilizo esta técnica para mis clases alignright y alignleft en WordPress.
Por ejemplo, si quiero un "margen inferior" que se respeta al borrar los elementos que puede utilizar.
.alignright{
float: right;
margin-left: 20px;
margin-top: 20px;
position: relative;
top: -20px;
}
Para tu ejemplo podrías hacer algo como
<div style="float: left;">Left</div>
<div style="float: right;">Right</div>
<div style="clear: both; margin-bottom: 200px; position: relative; top: 200px;">Main Data</div>
Intente establecer un margen inferior en uno de los elementos flotados. Alternativamente, puede envolver los flotantes en un elemento padre y usar un hack css para borrarlo sin marcas adicionales .
La lógica detrás de esto en la especificación es alucinante, e implica una interacción complicada de las reglas para la clearance y el colapso de los márgenes .
Probablemente esté familiarizado con el modelo de cuadro CSS convencional, en el que el cuadro de contenido está contenido dentro de un cuadro de relleno contenido dentro de un cuadro de borde dentro de un cuadro de margen :
Para los elementos con clearance configuración clearance en algo diferente a none
, se puede introducir un componente adicional a este modelo: espacio libre .
Valores distintos de ''ninguno'' introducen potencialmente la autorización . La separación inhibe el colapso del margen y actúa como un espaciado sobre el margen superior de un elemento.
En otras palabras, el modelo de caja en esos casos realmente se parece más a esto:
Pero, ¿cuándo se introduce la autorización y qué tamaño debe tener? Comencemos con la primera de esas preguntas. La especificación says :
El cálculo de la separación de un elemento en el que se establece ''borrar'' se realiza determinando primero la posición hipotética del borde superior del borde del elemento. Esta posición es donde habría estado el borde del borde superior real si la propiedad ''clara'' del elemento hubiera sido ''ninguna''.
Si esta posición hipotética del borde superior del elemento no supera los puntos flotantes relevantes, se introduce el espacio libre y los márgenes se colapsan según las reglas de 8.3.1.
Apliquemos esta lógica al código del interrogador de preguntas. Recuerde, estamos tratando de explicar la posición del tercer div en el código siguiente (fondos agregados para ayudar en la visualización):
<div style="float: left; background: red;">Left</div>
<div style="float: right; background: green;">Right</div>
<div style="clear: both; margin-top: 200px; background: blue;">Main Data</div>
Imaginemos, como nos lo pide la especificación, que clear
está establecido en none
en el tercer div, en lugar de both
. Entonces, ¿cómo se vería el fragmento de arriba?
<div style="float: left; background: red;">Left</div>
<div style="float: right; background: green;">Right</div>
<div style="clear: none; margin-top: 200px; background: blue;">Main Data</div>
Aquí, el tercer div está superponiendo los dos divs flotados. Pero espera; ¿por qué esto es tan? Claro, es permisible que los elementos flotantes se superpongan a los de nivel de bloque (según la especificación de Flotadores , "Dado que un flotador no está en el flujo, las cajas de bloque no posicionadas creadas antes y después del flujo flotan verticalmente como si el flotador no existiera . " ), pero nuestro tercer div tiene un montón de margin-top
en él, y viene después de los dos divs flotantes; ¿No deberían los dos divs flotantes aparecer en la parte superior del cuerpo, y el tercer div aparecer 200px abajo, muy por debajo de ellos?
La razón por la que esto no ocurre es que el margen del tercer div se colapsa en el margen del padre de los divs (en este caso, el cuerpo, pero el mismo comportamiento ocurre si envuelve los tres divs en un div padre). La especificación de márgenes de colapso (citada a continuación con varios detalles irrelevantes omitidos) nos dice que:
Los márgenes verticales adyacentes colapsan ...
Dos márgenes son contiguos si y solo si:
- ambos pertenecen a cuadros de nivel de bloque en flujo que participan en el mismo contexto de formato de bloque
- Sin cajas de línea, sin espacio libre, sin relleno y sin bordes separarlos ...
- ambos pertenecen a bordes de caja adyacentes verticalmente, es decir, forman uno de los siguientes pares:
- margen superior de una caja y margen superior de su primer elemento secundario en flujo
- ...
El tercer div en nuestro ejemplo ciertamente no es el primer hijo del cuerpo, pero es su primer hijo en flujo . Tenga en cuenta que, según https://www.w3.org/TR/CSS22/visuren.html#positioning-scheme :
Un elemento se llama fuera de flujo si está flotante, en posición absoluta o es el elemento raíz. Un elemento se llama in-flow si no está fuera de flujo.
Dado que la primera y la segunda div en nuestro ejemplo son flotantes, solo la tercera div está en flujo. Por lo tanto, su margen superior colinda con el margen superior de su padre y los márgenes se colapsan, empujando hacia abajo todo el cuerpo, incluidos los dos elementos flotantes. Así, el tercer div se superpone a sus hermanos a pesar de tener un gran margin-top
. En consecuencia, en este caso hipotético, donde el clear
del tercer elemento se establece en none
, satisfacemos la condición de que:
El borde superior del elemento no está más allá de los flotadores relevantes.
Así:
se introduce el espacio libre y los márgenes se colapsan según las reglas en 8.3.1
¿Cuánta liquidación? La especificación le da a los navegadores dos opciones, con un par de notas aclaratorias:
Entonces la cantidad de espacio libre se establece en el mayor de:
- La cantidad necesaria para colocar el borde del borde del bloque incluso con el borde exterior inferior del flotador más bajo que se va a eliminar.
- La cantidad necesaria para colocar el borde superior del bloque en su posición hipotética.
Alternativamente, el espacio libre se establece exactamente en la cantidad necesaria para colocar el borde del borde del bloque, incluso con el borde exterior inferior del flotador más bajo que se debe limpiar.
Nota: Se permite que ambos comportamientos estén pendientes de la evaluación de su compatibilidad con el contenido web existente. Una futura especificación de CSS requerirá una u otra.
Nota: El espacio libre puede ser negativo o cero.
Antes de que podamos comenzar a aplicar estas reglas, inmediatamente nos encontramos con una complicación. ¿Recuerda ese margen de colapso que tuvimos que tener en cuenta en el caso hipotético donde estaba clear
none
? Bueno, no existe en este caso no hipotético en el que calculamos la autorización de uso, porque la existencia de la autorización lo inhibe. Recuerde las reglas de margen de colapso de 8.3.1 , citadas anteriormente, dicte que los márgenes solo se adjuntan si:
- Sin cajas de línea, sin espacio libre , sin relleno y sin bordes separarlos
(énfasis añadido). Como tal, el margen superior del tercer div y el margen superior de su padre ya no están contiguos. Podemos simular este escenario de autorización previa en nuestro fragmento de ejemplo manteniendo clear: none
pero agregando padding-top: 1px
al cuerpo, que también desactiva el colapso del margen, según la regla citada anteriormente.
body {
padding-top: 1px;
}
<div style="float: left; background: red;">Left</div>
<div style="float: right; background: green;">Right</div>
<div style="clear: none; margin-top: 200px; background: blue;">Main Data</div>
Ahora, a diferencia de cuando los márgenes se colapsaron, nuestro tercer div se encuentra cómodamente por debajo de sus dos hermanos flotantes. Pero ya hemos decidido, sobre la base de un escenario hipotético en el que los márgenes colapsaron, que se debe agregar la autorización; todo lo que queda es elegir la cantidad de espacio libre, con el fin de:
coloque el borde del borde del bloque incluso con el borde exterior inferior del flotador más bajo que se va a despejar
Y, por lo tanto, no tenemos más remedio que aplicar un espacio negativo al tercer div, para arrastrar el borde superior del borde hacia arriba hasta que toque el borde exterior inferior (también conocido como borde del margen ) de los elementos flotantes que se encuentran sobre él. Como tal, si los elementos flotados tienen 10px de altura cada uno y la tercera división tiene 200px de margen superior, se aplicará -190px de espacio libre. Eso, por fin, nos lleva al resultado final visto por el que pregunta:
<div style="float: left; background: red;">Left</div>
<div style="float: right; background: green;">Right</div>
<div style="clear: both; margin-top: 200px; background: blue;">Main Data</div>
(Tenga en cuenta que si inspecciona el tercer div en el fragmento de código anterior utilizando las herramientas de desarrollo de su navegador, aún podrá ver los 200px del margen superior sobre el div, superando por encima el resto del contenido; toda la caja de margen ha sido arrastrada hacia arriba por la gran distancia negativa.)
¡Sencillo!
Mientras Pointy muestra cómo puede envolver los flotadores en un div, alternativamente puede insertar un div vacío entre los flotadores y la sección de datos principal. Por ejemplo:
<div style="float: left;">Left</div>
<div style="float: right;">Right</div>
<div style="clear: both;"></div>
<div style="margin-top: 200px;">Main Data</div>
Esto podría resultar útil en los casos en los que no es conveniente agregar un envoltorio div alrededor de algún HTML.
Podría colocar los dos divs flotantes en otro que tenga el conjunto "overflow: hidden":
<div style=''overflow:hidden''>
<div style="float: left;">Left</div>
<div style="float: right;">Right</div>
</div>
<div style="clear: both; margin-top: 200px;">Main Data</div>
Editar - Para agregar un poco a esta respuesta de 5 años: creo que la causa de este comportamiento confuso es el proceso un tanto complicado del colapso del margen . Un buen truco con el HTML original del OP es agregar una regla CSS como esta:
div { border: 1px solid transparent; }
¡Maricón! Ahora (sin mi <div>
adicional) funciona bien! Bueno, a excepción de ese píxel extra de las fronteras. En particular, creo que es una combinación de la forma más clear: both
obras como las reglas de colapso del margen que resultan en un diseño inesperado del código en el OP.
Edite de nuevo : para la historia completa (y, creo, completamente precisa), vea la excelente respuesta de Mark Amery . Los detalles tienen cierta complejidad que esta respuesta pasa por alto.
Pointy y Randall Cook tienen excelentes respuestas. Pensé en mostrar una solución más.
<div style="float: left;">Left</div>
<div style="float: right;">Right</div>
<div style="float: left; clear: both; margin-top: 200px;">Main Data</div>
Si haces el tercer elemento "float: left;" Y "claro: ambos;", debe tener el efecto deseado de darle al tercer elemento un margen de 200 píxeles. Aquí hay un link a un ejemplo.
Esto también podría afectar a otros elementos de seguimiento en cuanto a si deben ser flotantes o no. Sin embargo, también podría tener el efecto deseado.
Solución alternativa:
En realidad, puede colocar un
margin-bottom
en los elementos flotantes para empujar hacia ABAJO el elemento que está debajoclear: both
.
Nota: Habiendo hecho esta sugerencia, tengo que retractarla de inmediato, ya que generalmente no es una buena idea, pero en algunas situaciones limitadas puede ser apropiado;
<div class=''order''>
<div class=''address''>
<strong>Your order will be shipped to:</strong><br>
Simon</br>
123 Main St<br>
Anytown, CA, US
</div>
<div class=''order-details''>
Item 1<br>
Item 2<br>
Item 3<br>
Item 4<br>
Item 5<br>
Item 6<br>
Item 7<br>
Item 8<br>
Item 9<br>
Item 10<br>
</div>
<div class=''options''>
<button>Edit</button>
<button>Save</button>
</div>
</div>
El panel con elementos se llama order-details
con este css
.order-details
{
padding: .5em;
background: lightsteelblue;
float: left;
margin-left: 1em;
/* this margin does take effect */
margin-bottom: 1em;
}
En el violín anterior, el panel amarillo tiene un margin-top
, pero a menos que sea mayor que el elemento flotado más alto, entonces no hará nada (por supuesto, ese es el punto principal de esta pregunta).
Si establece el margin-top
del panel amarillo en 20em, será visible porque el margen se calcula desde la parte superior del cuadro azul exterior.
Utilice ''padding-top'' en su div principal de datos en su lugar. O, como alternativa, envuelva el div principal de datos en uno con ''padding-top''.