Cómo conseguir columnas de igual altura con CSS

Columnas de igual altura
Imagen de Christian Hoppe

En la maquetación con CSS siempre ha habido dos problemas principales. Uno de ellos es como no el centrado, una cuestión que a priori parece de lo más sencilla, puede volverse una pesadilla si no tenemos claro como funciona el modelo de caja con el que trabajamos. El otro es conseguir que varios elementos tengan la misma altura, siendo su contenido completamente desigual.

En esto post no voy a tratar todas las formas de conseguir tal efecto, ya que muchas de ellas a día de hoy no son nada recomendables. Por supuesto en su día fueron un gran paso para conseguir un buen layout, como por ejemplo el conocido método de Dan Cederholm Faux Columns, que consiste en usar un contenedor general, que contendrá a las columnas, con una imagen de fondo que se repite verticalmente y que simula las columnas que deseamos (hay una versión más moderna de Doug Neiner que usa gradientes en vez de una imagen de fondo), el problema es que Faux Columns está pensado para diseños rígidos y no para diseños fluidos.

Otro de los grandes métodos es el de Matthew James Taylor, que queda a medio camino entre las Faux Columns de Dan Cederholm y el método de Doug Neiner. Consiste en anidar tantos contenedores como columnas vayamos a usar, y la última de ellas contendrá las columnas. Cada contenedor tendrá un color de fondo, y los flotaremos y posicionaremos relativamente con la intención de moverlos para conseguir visualmente las columnas. También haremos lo propio con las columnas, que también las flotaremos y posicionaremos relativamente para posteriormente moverlas. El problema es que a mi gusto se usa demasiado marcado HTMl, un contenedor por cada columna.

A vueltas con las tablas

A día de hoy las cosas son un tanto diferentes, y no es necesario realizar un gran marcado HTML o usar imágenes de fondo para conseguir igualar la altura de las columnas. Hay que tener en cuenta que no siempre hemos necesitado de estos métodos, ya que cuando creábamos los layouts con tablas (cosa que nunca debe de hacerse) el propio comportamiento de la tabla nos daba la solución sin más. Claro que fijándonos en esta propiedad sólo debemos recurrir a cambiar nuestro modelo de caja por display:table para conseguir exactamente lo mismo.

Hay que tener en cuenta el problema que a día de hoy tiene Firefox con la imágenes responsive para la cuales usamos max-width, ya que dentro de un contenedor con display:table no funciona esta propiedad (da igual que la imagen sea hijo directo o no). Aunque para todo hay una solución, como la que di en el artículo pasado Imágenes en diseño responsive: El problema de max-width.


<div id="contenedor">
    <div id="columna1"></div>
    <div id="columna2"></div>
    <div id="columna3"></div>
</div>

#contenedor {
    display:table;
}

#columna1, #columna2, #columna3 {
    display:table-cell;
}

Jugando con los márgenes

Este método usa margin, padding y overflow para conseguir igualar las columnas en altura. El truco consiste en dar un padding inferior lo suficientemente grande a cada columna y luego corregirlo con un margin negativo inferior de igual valor. Para que todo se vea bien ocultaremos el sobrante mediante overflow en el contenedor padre.


<div id="contenedor">
    <div id="columna1"></div>
    <div id="columna2"></div>
    <div id="columna3"></div>
</div>

#contenedor {
    overflow: hidden;
}

#columna1, #columna2, #columna3 {
    padding-bottom: 9999px;
    margin-bottom: -9999px;
}

Las maravillas de flexbox

Flexbox o la caja flexible se ha vuelto la piedra angular de CSS3, más aún cuando es soportado por todos los navegadores en su última versión. Se puede hacer casi de todo y simplifica muchos casos en los que usábamos trucos y maquetaciones imposibles para conseguir, lo que a priori, CSS no nos ofrecía. Para el caso de igualar la altura de las columnas, también hay solución con flexbox.


<div id="contenedor">
    <div id="columna1"></div>
    <div id="columna2"></div>
    <div id="columna3"></div>
</div>

#contenedor {
   display: -webkit-flex;
   display: flex;
}

Sí, parece demasiado sencillo, y así es. Cuando definimos y contenedor con display:flex, todos sus hijos pasan a ser elementos flexibles y pueden beneficiarse del funcionamiento de la caja flexible. Por defecto en un contenedor definido con display:flex, la propiedad align-items toma el valor strech, lo hace que todos sus hijos tenga la misma altura, siempre que no modifiquemos el main-axis. Si te interesa saber como funciona esta "propiedad" más a fondo el artículo A Complete Guide to Flexbox de CSS-Tricks es la guía que necesitas.