Margen en el elemento hijo mueve el elemento padre


Tengo un div (padre) que contiene otro div (niño). Padre es el primer elemento en body sin un estilo CSS particular. Cuando establezco

.child
{
    margin-top: 10px;
}

El resultado final es que top of my child sigue alineado con parent. En lugar de desplazar al niño por 10px hacia abajo, mi padre mueve 10px hacia abajo.

Mi DOCTYPE se establece en XHTML Transitional.

¿Qué me estoy perdiendo aquí?

editar 1
Mi padre necesita haber definido estrictamente dimensiones porque tiene un fondo que tiene que mostrarse debajo de él de arriba a abajo (pixel perfecto). Así que establecer márgenes verticales en él es un no go.

editar 2
Este comportamiento es el mismo en FF, IE y CR.

Author: Robert Koritnik, 2009-11-19

14 answers

Encontró una alternativa en Elementos secundarios con márgenes dentro de DIVs También puede agregar:

.parent { overflow: auto; }

O:

.parent { overflow: hidden; }

Esto evita que los márgenes se contraigan . El borde y el relleno hacen lo mismo. Por lo tanto, también puede usar lo siguiente para evitar un colapso del margen superior:

.parent {
    padding-top: 1px;
    margin-top: -1px;
}

Actualización por petición popular: El objetivo de colapsar los márgenes es manejar el contenido textual. Por ejemplo:

<style type="text/css">
    h1, h2, p, ul {
        margin-top: 1em;
        margin-bottom: 1em;
    }
</style>

<h1>Title!</h1>
<div class="text">
    <h2>Title!</h2>
    <p>Paragraph</p>
</div>
<div class="text">
    <h2>Title!</h2>
    <p>Paragraph</p>
    <ul>
        <li>list item</li>
    </ul>
</div>

Porque el navegador colapsa márgenes, el texto aparecerá como es de esperar, y las etiquetas <div> wrapper no influyen en los márgenes. Cada elemento se asegura de que tenga espacio a su alrededor, pero el espacio no se duplicará. Los márgenes de <h2> y <p> no se suman, sino que se deslizan entre sí (se colapsan). Lo mismo sucede con los elementos <p> y <ul>.

Tristemente, con diseños modernos esta idea puede morderte cuando quieres explícitamente un contenedor. Esto se llama un nuevo contexto de formato de bloque en lenguaje CSS. El overflow o truco de margen te dará eso.

 394
Author: vdboor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:43

Este es un comportamiento normal (al menos entre las implementaciones del navegador). El margen no afecta la posición del hijo en relación con su padre, a menos que el padre tenga relleno, en cuyo caso la mayoría de los navegadores agregarán el margen del hijo al relleno del padre.

Para obtener el comportamiento que desea, necesita:

.child {
    margin-top: 0;
}

.parent {
    padding-top: 10px;
}
 44
Author: Ben James,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-19 11:10:31

Aunque todas las respuestas solucionan el problema, pero vienen con compensaciones / ajustes / compromisos como

  • floats, Usted tiene para flotar elementos
  • border-top, Esto empuja al padre al menos 1px hacia abajo, que luego debe ajustarse introduciendo -1px margen al propio elemento padre. Esto puede crear problemas cuando el padre ya tiene margin-top en unidades relativas.
  • padding-top, el mismo efecto que usar border-top
  • overflow: hidden, No se puede usar cuando el padre debe mostrar contenido desbordante, como un menú desplegable
  • overflow: auto, Introduce barras de desplazamiento para el elemento padre que tiene (intencionalmente) contenido desbordante (como sombras o triángulo de punta de herramienta)

El problema se puede resolver usando pseudo elementos CSS3 de la siguiente manera

.parent::before {
  clear: both;
  content: "";
  display: table;
  margin-top: -1px;
  height: 0;
}

Https://jsfiddle.net/hLgbyax5/1 /

 14
Author: Ejaz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-15 14:22:06

Añadir estilo display:inline-block al elemento secundario

 11
Author: Атанас Димитров,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-08 11:09:47

El elemento padre no tiene que estar vacío al menos pon &nbsp; antes del elemento hijo.

 6
Author: George SEDRA,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-23 09:00:13

Esto es lo que funcionó para mí

.parent {
padding-top: 1px;
margin-top: -1px;
}

.child {
margin-top:260px;
}

Http://jsfiddle.net/97fzwuxh/

 6
Author: erdomester,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-26 18:34:32

Me entero de que, dentro de tu .css > si establece la propiedad display de un elemento div en inline-block soluciona el problema. y el margen funcionará como se espera.

 2
Author: vincent thorpe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-13 22:29:47

El margin de los elementos contenidos dentro de .child se están colapsando.

<html>
<style type="text/css" media="screen">
    #parent {background:#dadada;}
    #child {background:red; margin-top:17px;}
</style>
<body>
<div id="parent">

    <p>&amp;</p>

    <div id="child">
        <p>&amp;</p>    
    </div>

</div>
</body>
</html>

En este ejemplo, p está recibiendo un margin de los estilos predeterminados del navegador. El valor predeterminado del navegador font-size es típicamente 16px. Al tener un margin-top de más de 16px en #child comienzas a notar su movimiento de posición.

 1
Author: 25thhour,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-19 11:45:40

También tuve este problema, pero preferí evitar hacks de márgenes negativos, así que puse un

<div class="supercontainer"></div>

Alrededor de todo lo que tiene rellenos en lugar de márgenes. Por supuesto, esto significa más divitis, pero es probablemente la forma más limpia de hacerlo correctamente.

 1
Author: Zyl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-07 15:03:51

Curiosamente, mi solución favorita para este problema aún no se menciona aquí: el uso de flotadores.

Html:

<div class="parent">
    <div class="child"></div>
</div>

Css:

.parent{width:100px; height:100px;}
.child{float:left; margin-top:20px; width:50px; height:50px;}

Véalo aquí: http://codepen.io/anon/pen/Iphol

Tenga en cuenta que en caso de que necesite altura dinámica en el padre, también tiene que flotar, así que simplemente reemplace height:100px; por float:left;

 1
Author: schellmax,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-14 20:13:54

Una solución alternativa que encontré antes de saber la respuesta correcta fue agregar un borde transparente al elemento padre.

Sin embargo, su caja usará píxeles adicionales...

.parent {
    border:1px solid transparent;
}
 1
Author: SandRock,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-08 09:09:07

Solución solo CSS ordenada

Use el siguiente código para anteponer un primer hijo sin contenido al div que se mueve involuntariamente:

.parent:before
{content: '';position: relative;height: 0px;width: 0px;overflow: hidden;white-space: pre;}

La ventaja de este método es que no necesita cambiar el CSS de ningún elemento existente, y por lo tanto tiene un impacto mínimo en el diseño. Junto a esto, el elemento que se agrega es un pseudo-elemento, que es no en el árbol DOM.

El soporte para pseudo-elementos está muy extendido: Firefox 3+, Safari 3+, Chrome 3+, Opera 10+, e IE 8+. Esto funcionará en cualquier navegador moderno (tenga cuidado con el nuevo ::before, que no es compatible con IE8).

Contexto

Si el primer hijo de un elemento tiene un margin-top, el padre ajustará su posición como una forma de contraer márgenes redundantes. ¿Por qué? Es así de simple.

Dado el siguiente problema:

<style type="text/css">
div {position: relative;}
.parent {background-color: #ccc;}
.child {margin-top: 40px;}
</style>

<div class="parent"><!--This div moves 40px too-->
    <div class="child">Hello world!</div>
</div>

Puede arreglarlo agregando un hijo con contenido, como un espacio simple. Pero todos odiamos agregar espacios para lo que es un problema solo de diseño. Por lo tanto, utilice la propiedad white-space para falsificar contenido.

<style type="text/css">
div {position: relative;}
.parent {background-color: #ccc;}
.child {margin-top: 40px;}
.fix {position: relative;white-space: pre;height: 0px;width: 0px;overflow: hidden;}
</style>

<div class="parent"><!--This div won't move anymore-->
    <div class="fix"></div>
    <div class="child">Hello world!</div>
</div>

Donde position: relative; asegura el posicionamiento correcto de la solución. Y white-space: pre; hace que no tenga que agregar ningún contenido, como un espacio en blanco, a la solución. Y height: 0px;width: 0px;overflow: hidden; se asegura de que nunca verás la solución.

Es posible que deba agregar line-height: 0px; o max-height: 0px; para asegurarse de que la altura es realmente cero en los navegadores IE antiguos (no estoy seguro). Y opcionalmente se puede añadir <!--dummy--> en los navegadores IE antiguos, si no funciona.

En resumen, puedes hacer todo esto con solo CSS (que elimina la necesidad de agregar un hijo real al árbol DOM HTML):

<style type="text/css">
div {position: relative;}
.parent {background-color: #ccc;}
.child {margin-top: 40px;}

.parent:before {content: '';position: relative;height: 0px;width: 0px;overflow: hidden;white-space: pre;}
</style>

<div class="parent"><!--This div won't move anymore-->
    <div class="child">Hello world!</div>
</div>
 1
Author: Yeti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-13 09:39:00

Usar top en lugar de margin-top es otra solución posible, si es apropiado.

 0
Author: lamplightdev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-20 10:57:32

Para evitar que "Div parent" use el margen de " div child":
En el padre use estas css:

  • Float
  • Relleno
  • Frontera
  • Desbordamiento
 0
Author: bingo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-11 06:00:47