¿Por qué este estilo CSS de margen superior no funciona?
Intenté agregar margin
valores dentro div
de otro div
. Todo funciona bien excepto el valor superior, que parece ignorarse. ¿Pero por qué?
Lo que esperaba:
Lo que consigo:
Código:
#outer {
width: 500px;
height: 200px;
background: #FFCCCC;
margin: 50px auto 0 auto;
display: block;
}
#inner {
background: #FFCC33;
margin: 50px 50px 50px 50px;
padding: 10px;
display: block;
}
<div id="outer">
<div id="inner">
Hello world!
</div>
</div>
W3Escuelas no tiene explicación de por qué margin
se comporta de esta manera.
En realidad, estás viendo que el margen superior del #inner
elemento colapsa en el borde superior del #outer
elemento, dejando solo el #outer
margen intacto (aunque no se muestra en tus imágenes). Los bordes superiores de ambas cajas están alineados entre sí porque sus márgenes son iguales.
Aquí están los puntos relevantes de la especificación W3C:
8.3.1 Márgenes colapsados
En CSS, los márgenes contiguos de dos o más cuadros (que pueden ser hermanos o no) se pueden combinar para formar un único margen. Se dice que los márgenes que se combinan de esta manera colapsan y el margen combinado resultante se denomina margen colapsado .
Los márgenes verticales contiguos colapsan [...]
Dos márgenes son contiguos si y sólo si:
- ambos pertenecen a cuadros de nivel de bloque de flujo entrante que participan en el mismo contexto de formato de bloque
- sin cuadros de línea, sin espacio libre, sin relleno y sin borde que los separe
- ambos pertenecen a bordes de caja verticalmente adyacentes, es decir, forman uno de los siguientes pares:
- margen superior de una caja y margen superior de su primer hijo entrante
Puede realizar cualquiera de las siguientes acciones para evitar que el margen colapse:
- Flota cualquiera de tus
div
elementos- Haga cualquiera de sus
div
elementos en bloques en línea- Conjunto
overflow
de#outer
aauto
(o cualquier valor distinto devisible
)
La razón por la que las opciones anteriores evitan que el margen colapse es porque:
- Los márgenes entre un cuadro flotante y cualquier otro cuadro no colapsan (ni siquiera entre un cuadro flotante y sus hijos de flujo entrante).
- Los márgenes de los elementos que establecen nuevos contextos de formato de bloque (como flotantes y elementos con un "desbordamiento" distinto de "visible") no colapsan con sus hijos entrantes.
- Los márgenes de las cajas de bloques en línea no colapsan (ni siquiera con sus hijos de flujo entrante).
Los márgenes izquierdo y derecho se comportan como se espera porque:
Los márgenes horizontales nunca colapsan.
Intente usarlo display: inline-block;
en el interior div
. Al igual que:
#outer {
width:500px;
height:200px;
background:#FFCCCC;
margin:50px auto 0 auto;
display:block;
}
#inner {
background:#FFCC33;
margin:50px 50px 50px 50px;
padding:10px;
display:inline-block;
}
La respuesta de BoltClock es bastante sólida. Aquí solo quiero agregar varias soluciones más para este problema. marque este margen w3c_collapsing . Las partes verdes son la idea potencial de cómo se puede resolver este problema.
Solución 1
Los márgenes entre un cuadro flotante y cualquier otro cuadro no colapsan (ni siquiera entre un cuadro flotante y sus hijos de flujo entrante).
eso significa que puedo agregar float:left
a cualquiera de los dos #outer
o #inner
demo1 .
También tenga en cuenta que eso float
invalidaría el auto
margen interior.
Solución 2
Los márgenes de los elementos que establecen nuevos contextos de formato de bloque (como flotantes y elementos con un "desbordamiento" distinto de "visible") no colapsan con sus hijos entrantes.
aparte de visible
, pongámoslo overflow: hidden
en #outer
. Y de esta manera parece bastante simple y decente. Me gusta.
#outer{
width: 500px;
height: 200px;
background: #FFCCCC;
margin: 50px auto;
overflow: hidden;
}
#inner {
background: #FFCC33;
height: 50px;
margin: 50px;
}
Solución 3
Los márgenes de las cajas absolutamente posicionadas no colapsan (ni siquiera con sus hijos entrantes).
#outer{
width: 500px;
height: 200px;
background: #FFCCCC;
margin: 50px auto;
position: absolute;
}
#inner{
background: #FFCC33;
height: 50px;
margin: 50px;
}
o
#outer{
width: 500px;
height: 200px;
background: #FFCCCC;
margin: 50px auto;
position: relative;
}
#inner {
background: #FFCC33;
height: 50px;
margin: 50px;
position: absolute;
}
Estos dos métodos romperán el flujo normal dediv
Solución 4
Los márgenes de las cajas de bloques en línea no colapsan (ni siquiera con sus hijos de flujo entrante).
es lo mismo que enderskill
Solución 5
El margen inferior de un elemento a nivel de bloque de flujo entrante siempre colapsa con el margen superior de su siguiente elemento hermano a nivel de bloque de flujo entrante, a menos que ese hermano tenga autorización.
Esto no tiene mucho que ver con la pregunta, ya que se trata del margen de colapso entre hermanos. generalmente significa si un top-box tiene margin-bottom: 30px
y un hermano-box tiene margin-top: 10px
. El margen total entre ellos es 30px
en lugar de 40px
.
Solución 6
El margen superior de un elemento de bloque de flujo entrante se colapsa con el margen superior de su primer elemento secundario a nivel de bloque de flujo entrante si el elemento no tiene borde superior ni relleno superior y el elemento secundario no tiene espacio libre.
Esto es muy interesante y solo puedo agregar una línea de borde superior.
#outer{
width: 500px;
height: 200px;
background: #FFCCCC;
margin: 50px auto;
border-top: 1px solid red;
}
#inner {
background: #FFCC33;
height: 50px;
margin: 50px;
}
Además, <div>
está a nivel de bloque de forma predeterminada, por lo que no es necesario declararlo a propósito. Perdón por no poder publicar más de 2 enlaces e imágenes debido a mi reputación de novato. Al menos sabrás de dónde viene el problema la próxima vez que veas algo similar.
No estoy seguro de por qué lo que tienes no funciona, pero puedes agregarlo overflow: auto;
al exterior div
.