Ampliado: Mayo de 2013
Pocas 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) 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.
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:
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:
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 %:
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:
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 (position≠static;).
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).
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;
}
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 medidas desconocidas con transform
NUEVO MAYO 2013Una variante del anterior para los casos en que se desconocen las medidas del hijo es recurrir a las transform
.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:
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:
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;
}
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>KsesoCss</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;">
KSESOCSS
Por una web con mucho estilo, para Argonautas con buen gusto.
Contenido editable.
</div>
</div></div>
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.
- 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.
- 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:
Esta regla css (diplay: table + margin: X auto) puedes usarla en una clase para centrar las imágenes y así unto a las típicas .izquierda // .derecha con sus floats 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;
}
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 demoCentrar 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:
Check out this Pen!
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
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
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é.
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
+Kseso
Hola, quisiera centrar un par de menues o mejor dicho navcontainer de mi blog y no se como, me das una mano amigo???
ResponderEliminarHola nightcrawler23
ResponderEliminarComo habrá observado, el blog no está enfocado ni tampoco cuenta con las herramientas necesarias para ser un lugar de consultas y resolución de problemas concretos.
En la web encontrará multitud de sitios con esa finalidad y que además cuentan con las herramientas necesarias para exponer el problema y los códigos involucrados.
Un saludo
Excelente artículo!!
ResponderEliminarGracias, Jano
ResponderEliminargracias por el aporte, una consulta en mi caso el div padre mide 100% mientras que el div hijo 700px x 400px, como podria centrarlo, es que debo establecer las propiedades min-width y min-height para el padre ?
ResponderEliminarSin más información que la que aportas es imposible recomendar sin fallar uno de los 17 métodos de centrado que describo:
ResponderEliminarNavegador (versiones) a tener presentes, tamaños de "ventana" a tener en cuenta, ¿Los 2 divs son divitis o contenedor de otros elementos?, ¿qué tipo de contenido? ¿qué centrado? ¿En X, en Y, en los dos?...
Con tan escaso información sí se puede descartar alguno. Pero eso lo puedes hacer tú tranquilamente.
Como verás, el diablo y la virtud están en los detalles. Y mi carencia en que no soy adivino.
Un saludo.
tratare de ser un poco mas especifico y gracias x responder tan rapidamente, dentro de toda la ventana del navegador tengo un div ("all" - width:100%; height:100%), dentro de este tendre otro div (container width:800px; height:600px) lo que quiero es centrar al div container respecto al padre y que esto funcione en todos los navegadores y resoluciones, el div container tendra a su vez otros div, textos, images, etc. tenia duda si debia establecer un min-height y un min-width para el padre (div "all"). para asegurarme que no colapse la distribucion de las capas ? que tecnica me aconsejarias?
ResponderEliminarEn todos los navegadores (¿versiones también?) y resoluciones?
ResponderEliminarPues una mezcla de todas las formas descritas con ayuda de las @media queries y posiblemente comentarios condicionales para versiones anteriores de ie.
Y con una caja "tan grande" como 800x600, quien no conoce al detalle el proyecto, no recomendaría la técnica de los márgenes negativos (que sería soportado por todos y todas las versiones). El riesgo de que queden contenidos inaccesibles es demasiado probable en demasiadas situaciones.
Gracias, gracias, gracias, gracias y más gracias para siempre
ResponderEliminarsos un genio, para los que estamos iniciando en css tus tips son de muchisima utilidad, gracias por compartir.
ResponderEliminarSaludos,
Andres.