Columnas «like a boss»
Tabla de contenidos
He visto que muchos diseñadores de skins que necesitan columnas abusan de métodos como los float o display: inline-block para obtener dicho resultado.
El uso de estas propiedades no es más que un «truco» para evitar tener que utilizar el elemento
Hasta este punto hemos pasado por dos métodos y los dos tenían sus desventajas. Si te has fijado, los anteriores métodos no eran más que pequeños trucos utilizados para obviar la carencia de un método nativo en CSS para hacer columnas. Seguramente incluso ya sabías la existencia de ambos métodos y cómo corregir dichos errores. Sin embargo, te traigo malas noticias. Has estado haciéndolo mal todo este tiempo.
<table>
para maquetar. Debemos recordar que en el pasado (¿en serio acabo de llamarle a los años 2000 «pasado»?) este elemento era utilizado de forma abusiva para constituir las estructuras de las páginas, llevando a los desarrolladores a problemas de semántica y mantenibilidad, entre otros.
Desafortunadamente mucha gente utiliza de forma incorrecta estas propiedades, por lo que dedicaré las siguientes líneas a explicar cómo se deben utilizar para obtener columnas como resultado.
La base
Antes de empezar con los distintos métodos para crear columnas voy a presentar la estructura HTML básica para poder hacerlas y con la que voy a trabajar en todos los ejemplos de esta guía:<div id="contenedor">
<div class="columna">Columna 1</div>
<div class="columna">Columna 2</div>
<div class="columna">Columna 2</div>
</div>
Para hacer las cosas más claras, he añadido a los elementos colores y unos pocos márgenes para poder diferenciarlos:
#contenedor {
width: 500px;
background-color: #4DC6BB;
}
#contenedor .columna {
background-color: #FAC44D;
margin: 20px;
padding: 20px;
}
El resultado de ese HTML y el CSS que le he añadido es el siguiente:
Float, el método malo
Cuando utilizamos la propiedadfloat
, tenemos que recordar que en realidad estamos utilizando una propiedad diseñada para trabajar con texto y elementos inline
, con bloques.
En efecto, el uso intencionado para esta propiedad era el de hacer «flotar» las imágenes sobre el texto para obtener un efecto como esos que hacíamos en el Word 2003, con las imágenes a la izquierda rodeada de texto.
Por eso lo llamé truco, porque en realidad estamos abusando de un comportamiento inintencionado, lejos del objetivo para el que se creó la propiedad.
Uno de los problemas de los floats
para hacer columnas es que, al estar flotando, no afecta al contenido de su padre y, por lo cual, no se tiene en cuenta la altura del elemento flotado para calcular la altura de su padre.
Vamos a ver esto mejor con un ejemplo. Pongamos ahora a los elementos que serán las columnas la propiedad y valor float: left
(para que floten con respecto a la izquierda, se podría utilizar perfectamente el valor right
):
#contenedor .columna {
float: left;
}
Como la altura de los hijos no está siendo tomada en cuenta para div#contenedor
, su altura interna es 0 (recordad que he colocado padding
, por eso su altura externa es mayor).
Mucha gente soluciona este problema añadiendo una altura definida al padre y, aunque ciertamente es una solución, no se adapta al contenido, por lo que no serviría en caso de que éste fuese dinámico.
En un principio se optaba por añadir un div
con clear: both
al final de todo de nuestros elementos flotados para restaurar el flujo. Recordemos que la propiedad clear
evita que elemento al que se aplica se coloque detrás del anterior elemento flotado, si cupiese. Por ejemplo:
<div id="contenedor">
<div class="columna">Columna 1</div>
<div class="columna">Columna 2</div>
<div class="columna">Columna 2</div>
<div style="clear: both"></div>
</div>
Sin embargo, esto volvía a traer un problema que se intentaba solucionar con los floats
: que el HTML sea sintáctico. Es decir, que todos los elementos existan porque tienen un significado para el contenido (y no para el diseño).
No se tardó en encontrar una solución con CSS3 y sus pseudoelementos:
#contenedor::after {
content: '';
display: block;
height: 0;
clear: both;
}
Finalmente se descubrió otro truco (un truco dentro de otro truco, qué es esto, ¿inception?). Esta vez se trataba de la propiedad overflow
, que si la ponías en el padre con cualquier valor otro que visible
, éste volvía a tomar en cuenta la altura de los hijos flotados.
Es decir, el siguiente método también corregiría el anterior problema:
#contenedor {
overflow: hidden;
}
Aún así, float
trae consigo algo curioso: el ancho de los elementos flotados pasará a ser el mínimo posible con respecto a su contenidio. Tendríamos que sacar la calculadora y calcular nosotros el ancho que le corresponde a cada elemento teniendo en cuenta cosas como los márgenes. Pero eso es lo de menos, el resultado está ahí.
Inline-block, el método bueno
Si has llegado hasta aquí te habrás podido dar cuenta que hacer algo tan simple como organizar el contenido de tu página en columnas puede sentirse sucio con el anterior método. Tranquilo, es normal.float
no es la forma ideal para hacer columnas (y a medida que vayas leyendo te darás de cuenta que esta tampoco lo es).
El método inline-block
, como otro truco que es, funciona haciendo comportar a los elementos de tipo bloque como elementos en línea, conservando algunas propiedades de los bloques. Es decir, básicamente los bloques seguirían el baseline
del texto, se colocarían uno al lado del otro y su tamaño se adaptaría a su contenido.
Vamos a probarlo:
#contenedor .columna {
display: inline-block;
}
Simple y efectivo, ¿no? No te creas. Aunque sí es cierto que la eficacia del método es indudable, hay que tener en cuenta que sigue siendo un «truco» y los posibles errores secundarios pueden llegar a ocurrir.
Un error muy común que con este método ocurre cuando empiezas a anidar elementos unos dentro de otros, sobre todo cuando el flujo de dichos elementos cambia.
Aunque esto depende mucho de tu código, es posible que en algún momento te encuentres con el efecto escalera, como por ejemplo en este foro (lo encontré de forma totalmente aleatoria y lo pongo como ejemplo):
Este problema ocurre porque el flujo de los elementos inline-block
sigue el baseline
(la línea del texto) y el flujo de alguno de los elementos anidados provoca que se realinee contra el baseline
.
Mucha gente se queda en la anterior propiedad para crear las columnas, pero así como los float
van acompañados de clear
o overflow
, inline-block
va pegado de vertical-alignment
.
vertical-alignment
cambia la forma en la que se alinea un elemento con respecto al baseline
. Ponerle el valor top
a la propiedad vertical-alignment
en las columnas debería solucionar el problema en la mayoría de los casos:
Hasta este punto hemos pasado por dos métodos y los dos tenían sus desventajas. Si te has fijado, los anteriores métodos no eran más que pequeños trucos utilizados para obviar la carencia de un método nativo en CSS para hacer columnas. Seguramente incluso ya sabías la existencia de ambos métodos y cómo corregir dichos errores. Sin embargo, te traigo malas noticias. Has estado haciéndolo mal todo este tiempo.
Flexbox, el método «like a boss»
Ha entrado un nuevo jugador a la partida. Éste nuevo jugador esflexbox
, un conjunto de propiedades CSS diseñadas para crear elementos flexibles, teniendo en cuenta la necesidad de los desarrolladores para crear cosas como columnas.
Aunque la cantidad de propiedades que vienen con flexbox
son enormes y no las voy a explicar en esta guía (puedes buscar información en internet), sí que voy a explicar cómo hacer columnas e introduciros así a esta nueva tecnología.
Agárrate bien fuerte porque quizás te sorprende:
#contenedor {
display: flex;
}
Mola, ¿eh? Una simple propiedad con absolutamente ningún tipo de efectos secundarios porque ha sido creada pensando en esto.
Si has prestado atención a los anteriores métodos, en ambos existía un problema común: el ancho de cada elemento había que calcularlo. Esto puede resultar un problema si tu foro se adapta dependiendo de la resolución, puesto que se descuadrarían los elementos.
Flexbox tiene la posibilidad de hacer que los elementos ocupen todo el espacio disponible de forma automática. Prueba a poner el siguiente CSS:
#contenedor .columna {
flex: 1;
}