Centrado horizontal y vertical «like a boss»
Tabla de contenidos
Menos de 24h y ya escribo otra guía. Me parece justo, llevaba un mes sin publicar nada; aunque he de admitir que me gusta esta «serie», si es que se le puede llamar así.
Ahora toca el turno de los centrados, algo tan simple y que a su vez mucha gente implementa mal. Antes de empezar, vamos a situarnos. Cuando nos referimos a centrar tenemos que saber que existen dos formas de centrar las cosas: horizontal (con respecto al eje de las X) y vertical (con respecto al eje de las Y). A parte de esto, existen dos posibilidades para centrar dependiendo de si el elemento se comporta como un bloque o como texto. Es decir, tenemos 22 posibilidades para centrar.
La etiqueta
Este es el único método que deberías utilizar para centrar textos (por no decir el único —viable—, je je). Por lo general, se aplica la propiedad al padre y automáticamente centra el texto, dejando sin modificar las dimensiones del contenido.
Hay que destacar que esta propiedad se hereda en los hijos sucesivos a no ser que se diga lo contrario en uno de ellos y que las dimensiones de ninguno de estos se ven modificados (si fuesen bloques).
Vamos a verlo mejor con un poco de código:
Tanto
Sí señor. Esta es la forma en la que lo deberías estar haciendo. La propiedad
Existe un método bastante curioso para centrar el texto que implicaría poner la propiedad
Otro truco bastante original es utilizar la propiedad
Si no te habías dado cuenta cuando ya hablé de los position en el centrado vertical, te voy a comentar que también se podría haber utilizado el mismo método pero en vez de trabajar con la izquierda, trabajando con la parte superior (incluso con la inferior). Tan solo tendrías que hacer los mismo pasos, pero poner
Hasta aquí todos los métodos que se me han ocurrido para centrar. Es posible que se me haya escapado alguno que otro, pero básicamente la intención de esta guía era aclarar qué métodos son los correctos. Recuerda:
Centrado horizontal
<center>
o align="center"
, los métodos del demonio
La etiqueta <center>
es una etiqueta obsoleta, al mismo tiempo que añadir la propiedad align="center"
al padre del texto que quieres centrar.
<center>
lo que hace es crear un elemento de tipoblock
al rededor de todo su contenido. Dicho elemento lo que hacía (cuando no estaba obsoleto) era centrar los elementos de tipo bloque que fuesen hijos, además de todo el texto.align="center"
sigue una lógica similar a la anterior. Aunque su uso fuese recomendado desde que se desaconsejó el uso de<center>
, a día de hoy están ambas al mismo nivel de maldad.
Texto
Una vez mencionado los métodos malos para centrar de forma horizontal, vamos a analizar las alternativas correctas (o mejor dicho, alternativa) de centrar texto con CSS y, posteriormente, las de los bloques.text-align: center
, el método para dominarlos a todos
Este es el único método que deberías utilizar para centrar textos (por no decir el único —viable—, je je). Por lo general, se aplica la propiedad al padre y automáticamente centra el texto, dejando sin modificar las dimensiones del contenido.
Hay que destacar que esta propiedad se hereda en los hijos sucesivos a no ser que se diga lo contrario en uno de ellos y que las dimensiones de ninguno de estos se ven modificados (si fuesen bloques).
Vamos a verlo mejor con un poco de código:
<div id="contenedor">
<div id="contenido">
<div id="inception">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea iste ipsa ex sapiente rerum, alias unde atque debitis soluta iure quam exercitationem mollitia magni similique, dolores molestias ut, voluptates at?</div>
</div>
</div>
#contenedor {
width: 700px;
background-color: #4DC6BB;
padding: 20px;
}
#contenido {
width: 400px;
background-color: #FAC44D;
padding: 20px;
}
#inception {
width: 200px;
padding: 20px;
display: inline-block;
background-color: #FF6227;
}
Vamos ahora a aplicar la propiedad text-align: center;
a #contenedor
:
En la anterior captura podemos ver como el texto contenido en #inception
está ahora centrado, como era de esperar. Aunque la propiedad está colocada en su «abuelo», como no hemos especificado lo contrario en ninguno de los descendientes de éste, la propiedad se hereda hasta llegar a #inception
.
Además, el propio #inception
también está centrado. ¿Cómo es esto posible? Flerex, ¿no habías dicho que solo servía para texto?
Sí, es cierto. Pero si te fijas incluí también la propiedad display: inline-block
a #inception
, que lo hace comportarse como un bloque que sigue el flujo del baseline
del texto (es decir, se comporta como si fuese texto aunque conserva algunas características de los bloques).
He hecho esto para haceros ver que sí que se pueden centrar bloques con este método, pero no es por norma general el método que se debería usar. Solo en algunos casos específicos convertir un elemento bloque a inline-block
puede resultar útil. De lo contrario, podemos llegar a problemas con la alineación al baseline
como comenté ayer en «Columnas “like a boss”».
Bloques
En el ejemplo anterior ya hemos visto una posibilidad de cómo centrar un bloque, aunque no es un buen método. La manera ideal de centrar un bloque está en las próximas líneas, pero antes vamos a decir cómo no se debe centrar un bloque.position
, el método de los matados
Tanto position
con valor relative
como absolute
son métodos horribles para centrar. Requieren de que saquemos la calculadora para calcular cuántos pixeles tenemos que separar nuestro elemento desde el borde izquierdo, teniendo en cuenta su propio ancho. Muy engorroso. Tan engorroso que ni le dedicaré mucho tiempo.
El método con position: absolute
es el siguiente:
- Ponemos
position: relative
en el padre para que los hijos lo tomen como referencia. - Al hijo le añadimos la propiedad
position: absolute
(recuerda que desde el momento que pongas ese valor, el elemento no existirá para el padre a la hora de calcular las dimensiones del mismo, por lo que es posible que perdieses la altura y anchura si el elemento influyese en ellas). - Ahora tenemos que mover el elemento. Vamos a pensarlo con respecto a la izquierda, aunque sería lo mismo si se hiciese con respecto a la derecha. Ponemos la propiedad
left: 50%
para mover nuestro elemento la cantidad exacta de la mitad del ancho del padre. - Obviamente esto no estaría centrado, puesto que estaríamos moviendo nuestro elemento desde su esquina superior izquierda, no desde su propio centro. Para solucionarlo, tendríamos que reposicionar el elemento un poco más a la izquierda con exactamente la mitad de su ancho. Una forma de hacerlo sería
margin-left: -{la mitad del ancho del elemento}px;
o, si no quieres sacar la calculadora,transform: translateX(-50%)
.
position: relative
es aún más de locos puesto que habría que hacerlo todo con calculadora. Aún así solo funcionaría si el ancho del elemento fuese fijo (y no siempre es así). El método con absolute
tampoco funcionaría con ancho variable si se usase el truco de margin
(aunque sí funcionaría con transform
).
margin-left: auto; margin-right: auto;
, el método bueno
Sí señor. Esta es la forma en la que lo deberías estar haciendo. La propiedad margin
con valor auto
a ambos lados de un bloque lo centra perfectamente con respecto a su padre, sin más líos y sin ser tan engorroso como los anteriores trucos.
#contenido {
margin-left: auto;
margin-right: auto;
}
La propiedad funciona porque el valor auto
al margen indica que debe aprovechar tanto espacio como tenga disponible. Si solo colocásemos el valor auto
al lado izquierdo, se movería el bloque totalmente a la derecha. Al hacerlo tanto en babor como en estribor garantizamos que se utilice de forma equitativa el espacio a ambos lados.
Con este método solo el elemento al que le aplicamos la propiedad se ve afectado, y esto es algo bueno, puesto que hace el CSS más predecible.
Flexbox, el método «like a boss»
Sí, ya hemos llegado aquí. El momento de las guías de la serie «like a boss» donde predico sobre lo bueno que es flexbox. En este caso, flexbox va a aparecer varias veces en esta guía. Aunque quizás no merezca la pena en un principio utilizar flexbox para centrar de forma horizontal al tener efectos «secundarios» sobre cómo se comportan los elementos hijos, una vez que lo dominas a la perfección verás que será tu primera opción. La forma de centrar los elementos con flexbox es la siguiente:- Aplicamos al padre del elemento o elementos que queremos centrar la propiedad
display: flex;
. - Por defecto, flexbox hace que todos los hijos estén en una misma línea, el eje de las X. El comportamiento normal del flujo de los bloques es que uno se debe colocar bajo el otro. Para obviar esto en flexbox tenemos la propiedad y valor
flex-direction: column;
, que pasa a trabajar sobre el eje de las Y. Aunque no es exactamente lo mismo y sigue teniendo otros comportamientos ajenos al comportamiento normal de flujo (véase la documentación de flexbox para información más detallada), nos servirá para la mayor parte de los casos. - Añade la propiedad
align-items: center;
si estás trabajando sobre el eje de las Y (es decir, si has añadidoflex-direction: column;
ojustify-content: center;
si no lo has añadido (por ejemplo, si solo tenías un elemento no sería necesario cambiar el eje de trabajo).
#contenedor {
display: flex;
flex-direction: column;
align-items: center;
}
Aún así, flexbox sigue teniendo comportamientos especiales que hay que tener en cuenta. Por ejemplo, los elementos siempre ocuparán todo el espacio del eje alternativo (el eje con el que no estés trabajando, las Y si no has puesto flex-direction: column;
y viceversa).
Todos estos comportamientos dejan de ser un problema cuando se aprende flexbox, por lo que te invito a buscar en internet información sobre él para dominarlo a la perfección y aprovecharte de todas sus capacidades.
Centrado vertical
Aquí llega la gallina de los huevos de oro. Lo que seguramente estabas esperando. El centrado horizontal son juegos de niños y todo el mundo lo sabe. No hay que ser muy genio para saber que<center>
es de malos desarrolladores y que margin
es bastante straightforward
.
El problema que tiene el centrado vertical es que, mientras que por defecto el ancho de los bloques toman todo el espacio disponible, el alto solo toma el espacio necesario para mostrar el contenido (¿¿¿POR QUÉ??? No me lo preguntes a mí. Yo no soy 100tifiko. Venga, ya está con los memes del 2000).
Utilizar un margin-top: auto
y margin-bottom: auto
simplemente haría que dichos valores se calculasen a cero. En realidad no se puede porque, en resumen, provocaría que el navegador entrase en un bucle infinito a la hora de calcular las alturas.
Entonces… si no se puede, ¿cómo se centra de forma vertical?
Texto
line-height
, el método masoca
Existe un método bastante curioso para centrar el texto que implicaría poner la propiedad line-height
a exactamente el mismo valor que la altura del elemento. Obviamente esto solo da problemas, puesto que no se podría tener varias líneas de texto, pero funciona en cosas simples como por ejemplo una navegación.
Si no lo he dejado ya a entender, este no es un buen método.
vertical-align: middle;
, para los que son unos morbosos de las tablas
Otro truco bastante original es utilizar la propiedad vertical-alignment: middle;
. Como supongo que ya sabrás, esta propiedad está ideada para trabajar con elementos inline
y table-cell
. Los elementos inline
los vamos a descartar porque es una tontería trabajar con ellos. El método que vamos a analizar es el siguiente:
- Convierte tu elemento en un
table-cell
condisplay: table-cell;
. - Por limitaciones, tiene que haber un padre con
display: table;
- Añade a la celda, la propiedad
vertical-alignment: middle;
- Añade al padre
width: 100%;
para que se comporte como un bloque.
flexbox, again
Este es el método para centrar verticalmente textos que me he dado cuenta que es el mejor. Como el método es igual que para centrar bloques, lo dejaré para el final, para la guinda del pastel.Bloques
position: relative;
y position: absolute;
, the return of the matados
Si no te habías dado cuenta cuando ya hablé de los position en el centrado vertical, te voy a comentar que también se podría haber utilizado el mismo método pero en vez de trabajar con la izquierda, trabajando con la parte superior (incluso con la inferior). Tan solo tendrías que hacer los mismo pasos, pero poner top: 50%;
y compensar el tamaño del elemento restándolo con margin-top: -{la mitad del elemento}px;
o el equivalente CSS3 transform: translateY(-50%)
.
flexbox. (Not this again ?)
¡Volvemos a los ejes! Yaaay. Centrar de forma vertical con flexbox es absurdamente simple. Tan solo tenemos que volver a tener en cuenta que el comportamiento de los elementos cambia con flexbox aplicado, por lo que tenemos que ser conscientes de ello. Como ya he explicado así un poco por encima cómo funcionan los ejes, voy a suponer que vamos a alinear elementos que están sobre el eje de las X (el por defecto). Para centrar un elemento, ya sea de tipo en línea o bloque, tan solo tenemos que añadirdisplay: flex
a su padre, junto con la propiedad align-items: center;
(justo lo contrario que antes). Automáticamente todos los hijos serán centrados verticalmente. Y ya está.
Hasta aquí todos los métodos que se me han ocurrido para centrar. Es posible que se me haya escapado alguno que otro, pero básicamente la intención de esta guía era aclarar qué métodos son los correctos. Recuerda:
- Para centrar de forma horizontal, utiliza el valor
auto
en losmargin
horizontales o, si sabes flexbox y lo estabas utilizando porque está relacionado con tu estructura, utilízalo directamente. - Para centrar de forma vertical, la mejor alternativa es directamente utilizar flexbox.