Los tres bugs clásicos y su única causa
El float que se sale del padre, el margen que se escapa por arriba y el fondo que no cubre el contenido: tres síntomas famosos que son el mismo problema visto desde tres ángulos.
Hay tres bugs de layout que todo el mundo ha sufrido y que la mayoría resuelve por superstición: se prueban cosas hasta que una funciona. Los tres tienen exactamente la misma causa —una caja que no abrió un contexto de formato propio— y por tanto la misma solución. Verlos juntos, con el mismo diagnóstico y el mismo arreglo, es lo que convierte el conocimiento del nivel anterior en algo operativo.
- Reproducir los tres bugs desde cero y explicar el mecanismo de cada uno.
- Aplicar el diagnóstico común: preguntar quién abrió el contexto.
- Distinguir cuándo el arreglo correcto es aislar y cuándo es no usar flotantes.
- Reconocer los tres síntomas en código ajeno sin ejecutarlo.
El float que se sale del padre
El caso original, el que dio nombre al clearfix. Un contenedor con un único hijo flotado tiene altura cero.
<div class="tarjeta">
<img class="avatar" src="/foto.jpg" alt="">
</div>
.tarjeta { border: 2px solid crimson; }
.avatar { float: left; inline-size: 80px; }
El borde rojo se dibuja como una línea de cuatro píxeles de alto, con la imagen colgando por debajo. No es un error de renderizado: es exactamente lo que dice CSS 2.1. La altura de una caja de bloque en flujo normal se calcula a partir de sus hijos en flujo, y un flotante está fuera del flujo. El contenedor no lo cuenta porque no lo ve.
Esto no era una chapuza de la especificación, era el objetivo. float se inventó para reproducir la maquetación de una revista: una imagen a la izquierda con el texto de los párrafos siguientes rodeándola. Para que el texto de los hermanos posteriores pueda rodear la imagen, la imagen tiene que sobresalir del párrafo que la contiene. El comportamiento que hoy llamamos bug era la funcionalidad.
El arreglo es abrir un contexto independiente en el padre, porque un contexto independiente sí se dimensiona alrededor de sus flotantes:
.tarjeta { display: flow-root; border: 2px solid crimson; }
En 2026, un avatar a la izquierda y texto a la derecha no se hace con float, se hace con flex o grid. float solo tiene un uso vivo hoy: envolver texto alrededor de una forma, normalmente junto a shape-outside. Si tu flotante no lo usa nadie para rodearlo, no es un flotante, es un elemento mal colocado.
El margen que se escapa por arriba
Segundo síntoma, y el que más tiempo hace perder porque el efecto aparece lejos de la causa. Tienes una cabecera con fondo de color y un título dentro. Le pones margen superior al título y lo que se mueve es la cabecera entera.
<header class="cabecera">
<h1>Título</h1>
</header>
.cabecera { background: #cba6f7; }
h1 { margin-block-start: 2rem; }
El resultado: la cabecera se despega 2rem del borde superior, y el título queda pegado al techo de su fondo. El margen del hijo ha salido del padre.
Esto es colapso de márgenes entre padre y primer hijo. Ocurre porque ambos participan en el mismo BFC: no hay nada entre el borde superior del padre y el borde superior del hijo —ni borde, ni relleno, ni contenido en línea, ni un contexto de formato nuevo— así que los dos márgenes se funden en uno solo que se aplica por fuera del padre.
Hay cuatro formas de cortarlo, y solo una es limpia:
/* 1. Un borde transparente: funciona, pero suma un pixel al layout */
.cabecera { border-block-start: 1px solid transparent; }
/* 2. Un relleno: funciona, pero cambia el espaciado interior */
.cabecera { padding-block-start: 0.05px; }
/* 3. overflow: hidden: funciona, pero recorta */
.cabecera { overflow: hidden; }
/* 4. Un contexto independiente: funciona y no cambia nada más */
.cabecera { display: flow-root; }
Y una quinta forma, la que usarás de verdad: si la cabecera ya es flex o grid, el problema no existe, porque los márgenes de los elementos flex y grid nunca colapsan. Ese es el motivo real de que la generación de layouts posterior a 2017 apenas se tropiece con este bug.
El fondo que no cubre
Tercer síntoma, y realmente es el primero visto por su consecuencia visual. Un contenedor con fondo o con un borde de color no cubre a sus hijos flotados, porque su altura calculada los ignora. El fondo se pinta sobre el área del padre, y el área del padre acaba donde acaba su contenido en flujo.
<section class="destacado">
<aside class="nota">Nota lateral</aside>
<p>Este párrafo sí cuenta para la altura.</p>
</section>
.destacado { background: #94e2d5; color: #11111b; }
.nota { float: right; inline-size: 12rem; block-size: 20rem; }
Si la nota es más alta que el párrafo, el fondo turquesa acaba a la altura del párrafo y la nota sobresale sobre el fondo de la página. Mismo mecanismo, mismo arreglo:
.destacado { display: flow-root; background: #94e2d5; color: #11111b; }
La ventaja de reconocer los tres como uno solo es que dejas de necesitar tres recetas. El diagnóstico es siempre el mismo: hay una caja que participa en un contexto que no es el que tú creías.
El método de tres preguntas
Cuando un layout hace algo que no esperas, contesta en este orden:
Primero, ¿qué caja se está comportando raro, el contenedor o el contenido? Casi siempre culpas al contenido y la causa está en el contenedor.
Segundo, ¿quién abrió el contexto de formato en el que está esa caja? Sube por el árbol hasta encontrar el primer ancestro que aparezca en el catálogo del nivel anterior. Si llegas hasta html, tu caja está en el BFC inicial y comparte contexto con media página.
Tercero, ¿el comportamiento tiene sentido dentro de ese contexto? Si la respuesta es sí, no es un bug: es que el aislamiento que dabas por hecho no existe.
En las DevTools, el atajo práctico es mirar la altura calculada del contenedor. Si es menor que la de su contenido visible, tienes flotantes fuera del flujo. Si el margen que aplicaste a un hijo aparece en el panel de caja del padre, tienes colapso.
Los tres bugs de esta lección comparten algo más profundo que su causa técnica: comparten una decisión de diseño de 1996. CSS eligió que el contenedor de bloque corriente no aislara nada. No fue un descuido. En un lenguaje pensado para documentos de texto, el aislamiento por defecto habría sido un desastre: querías que el margen de un h2 y el del párrafo anterior se fundieran en uno, porque de lo contrario cada encabezado acumularía el espacio de los dos y el ritmo tipográfico se rompería. El colapso de márgenes es una función tipográfica, no un accidente, y funciona magníficamente para un artículo. El problema llegó cuando empezamos a usar el mismo mecanismo para construir interfaces, donde cada componente quiere ser una unidad sellada y el sangrado entre componentes es exactamente lo que no quieres. La respuesta de la plataforma no fue arreglar el flujo de bloque —habría roto la web entera— sino ofrecer modelos de layout alternativos que aíslan por defecto: flex, grid, flow-root. La conclusión operativa es incómoda pero clara: el flujo de bloque es un modelo de documento, no un modelo de interfaz. Si estás construyendo componentes, deberías estar en un contexto independiente casi siempre, y la pregunta interesante deja de ser cómo aislar y pasa a ser por qué no lo has hecho ya.
- Escribe un HTML con los tres bugs a la vez y confirma cada síntoma en el navegador.
- Arregla el primero con
flow-rooty comprueba en DevTools que la altura calculada del padre cambia. - Arregla el segundo de las cuatro formas y compara los tamaños calculados de cada una.
- Convierte el tercer contenedor en
display: flexsin tocar nada más y explica por qué también funciona. - Añade a la tarjeta arreglada un hijo con
position: absoluteque sobresalga y verifica que conoverflow: hiddense recorta y conflow-rootno.