JASoft.org

El blog de José Manuel Alarcón Aguín. Programación web y mucho más...

MENÚ - JASoft: JM Alarcón

HTML y CSS: El "extraño" comportamiento de las cajas anidadas

Un concepto que todo programador Web debe tener claro es el modo de visualización CSS de los elementos. Es indispensable ya que condiciona por completo el comportamiento de los elementos HTML dentro de una página.

Otro comportamiento que es importante tener claro es todo lo que se refiere con el derrumbamiento de márgenes verticales de los elementos. Éste hace que los márgenes verticales no se sumen, sino que se combinen, aunque no en todas las circunstancias.

Un caso "extraño" se da cuando tenemos en una página elementos anidados, es decir, cuando uno o varios elementos están contenidos dentro de otros.

Por ejemplo, consideremos esta página tan sencilla con dos elementos de tipo <div>, uno dentro de otro:

<div id="Uno">
    <div id="Dos">
        Lorem ipsum...
    </div>
</div>

Y les aplicamos los siguientes estilos:

html, body{
    width: 100%;
    height: 100%;
    margin:0px;
    padding:0px;
}

#Uno{
    background-color: aqua;
}

#Dos{
    background-color: blue;
    padding: 20px;
    margin: 30px;
    height: 200px;
    width: 200px;
}

Fíjate en que el div exterior ('Uno') no incluye ningún tipo de dimensión ni otras propiedades. Es un elemento de bloque (display:block) porque es su comportamiento por defecto, pero nada más.

Este fragmento tan sencillo se visualiza de la siguiente manera:

CSS-Anidados-01

Es decir, si nos fijamos, la caja exterior ocupa todo el ancho disponible en la página extendiéndose hacia la derecha, se respeta el margen horizontal de 30px de la caja interior (por eso está desplazada hacia dentro, a la derecha) pero aparentemente no se respeta el margen vertical que se ha indicado (también de 30px). Además la caja exterior no está pegada al borde superior de la página a pesar de tener un margen y un relleno de 0 (son sus valores por defecto).

Es decir, en este caso se dan dos comportamientos extraños, en apariencia independientes, que son los que he marcado en negrita en el párrafo anterior que vamos a analizar a continuación.

Funcionamiento de los márgenes en CSS

Como sabemos, los elementos de bloque (y estos lo son) respetan los márgenes entre elementos. En realidad se respetan los márgenes horizontales y, de los verticales, tan solo el mayor de ellos (no se suman).

Esto es algo que todo programador web debe saber y se conoce como el efecto de "derrumbe de márgenes" o incluso más comúnmente con el término en inglés "margin collapsing".

Esto quiere decir que en dos elementos de bloque que quedan uno encima del otro por algún motivo, si el que está arriba tiene por ejemplo un margen inferior de 10px y el que está debajo tiene un margen superior de 40px, el margen final que los separará no es la suma de ambos (50px), sino que es el mayor de los dos márgenes.

Veámoslo gráficamente mejor. Estos son dos divs "sueltos", es decir, considerados ellos solos en la página (no interaccionan, es solo para ver cómo son):

Cajas-Ejemplo-Base

Como vemos tienen un área para el contenido, y además el relleno (padding), un posible borde y un margen (las capturas son de la representación de la caja de un elemento en las herramientas del desarrollador de Chrome). La de arriba sería nuestra caja 'Uno' y la de abajo la caja 'Dos'.

Bien, si colocamos una caja encima de la otra con estos márgenes, de modo que sus lados inferior y superior se toquen, el efecto que conseguimos es este:

Colapso-Margenes-Adyacentes

Fíjate en cómo el margen que prevalece es el mayor, y no se suman, tal y como hemos explicado.

Es decir, el margen combinado se "derrumba" y se queda solamente con el mayor de ellos (no se suman).

Este es el comportamiento por defecto estándar.

Sin embargo si nos fijamos en el caso inicial de las dos cajas anidadas no ocurre esto y no hay separación entre los dos elementos, que quedan pegados uno dentro del otro, como se ve en la primera figura. ¿A qué es debido?

Cuando un elemento está dentro de otro, los lados que se tocan o se separan son los mismos. Es decir, en nuestro ejemplo inicial, la parte superior de la caja que está dentro toca a la parte superior de la caja "madre" que la contiene. En el caso más habitual de elementos adyacentes que acabamos de ver, es justo al revés: se toca el lado inferior con el superior.

Al estar tocándose los dos lados superiores de la caja, ambos márgenes de la caja están pegados también. O sea, igual que antes, pero se tocan desde dentro en lugar de desde fuera. Por lo tanto al igual que antes se produce un "colapso" y solo prevalece el mayor de ellos.

Pero... según eso, ambos elementos deberían estar separados por el mayor de los márgenes ¿no? y en este caso están pegados, es decir, que el margen es de 0, ¿no es así?

Pues no. Y la mejor forma de verlo es de nuevo gráficamente.

Pero antes de hacerlo es importante fijarse en una cuestión: si analizas el CSS del principio, la caja 'Uno' no tiene ni borde ni relleno (que por defecto son 0), por lo que su composición real es esta:

Caja-Uno-SinBordeNiPadding

Es decir, al no tener borde ni relleno está formada tan solo por el contenido y el margen.

Cuando le metemos dentro otro elemento de bloque, la caja 'Dos', el resultado que tenemos es el de la siguiente figura:

Colapso-Margenes-Anidados

Fíjate bien en qué elementos se están tocando: se tocan el margen vertical de la caja exterior con el margen vertical de la caja interior.

Como hemos visto, cuando dos márgenes verticales se tocan se produce un derrumbe de los mismos, siendo el margen resultante el mayor de ellos, pero no su suma. En este caso lo que ocurre es que el margen que prevale es el de la caja interior, de 40px, por lo que el resultado final es el que veíamos en la figura inicial, que tiene dos efectos:

  • Los lados superiores de las dos cajas se tocan.
  • La caja superior está separada del borde superior de la página.

Es decir: el margen resultante tiene efecto sobre la caja de fuera, no sobre la de dentro, y ambas cajas están pegadas entre sí.

Por eso en el ejemplo inicial que puse, la caja 'Uno' está separada de la parte superior de la página.

Este es un resultado muy poco intuitivo y difícil de ver a la primera, salvo que te lo enseñen gráficamente como acabo de hacer yo.

Pero es que todavía hay más...

¿Qué pasa si la caja "madre" que contiene a la otra tuviese un borde o un relleno cualquiera?

Pues que si volvemos a visualizar como quedarían las cajas, nos daremos cuenta de una cosa muy importante que cambia por completo el resultado: ahora los márgenes ya no se tocan. Y como no se tocan ya no existe la posibilidad de que se derrumben, respetándose sin problema. Vamos a verlo:

Colapso-Margenes-Anidados-Borde-Padding

Nota: he representado la caja interior cortada como si la caja exterior tuviese un overflow:hidden; tratando de simplificar la visualización. Pero es importante señalar que no es así. Si fuera de ese modo el comportamiento sería diferente, como veremos en breve. Ojo con esta licencia estética.

Como vemos, como la caja "Uno" tiene padding y borde (llegaría con uno de los dos) hace que los márgenes no se toquen entre sí, por lo que se respetan ambos.

Es decir, si queremos que los márgenes verticales se respeten solo tenemos que asegurarnos de que no se toquen.

Por eso, si en el ejemplo del principio le ponemos un simple padding:1px; a la caja 'Uno', de repente se comportará como esperábamos y se respetarán ambos márgenes, teniendo como resultado quel a caja estará pegada a la parte superior de la página (ya que tiene margen superior 0 por defecto):

CSS-Anidados-02

Llega con un cambio tan simple para modificar por completo todo el comportamiento visual de las dos cajas :-O

El efecto de la propiedad overflow: nuevo contexto de formato de bloque

Vale, una vez comprendido cómo se colapsan los márgenes, vamos a ver un efecto importante relacionado con todo esto, y que tampoco es nada intuitivo.

Dejemos el ejemplo como estaba al principio, es decir, la caja exterior sin padding de forma que quede todo como en la primera figura.

Ahora le aplicaremos a la caja exterior la propiedad overflow:hidden;. El resultado, sorprendentemente, vuelve a ser el mismo que cuando le poníamos un relleno o un borde: de repente ¡el contenedor está pegado arriba y el margen del hijo se conserva dentro del padre!

Lo único que ha cambiado es el overflow. Esto se debe a que cuando se utiliza un overflow distinto a "visible" (que es el valor que tiene por defecto) se crea un nuevo contexto de formato de bloque.

¿Y esto que es? Bueno, podemos ir al estándar, pero no se entiende casi nada. En la práctica lo que significa, entre otras cosas, es que los márgenes verticales no se colapsan, y por eso se da el mismo efecto que cuando le ponemos un borde o un relleno.

Cualquier valor de overflow distinto de "visible" consigue el mismo efecto, y es algo que puede traerte por la calle de la amargura si no lo tienes claro.

Este es solo un ejemplo de que el comportamiento de HTML y CSS puede llegar a ser bastante complejo. Mucho más de lo que parece, debido a todas las interacciones y posibilidades que existen. De hecho todavía hay más posibilidades de comportamiento de estas dos cajas anidadas, dependiendo de si están flotadas no, de su modo de visualización de su modo de posicionamiento...

Es muy importante comprender bien todos los mecanismos de funcionamiento internos que tiene HTML y CSS, y no "tocar de oído" como se hace casi siempre. Por eso, humildemente, te recomiendo mi curso de HTML5 y CSS3 en el que se explican con todo lujo de detalles (con teoría, vídeos prácticos y ejemplos) todos los entresijos de funcionamiento de HTML y CSS. Para que aprendas "de verdad" estas tecnologías. ¡Gracias!

José Manuel Alarcón José Manuel Alarcón
Fundador de campusMVP.es, el proyecto de referencia en formación on-line para programadores en lengua española. Autor de varios libros y cientos de artículos. Galardonado como MVP de Microsoft desde 2004. Gallego de Vigo, amante de la ciencia y la tecnología, la música y la lectura. Ayudando a la gente en Internet desde 1996.
Descarga GRATIS mi último libro (no técnico): "Tres Monos, Diez Minutos".
Banner

Comentarios (2) -

Jesus Estevez (jecaestevez)

Gracias por las expliaciones ,desde que deje el Xaml cada vez voy entiendo mejor css :-P
Genial como siempre!

Responder

by Jose M. Alarcon

Gracias :-)

Responder

Agregar comentario