soy Kseso y esto EsCSS

Centrando al centro con Css: Todas las formas conocidas para hacerlo (25)

Actualizado: Noviembre 2015: 26+ formas totalmente distintas de centrar elementos con css y algunas variaciones: en la horizontal, la vertical o ambas. Elementos de bloque, línea, posiciones absolutas, relativas, de tamaños conocidos o ignorados, cajas, textos, imágenes...

Centrando al centro con Css: Todas las formas conocidas para hacerlo (25)

·Por Kseso ✎ 92

centrar cssPocas cuestiones como el tema de centrar suscitan tantas y tan variadas consultas por quienes se inician en Css. Bueno, y no tan iniciáticos. Este tema suele ser fuente de múltiples frustraciones. Y en la mayoría de los casos el error inicial es no pararse a pensar en qué tipo de elemento se pretende centrar y qué propiedades tiene.

Al plantearse centrar un elemento con css hay que tener claro como cuestión preliminar si es un elemento de bloque o si es de línea, si a priori se conocen sus dimensiones y en qué unidad están definidas (absoluta o relativa) y las de su contenedor. Sin olvidar que no es lo mismo el centrado en X (horizontal) que en el eje Y (vertical). Y por supuesto, no confundir que no es lo mismo centrar un contenedor respecto a su ancestro que su contenido.

Así que vamos a ver diferentes formas (16) 26+ de centrar una caja con Css.
¡Ah! Se me olvidaba una obviedad, pero creo necesario apuntarla:

Sólo se puede centrar un elemento dentro de otro cuando su tamaño es inferior al de la caja que lo contiene. Sí, es demasiado obvio, pero ya me he encontrado con algún caso de querer centrar cajas con mayor tamaño o igual al de su contenedor.

Y otra obviedad: tampoco confundas centrar con alinear. Aunque sea alinear al centro. Normalmente en el caso de las alineaciones al centro todo se reduce a dos casos: centrar la caja padre en su ancestro si controlamos su tamaño para que sea el de su contenido o el de éstos, los elementos hijos, repartirlos en la anchura del padre para que el espacio vacío sea igual por sus laterales.

Centrado horizontal de elementos

El caso más sencillo es el de una caja, elemento de bloque, del que conocemos su anchura, que queremos centrar en la horizontal de la ventana (u otro bloque).
Lo primero declaramos unos estilos básicos para visualizarla. Utilizo el elemento amarillo con la cuadrícula como elemento en el que hacer el centrado:

.caja { background: #D5CABF; border: 2px solid #fff; width: 200px; }

Centrado horizontal con anchuras fijas y conocidas:

Como ves, la posición natural (sin altrear el flujo) de un elemento es la esquina superior izquierda de su padre. Para centrarla en la horizontal sólo necesitamos utilizar el valor auto de la propiedad margin. Dicho valor significa que el espacio del padre no ocupado por el hijo se reparte mitad a su izquierda y mitad a su derecha.
Nuestro Css y resultado sería el siguiente:

.caja { width: 200px; margin: 0 auto; }

Fíjate bien:
En ningún lugar menciono el uso de text-align: center contrarrestado por una alineación posterior a la izquierda y la familia de los IE.
NO SE NECESITA
O mejor dicho. Sólo hay una situación y un navegador donde sería necesario utilizar esa combinación de declaraciones: ausencia de doctype en ie6. Así que mejor no cometer la burrada de no usar doctype.

Centrado horizontal anchura relativas:

La técnica anterior de margin: 0 auto; también es efectiva si la anchura de la caja a centrar está definida en valores relativos, por ejemplo en %:

.caja { width: 60%; margin: 0 auto; }

Fíjate bien, lo que estamos haciendo es centrar la caja respecto a su contenedor, no los contenidos.

Centrado horizontal sin anchura declarada

En los casos que no queremos/podemos definir una anchura a la caja a centrar, podemos recurrir a definir los márgenes laterales. El valor de la anchura por defecto es auto, que significa que ocupará toda la anchura disponible de su padre. Y en el modelo estándar de cajas de la anchura del padre primero se restará el margen y border del hijo, así como el padding y el resto será la anchura del hijo:

.caja { padding: 1em 3em; margin: 1em 25%; }

Recuerda que cuando se utilizan anchuras en % es conveniente declarar las propiedades max/min-width para prevenir los colapsos o desbordamientos.

Centrado de elementos posicionados

Hasta ahora, en todos los ejemplos hemos usado sólo el margen para desplazar un elemento del lugar que le correspondería ocupar. Pero para lograr lo mismo, Css también tiene las propiedades de posicionamiento (top/right/bottom/left) que pueden ser utilizadas en los elementos posicionados (positionstatic;).
Antes de continuar, recuerda que los elementos con position:relative; que son desplazados con estas propiedades, para los demás es como si no hubiesen sido movidos. Los ven y se comportan como si estuviesen en la posición original. Ve las explicaciones y ejemplos en el enlace anterior.

Doble Centrado en X e Y: posición absoluta y medidas conocidas

Si se conocen las medidas tanto del padre como del hijo, podemos utilizar la propiedad de posicionamiento para centrar al hijo. Para hacerlo fácil hay una fórmula que puedes usar:
left = (AnchuraPadre - AnchuraHijo) / 2

Y lo mismo para top con las alturas. Vamos con un ejemplo:

.padre { position: relative; width: 400px; height: 300px; } .hijo { position: absolute; /* podría ser relative */ width: 200px; height: 200px; }

Según la fórmula anterior, para el centrador horizontal, calculamos el valor de left= (400px-200px)/2= 100px
y para el centrado vertical el valor de top= (300-200)/2=50px
Así que el css para el centrado horizontal y vertical del hijo quedaría así:

.hijo { position: absolute; /* podría ser relative */ width: 200px; height: 200px; left: 100px; top: 50px; }

y el resultado:

Este método funciona utilizando la misma unidad para los valores (por ejemplo en % en vez de px). Recuerda que el % se calcula sobre el valor del padre (declarado o computado).

style="width: 50%; height: 200px;
width: 60%; height: 100px; left: 20%; /*(100%-60%)/2*/ top: 50px;

Doble centrado sin márgenes negativos con posición absoluta

Añadido: Agosto de 2013

Simple y genial, esta obra que vi en Jsfiddle. Es tan sencilla que parece mentira que nadie hasta ahora lo haya descubierto.

See the Pen XmMOdR by Kseso (@Kseso) on CodePen.

Pese a que en la vertical el valor 'auto' para 'margin' no surte efecto, al actuar sobre una caja con tamaños declarado y estar posicionada a 0 en las cuatro propiedades (left/top/right/bottom) la magia ocurre.

Una realización más compleja y explicada [ing] la tienes en este pen

Doble centrado. Padre medidas "fluidas".

Un caso particular de los anteriores se presenta cuando se desconocen las medidas del padre (por ejemplo la ventana del navegador) y las del hijo son conocidas, ya sean en valores absolutos o relativos.
En estos casos se vuelve a recurrir a posicionar el elemento al centro y compensar su posición con márgenes en negativo. Recuerda que al posicionar un elemento, se hace tomando como punto de colocación no el centro de la caja que se desplaza, sino la esquina correspondiente a la propiedad utilizada. Así si es top: 50% el punto es la esquina superior izquierda.

Aquí también podemos utilizar una fórmula para calcular el valor del margen lateral a utilizar:
margin-left = -(AnchuraHijo /2)
margin-top = -(AlturaHijo /2)

.hijo { position: absolute; left: 50%; top: 50%; width: 400px; height: 200px; margin: -100px 0 0 -200px; }
.hijo { width: 400px; height: 200px; left: 50%; top: 50%; margin: -100px 0 0 -100px; }

Con este método debes tener mucho cuidado. ¿Recuerdas qué ocurre con los elementos sacados del flujo?
Imagina que el .hijo tiene una anchura de 700px. Como su margen será de -350px no habrá problemas siempre que su .padre (la ventana de navegador por ejemplo) sea mayor de 700+350=1050px. A tamaños menores el .hijo ya no será visible. Si redimensionas la pantalla a 800px se perderán 250.

Doble centrado con margin: auto en el Flexbox

NUEVO ENERO 2015

Por @LeaVerou me llega esta forma usando margin: auto en el flexbox:

See the Pen doueble centered with margin: auto; on flex by Kseso (@Kseso) on CodePen.

Tienes este artículo sobre esta forma de doble centrado. Posíblemente sea la forma más sencilla y que menos Css necesita.

Doble centrado medidas desconocidas con transform

NUEVO MAYO 2013

Una variante del anterior para los casos en que se desconocen las medidas del hijo es recurrir a las transform

¡Mira mamá! centrado!
.centrado { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }

Doble centrado múltiples elementos en tamaños desconocidos o ventanas dinámicas

NUEVO: 01/2013

Esta forma solventa el problema anterior, ya que no se necesita ningún margen lateral negativo ni superior tan grande. Además añade la ventaja de que no se necesita conocer de antemano los tamaños de los elementos a centrar:

Puedes verlo en este pen o este fiddle:

See the Pen double centered in unknown or dynamic sizes by Kseso (@Kseso) on CodePen.

La clave está en la relación entre el valor en negativo del margen superior de la lista (es el elemento seleccionado para el ejemplo) y el line-height de los enlaces que conforman el menú (los elementos que se centran.

Doble centrado con la propiedad calc

NUEVO: 12/2012

Aunque de momento el soporte a la propiedad calc() es limitada, con ella se puede lograr un doble centrado (vertical y horizontal) de forma rápida y sencilla:

.calc { height: 12rem; width: 14rem; position: absolute; left: calc(50% - 7rem); top: calc(50% - 6rem); }

Centrado de Texto

Para el centrado horizontal de texto, ya esté contenido en un párrafo (p), en un hnº o en cualquier elemento de bloque, basta con utilizar la propiedad text-align: center; .

Doble centrado de texto

Para el centrado en X e Y de una sola línea podemos utilizar la propiedad line-height, dándole un valor en función de la altura de la caja padre que la contenga:

.padre { height: 200px; } .hijo { line-height: 200px; text-align: center; }
EsCss

Observa que el tamaño del texto font-size no influye. Así mismo, si en line-height se utilizan unidades relativas (em, %...) el cómputo se realiza sobre el tamaño de la tipografía (f-size). Por lo tanto, el centrado con ésta técnica no sirve si se desconoce a priori la altura de la caja.

Si quieres centrar un h1, por ejemplo, en la ventana del navegador, deberás utilizar una de las técnicas anteriores para centrar al .hijo sabiendo su altura y en el h1 utilizar la altura de línea.

Centrado con Display

Si has prestado atención a todos los casos planteados hasta ahora, posíblemente te hayas dado cuenta que no he mencionado una propiedad que a priori parecería que es la más indicada para el centrado vertical: vertical-align, o la alineación en la vertical. La razón la encontrarás en lo que dice la especificación sobre esta propiedad:

vertical-align: Se aplica a los elementos a nivel de línea y 'table-cell'.
Esta propiedad afecta el posicionamiento vertical dentro de una caja de línea de las cajas generadas por un elemento a nivel de línea. Los siguientes valores sólo tienen significado con respecto a un elemento a nivel de línea padre, o a un elemento a nivel de bloque padre, si ese elemento genera cajas de línea anónimas; no tienen ningún efecto si no existe tal padre.

Centrado con "Display: table" y asociadas

Así que para utilizar el vertical-align hay que provocar que el comportamiento de un elemento de bloque sea como el de una tabla. Para ello, Css define el valor table y asociados para la propiedad display.

Display: Se aplica a todos los elementos.
Valores del grupo de tabla: table, inline-table, table-row-group, table-column, table-column-group, table-header-group, table-footer-group, table-row, table-cell y table-caption
Estos valores provocan que un elemento se comporte como un elemento tabla.

En puridad, habría que definir al menos tres elementos con estas propiedades: uno con table, su hijo como table-row y el tercero a centrar como table-cell.

Cuando sólo tenemos un elemento en el body y lo queremos centrar en la ventana del navegador, podemos utilizar el selector html y body para lograrlo:

html { display: table; height: 100%; width: 100%; } body { display: table-row; } h1 { display: table-cell; vertical-align: middle; text-align: center; }

Y en la captura de abajo ves el resultado. El <h1>EsCss</h1> se centra tanto en la horizontal como en la vertical con independencia del tamaño de la ventana:

Para el siguiente ejemplo, creo un div para aplicarle display: table, el amarillo cuadriculado con display: table-cell y el tercero es el centrado, en la horizontal con el margen:

<div style="display: table; width: 100%; height: 250px;"> <div class="ejemplo" style="display: table-cell; height: 100%; vertical-align: middle;"> <div contenteditable="true" class="centrada" style="width: 50%; margin: 0 auto;" EsCss Por una web con mucho estilo, para Argonautas con buen gusto. Contenido editable. </div> </div></div>
EsCss
Por una web con mucho estilo, para Argonautas con buen gusto. Contenido editable.

El motivo para ser tan poco usada hasta el momento la declaración display: table no es otro que el estropicio que con ella hacían los ie6 y 7. Lo mismo para el vertical-align, que ie7 sólo la maneja en elementos que por naturaleza son de línea.

Display: table; Punto y mini punto

Con una doble utilización partiendo de no saber absolutamente nada del elemento.

  1. No necesitas saber ni declarar la anchura de la caja que quieras centrar horizontalmente: con este display y los márgenes laterales en auto nada se resiste.
  2. Si lo declaras a un elemento de bloque (un div) que como es sabido lleva en sus genes apropiarse de todo el espacio horizontal disponible, harás que se extienda sólo en función de su contenido. Mira el ejemplo:
div { display: table; margin: 0 auto; } /*html :*/ <div> <img src="ruta.ext" alt="alt" /> </div>

El resultado:

la letra E de EsCss

Esta regla css (diplay: table + margin: X auto) puedes usarla en una clase para centrar las imágenes y así junto a las típicas .izquierda{} .derecha{} con sus float correspondientes cubrir los tres casos de alineación de imágenes.

Doble centrado del contenido

Si lo que queremos es centrar en la vertical el contenido en una caja, tan sencillo como:

.padre { display: table; height: 150px; /*valor que necesites* width: 60%; /*Valor que necesites*/ padding: 1em; /*sólo ornamental */ } .hijo { display: table-cell; vertical-align: middle; }
EsCss Por una web con mucho estilo, para Argonautas con buen gusto. Contenido editable.

En este último ejemplo también podrías alinear el texto al centro añadiendo text-align: center;

Centrado de elementos flotados sin conocer anchuras ni su númeroNuevo 03/2013

Típico caso de menú horizontal con un número indeterminado de opciones donde los li´s se encuentran flotados:

Centrar cajas flotantes sin ancho definido. Por @Oloman

Tienes un artículo en este blog escrito por @Oloman, autor del blog Oloblogger, donde se explica detalladamente cómo lograrlo:

Ver artículo y demo

Centrar elementos flotados con fit-content

Utilizando el valor de width: fit-content se consigue centrar tanto la lista (ul) como sus items (li´s) sin necesidad de saber ni el número de ellos ni sus tamaños. Esto es, no es necesario calcular ni declarar tamaños. Y como bonus tampoco se necesita limpiar los float.

Puedes ver una explicación detallada en el artículo "Centrar elementos flotados con fit-content sin saber número ni tamaños" y este el ejemplo funcionando:

See the Pen Fit-content: Items floated and centered by Kseso (@Kseso) on CodePen.

Ver Demo

Centrado de elementos en línea

Centrado con vertical-align

Otros casos de centrado, son aquellos en los que los elementos que intervienen son de línea y con diferentes alturas. El ejemplo típico es el de una imagen y un texto dentro de un bloque.

<p><img src="ruta.ext" alt="alt" />Texto que acompaña a la imagen</p>

En estas situaciones, el elemento al que hay que declarar el vertical-align es a la imagen:

Lobo con piel de oveja

Esta solucción sólo es válida mientras haya una sola línea de texto. La 2ª y siguientes se posicionarán debajo (eje Y) de la imagen. Para esos casos hay que recurrir a otro método, como el siguiente.

Centrado vertical de múltiples líneas de texto respecto a una imagen

imagen con texto de varias líneas a su lado centrado en la vertical.
A la izquierda de este texto tenemos una imagen. El texto son unas cuantas líneas que se posicionan centradas respecto a la vertical de la imagen. Para este particular elijo el marcado figure y su asociado figcaption Los códigos Css y Html abajo.
figure {display: table;} img, figcaption {display: table-cell; vertical-align: middle;} Marcado Html <figure> <img src="barb.jpg" /> <figcaption> Texto extenso descriptivo de la imagen... </figcaption> </figure>

Centrado con padding

Otro caso típico es el centrar en X e Y un pequeño texto dentro de una caja, como suele suceder con el texto de un enlace en un menú

<ul> <li> <a href="#"....</a> </li> </ul>

Este caso tiene múltiples variables, pero básicamente se logra declarando los enlaces como bloques y asignandoles un padding superior e inferior y derecho e izquierdo de valor igual en cada par. Si los li´s tienen una anchura definida, basta con declarar la anchura del enlace al 100%, texto alineado al centro y padding superior e inferior al gusto.

Centrado horizontal y vertical con pseudoelemento CSS ::before

Una de las formas más sencillas de lograr un centrado simultáneo en ambos ejes, sin ser necesario añadir etiquetas en el html, es utilizar el pseudoelemeto ::before

EsCss Por una web con mucho estilo, para Argonautas con buen gusto. Contenido editable

Tienes una explicación más detallada en este artículo del blog.

Centrado en el flexbox

El nuevo modelo de caja flexible o flexbox provee nuevas formas de lograr el doble centrado, horizontal y vertical, de una forma súmamente sencilla:

Para una explicación pormenorizada del flexbox o "Flexible Box Model Layout" puedes ver este artículo del blog.

Más formas y más sencillas de centrar

Lo nuevo de Css3 para position

El documento del W3c "CSS Positioned Layout Module Level 3" introduce novedades sobre el posicionamiento de los elementos. Entre otras añade dos propiedades que podrán ser utilizadas para lograr centrar elementos:
Position: Center;
Position: Page;

Te remito a este artículo del blog donde ya las comenté.

CSS Box Alignment Module Level 3

Con la aparición de nuevas características de Css y los documentos del consorcio que las desarrollan se introducen verdaderas revoluciones como son el Flexbox y el Css Grid Layout. Los flex container y grid container crean espacios con características totalmente nuevas.

En ellos los ítems también necesitan de novedades para su correcto manejo. Un aspecto relativo a la distribución de los ítems respecto a su contenedor y respecto a ellos lo cubre y da respuesta el nuevo documento "CSS Box Alignment Module Level 3". Lo tienes explicado en el artículo [novb 2015] CSS Grid y el módulo Box Alignment.

Float: positioned

Sí, aún me dejaba una última para el final. Junto a las posiciones anteriores, Css3 en el documento "CSS Floats and Positioning Level 3" define el nuevo valor para la propiedad float: positioned. Este valor, junto a las propiedades de posicionamiento (top/bottom y left/right) también posibilita nuevas formas de centrar. Échale un vistazo al documento que te enlazo para ir conociendo lo más nuevo.

A modo de resumen final

Al plantearse el centrado de un elemento antes de escribir ni una sola línea de código Css hay que evaluar qué tipo de elemento es, qué contiene y dónde está contenido, así como proveer una serie de variables y las circunstancias en las que se desea lograr el centrado. Así se evitarán sorpresas desagradables y desesperar porque lo que pensábamos que iba a funcionar no lo hace como querríamos.

Espero que tu caso esté entre los que acabo de recoger en el post, porque sin pretender recopilar y dar una solucción a todos los posibles, sí creo que están los más comunes.

Lo que sí he dejado sin tratar es la alineación simultánea de varios elementos. O lo que es lo mismo: cómo distribuir equitatívamente varios hermanos en su caja padre. Este ya es tema para otro artículo:
Alineación simultánea: 3 dobles centrados de cajas en número y tamaño dispares.

¿Crees que me he dejado en el tintero algún supuesto común o el que a ti no te sale? ¿Conoces algún otro de los recogidos aquí? Si la respuesta es sí a cualquiera de esto, abajo tienes los comentarios para dejar constancia de mi olvido

avatar del Editor del blog

the obCSServer ᛯ Ramajero Argonauta, Enredique Amanuense de CSS.
#impoCSSible inside
Dicen que, en español, EsCss es el mejor blog de CSS. Posíblemente exageren.
@Kseso EsCss Kseso