Ni tan fácil ni tan difícil: centrando con CSS

Flor delante de una valla
Imagen de Aftab Uzzaman

El centrado en CSS es uno de los temas más recurrentes, y es que ¿quién no ha tenido algún percance con un elemento que quería centrar?, ¿quién no se ha dado de cabezazos contra la mesa?, o ¿quién no ha llegado a lanzar el teclado por la ventana?.

Si en alguna ocasión te ha ocurrido algo de esto, no desesperes, tan sólo preocúpate de recoger el teclado (lo vas a necesitar), del resto nos vamos a ocupar hoy en este artículo. Porque el centrado en CSS no es tan fácil, pero tampoco tan difícil.

Por regla general, a la hora de centrar un elemento, no tenemos en cuenta el modelo de caja con el que estamos trabajando, ni tampoco las propiedades definidas sobre dicho elemento. Esto nos lleva a cometer cierto tipo de errores que al final nos lleva irremediablemente a no conseguir centrar el elemento. En este artículo vamos a ver unas cuantas formas de centrado (que con el tiempo iré ampliando), para conseguir centrar un elemento en cualquier situación.

Centrado horizontal

Centrado horizontal de un elemento en línea

Un elemento en línea toma como valor la anchura de su contenido, con lo cual siempre y cuando el contenido del elemento tenga una anchura menor que la del padre del elemento, podemos centrarlo. ¿Y cómo?, pues con la propiedad text-align y su valor center aplicada sobre su padre.


.contenedor {
    text-align: center;
}

Este tipo de centrado también podemos usarlo si el elemento a centrar es inline-block.

Centrado horizontal de un elemento en bloque con anchura declarada

El caso más sencillo para centrar un elemento horizontalmente es conociendo su anchura, y nos da igual si sus medidas son fijas o relativas. Para ello sólo necesitamos el valor auto de la propiedad margin. Con esto conseguimos que el espacio del padre no ocupado por el hijo, se reparta equitativamente tanto a su izquierda como a su derecha.


.centrado {
    width: 12em;
    margin: 0 auto;
}

Centrado horizontal de un elemento de bloque sin anchura declarada: márgenes

Un elemento de bloque sin anchura declarada ocupa el 100% de su ancho disponible, con lo cual y a priori podrías pensar que no se puede centrar, pues no es así.

Jugando con sus márgenes podemos conseguir centrarlo, tan sólo necesitamos dar el mismo valor tanto a la izquierda como a la derecha, y voila, elemento centrado.


.centrado {
    margin-left: 1em;
    margin-right: 1em;
}

Centrado horizontal de un elemento sin anchura declarada: display:table

Un elemento con display:table se comporta exactamente igual a una tabla, y hay una propiedad muy interesante que nos interesa cuando intentamos centrar horizontalmente un elemento al cual no le hemos declarado un ancho. Una tabla amolda su ancho, siempre que sea posible, a su contenido.

Esta peculiaridad nos permite usar el margen automático a derecha e izquierda para poder centrarlo.


.centrado {
    display: table;
    margin: 0 auto;
}

También podríamos podríamos usar este centrado con un ancho declarado, aunque lo cierto es que no tiene mucho sentido hacerlo.

Centrado vertical

Centrado vertical de un elemento en línea

Este caso es muy común, sobre todo para elementos de texto, aunque vale para cualquier elemento en línea. Sólo hay que tener en cuenta que este elemento en línea debe estar contenido dentro de un elemento en bloque sin altura definida, como por ejemplo un texto dentro de un elemento p.

Un elemento en bloque sin altura definida toma como valor la misma que la de su contenido, por tanto para centrar verticalmente su contenido tan sólo es necesario darle un mismo valor a su padding superior e inferior.


p {
    padding-top: 2em;
    pading-bottom: 2em;
}

Centrado vertical de un elemento en línea que ocupa una sola línea

Este es un caso muy particular, y podría resolverse de la misma forma que el caso anterior, pero si conocemos la altura del elemento contenedor, podemos jugar con la propiedad line-height igualando su valor al de la altura del contenedor, y de esta forma el elemento en línea contenido aparecerá centrado verticalmente.


.contenedor {
    line-height: 5em;
    height: 5em;
}

Centrado vertical de un elemento con display:table

La propiedad display junto con su valor table nos permite jugar con una propiedad de CSS para centrar elementos de forma vertical, que no es ni mas ni menos que vertical-align.

Para ello necesitaremos un contenedor al que le aplicaremos display:table y un elemento a centrar con display: table-cell. Muchos puristas aseguran que es necesario un elemento intermedio con display:table-row, pero en realidad el centrado se realiza sin necesidad de él. ¡Ah!, y por mucho que te digan, realmente CSS no es semántico.


.contenedor {
    display: table;
}

.centrado {
    display: table-cell;
    vertical-align: middle;
}

Doble centrado

Hago esta clasificación para englobar propiedades que permiten centrar tanto horizontalmente como verticalmente, aunque también se pueden usar para centrar sólo verticalmente o sólo horizontalmente.

Doble centrado con medidas de padre e hijo conocidas: elemento posicionado

Si conocemos la altura y anchura tanto del padre como del hijo, podemos recurrir al posicionamiento para centrar el hijo, aplicando una simple fórmula: top = (altura del padre - altura del hijo) / 2 y left = (ancho del padre - ancho del hijo) / 2.


.contenedor {
    position: relative;
    widht; 6em;
    height: 8em;
}

.centrado {
    position: absolute;
    widht: 3em;
    height: 4em;
    top: 2em;
    left: 1em;
}

Doble centrado con medidas conocidas del elemento a centrar: márgenes negativos

Si únicamente conocemos las medidas del elemento a centrar el procedimiento es muy similar al caso anterior, pero en vez de aplicar la fórmula (de la que desconocemos datos) podemos jugar con márgenes negativos.


.contenedor {
    position: relative;
}

.centrado {
    position: absolute;
    top: 50%;
    left: 50%;
    widht: 6em;
    height: 4em;
    margin-top: -2em;
    margin-left: -3em;
}

Necesitamos usar márgenes negativos porque la referencia que tomamos del elemento es la esquina superior izquierda (borde superior y borde izquierdo), y lo que necesitamos es su centro. Es tan sencillo como mover el elemento (mediante márgenes negativos) hacia arriba y a la izquierda, concretamente la mitad de su alto y la mitad de su ancho.

Doble centrado con medidas desconocidas: transform

En ocasiones necesitamos realizar un doble centrado y no conocemos las medidas del elemento a centrar, y tampoco las del padre. En este caso la propiedad transform con su valor translate es todo lo que necesitamos.


.contenedor {
    position: relative;
}

.centrado {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate (-50%, -50%);
}

El centrado se realiza con el mismo cálculo que usamos con los márgenes negativos, teniendo en cuenta que cuando usamos porcentajes con el valor translate estos toman como referencia el tamaño (heigth o width) del elemento sobre el que se aplica transform. Puedes leer más a fondo sobre la propiedad transform y este comportamiento en el documento de la W3C CSS Transforms Module Level 1.

Doble centrado con medidas desconocidas: propiedades left/top/rigth/bottom.

Esta es una forma muy original de realizar un doble centrado, que vi por primera vez en este JsFiddle, referenciado en el artículo Absolute Horizontal And Vertical Centering In CSS de Smashing Magazine. Simplemente pura magia.


.contenedor {
    position: relative;
}

.centrado {
    position: absolute;
    top: 0;
    rigth: 0;
    bottom: 0;
    left: 0;
}

Doble centrado con medidas desconocidas: Flexbox

La "caja flexible" de CSS3 hace que las cosas sean muy sencillas y el centrado no podía ser menos. Definimos un contenedor con la propiedad display:flex y todos sus hijos son obedientes cajas flexibles (¡todos al centro!, ¡ar!).


.contenedor {
    display: flex;
    justify-content: center;
    align-items: center;
}

Doble centrado con medidas desconocidas: Flexbox y margin:auto

Una de las peculiaridades de Flexbox es como se comportan los elementos con esta propiedad cuando tiene algún margen en tamaño automático. Te aconsejo leas esta interesante artículo de Sam Provenza titulado Flexbox’s Best-Kept Secret y entenderás lo fácil que es hacer este centrado.


.contenedor {
    display: flex;
}

.centrado {
    margin: auto;
}