La declaración Css que lo hará posible será display: inline-block. Así que antes de meternos en harina, un poco de teoría e historia sobre este valor.
Display: inline-block
El valor inline-block se recoge en la especificación 2.1 y permite que elementos de bloque se comporten como de línea entre ellos.
O dicho de otra manera. Los inline-block pueden compartir la misma línea en el flujo del documento como los inline pero conservando propiedades de block.
Además de eso, y por la parte que tienen de elementos en línea acepta propiedades propias del texto, como alineamientos, lettter-spacing, etc.
El soporte de los navegadores a este valor no te debería preocupar. Según caniuse podemos afirmar que es total. Sólo se desmarca IE7 con un parcial: también lo soporta, pero sólo en elementos que por naturaleza son de línea.
Así que vamos a beneficiarnos de estas particularidades para lograr nuestro propósito: conseguir centrar un número desconocidos de elementos de los que tampoco sabemos a priori su contenido más o menos largo.
1. Doble centrado vertical y horizontal de un MENÚ de una línea.
El primer caso es el de la distribución de los items de un menú variables tanto en el número como en el la longitud del texto de cada enlace.
Tengamos el siguiente código Html:
<ul class="padre">
<li class="hijo">
<a href="#">Un enlace</a>
</li>
<li class="hijo">
<a href="#">Otro más largo</a>
</li>
<!-- Más items -->
</ul>
<li class="hijo">
<a href="#">Un enlace</a>
</li>
<li class="hijo">
<a href="#">Otro más largo</a>
</li>
<!-- Más items -->
</ul>
El uso de clases es para poder reutilizar el Css en las variaciones.
Y a continuación nuestro Css que comienza por un mini reset. De él sólo cabe reseñar el uso de la propiedad box-sizing porque no queremos preocuparnos por descuadres por los rellenos y bordes
* {
margin: 0;
padding: 0;
border: 0;
box-sizing: border-box;
-moz-box-sizing: border-box;
}
.padre {
background: #D5D5D5;
text-align: center;
font-size: 1rem;
letter-spacing: 1rem;
padding: 1rem 0;
}
.hijo {
background: #EFD996;
border: 1px solid #fff;
display: inline-block;
letter-spacing: normal;
}
.hijo a {
color: #444;
text-align: left;
text-decoration: none;
display: block;
padding: 0.5rem;
}
margin: 0;
padding: 0;
border: 0;
box-sizing: border-box;
-moz-box-sizing: border-box;
}
.padre {
background: #D5D5D5;
text-align: center;
font-size: 1rem;
letter-spacing: 1rem;
padding: 1rem 0;
}
.hijo {
background: #EFD996;
border: 1px solid #fff;
display: inline-block;
letter-spacing: normal;
}
.hijo a {
color: #444;
text-align: left;
text-decoration: none;
display: block;
padding: 0.5rem;
}
La alineación horizontal se debe al text-align: center y la vertical al padding superior e inferior de 'padre' y la separación entre items por el valor de letter-spacing
Los 'hijo' al tener declarado el valor inline-block se ven afectados como te decía al inicio por las propiedades de "texto" de 'padre'. Y lo único que necesitamos es volver al valor 'normal' la separación entre letras.
El resultado es el que ves a continuación:
Este caso tiene una contra: si la anchura de 'padre' no es la suficiente para todos los 'hijo' se pasan a la línea de abajo, alineado al centro y pegado al de arriba. Estéticamente feo.
2. Doble centrado y distribución homogénea en varias líneas. Galería de imágenes.
Podemos hacer alguna variación mínima en las propiedades de .padre, añadiendo un id (#segundo), para hacer la típica galería con distribución homogénea y así corregir el problema anterior de la segunda y sucesivas líneas y que en caso de que el número de items no sea múltiplo de los que caben por línea se coloque a la izquierda en vez del centro.
Nuestro Html de base, el típico y mínimo de una galería de miniaturas:
<article id="segundo" class="padre">
<section class="hijo">
<img src="pict141.jpg" alt="img" />
</section>
<section class="hijo">
<img src="pict132.jpg" alt="img" />
</section>
<!-- Más items -->
</article>
<section class="hijo">
<img src="pict141.jpg" alt="img" />
</section>
<section class="hijo">
<img src="pict132.jpg" alt="img" />
</section>
<!-- Más items -->
</article>
Y vamos con las variaciones Css. Recuerda que tanto la clase 'padre' como 'hijo' del ejemplo anterior siguen en uso.
#segundo {
width: 50%;
margin: 0 auto;
padding: 0;
letter-spacing: 15px;
text-align: justify;
border: 15px solid #D5D5D5;
border-bottom: 0 none;
}
#segundo .hijo {
margin: 0 0 15px;
width: 31%;
min-width: 600px;
min-height: 115px;
vertical-align: top;
padding: 0.5rem;
}
#segundo img {
width: 100%;
}
width: 50%;
margin: 0 auto;
padding: 0;
letter-spacing: 15px;
text-align: justify;
border: 15px solid #D5D5D5;
border-bottom: 0 none;
}
#segundo .hijo {
margin: 0 0 15px;
width: 31%;
min-width: 600px;
min-height: 115px;
vertical-align: top;
padding: 0.5rem;
}
#segundo img {
width: 100%;
}
La igualdad entre el espacio vacío de los laterales de la caja 'padre' y los ríos entre items lo conseguimos con el borde superior y de los laterales del padre de igual valor al margen inferior de los items. Y la separación entre los 'hijo', como antes, es obra de letter-spacing declarado en '#segundo'.
Para lograr que los items de la última fila se coloquen a la izquierda cambiamos la alineación del texto de centrado a justificado en la caja padre y a los hijos la alineación vertical la declaramos en 'top' y por las particularidades del ejemplo ayudo con un min-height por cuestiones de estética
El tamaño de las imágenes queda controlada por su anchura (100%). Recuerda que los porcentajes siempre son relativos no al propio elemento sino al que lo contiene.
El resultado es el que ves a continuación:
3. Tercera y última variación: galería horizontal con scroll
Y para terminar, una distribución horizontal con scroll. El marcado Html es el mismo que el anterior, así que nos lo ahorramos y directos al Css:
#tercero {
border-left: 1rem solid #D5D5D5;
border-right: 1rem solid #D5D5D5;
white-space: nowrap;
margin: 0 auto;
overflow: auto;
padding: 1rem 0 0;
width: 70%;
}
#tercero .hijo {
margin: 0 0 1rem;
vertical-align: middle;
padding: 0.3rem;
}
#tercero img {
height: 10rem;
}
border-left: 1rem solid #D5D5D5;
border-right: 1rem solid #D5D5D5;
white-space: nowrap;
margin: 0 auto;
overflow: auto;
padding: 1rem 0 0;
width: 70%;
}
#tercero .hijo {
margin: 0 0 1rem;
vertical-align: middle;
padding: 0.3rem;
}
#tercero img {
height: 10rem;
}
En este caso conjugamos el borde y relleno en la caja padre con el margen inferior de los hijos para darle un poco de aire en los laterales.
Y para no tener necesidad de calcular el ancho de la caja padre en función del número y tamaño de sus hijos (prácticamente imposible ya que estamos trabajando con el supuesto de desconocer esas variables a priori), hacemos uso de la swclración white-space: nowrap que en combinación con la anchura declarada y el overflow fuerzan la aparición del scroll.
En este último caso, los hijos los alineamos verticálmente al centro. Esto al gusto.
Y para terminar y conseguir cierta armonía en el tamaño de las imágenes las igualamos en altura porque son apaisadas.
Este es el resultado final:
4. Disclaimer y agradecimiento
Recuerda que estos ejemplos son sólo eso, ejemplos. Así que si decides usar alguno posíblemente tengas que retocarlo para ajustarlo a tus necesidades. Amén de tener que corregir algún despiste o fallo que seguro he cometido fruto de las prisas, ignorancia y mala cabeza.
Así que cualquier corrección o sugerencia se agradece. Tienes los comentarios a tu disposición.
Y para terminar este tocho que me ha salido, gracias a D. Oloman por prestarme su blog para compartir esta curiosidad con su lectores. Ha sido un placer.
5. Y final
Y ya que lo tengo a mano, por si alguno aún se preocupa por el innombrable en su ver.7 y quiere tenerlo presente, sólo tienes que añadir al ejemplo lo siguiente:
.hijo, #segundo .hijo {
*display: inline;
*margin: 10px; /*al gusto o necesidad*/
}
#tercero {*height: 120px; /*al gusto o necesidad*/}
*display: inline;
*margin: 10px; /*al gusto o necesidad*/
}
#tercero {*height: 120px; /*al gusto o necesidad*/}
Esta entrada está escrita por @Kseso, alguien a quién no conozco mas que por su blog y desde hace muy pocas semanas. Ayer, en lo que fue una enajenación mental espero que pasajera y tras un pequeño (pequeñísimo realmente dado el medio) intercambio de ideas en Twitter sobre el centrado, acordamos intercambiar los posts que cada uno habíamos preparado para hoy.
En esta ocasión no me va a costar nada saber quién lee realmente las entradas del blog hasta el final ;)
Kseso Css: Blog recomendado para estar al tanto de todo lo referente a CSS.
Nota: Los ejemplos mostrados con JSFIDDLE son accesibles desde el icono + y allí podréis trastear para probar los efectos de cada propiedad así como posibles variaciones.
Actualización: Y ahora que dispongo de la URL, mi post en Kseso Css fue Centrar cajas flotantes sin ancho definido.
¿Vemos otro post al azar por si le encuentras utilidad o quizás prefieres ser más metódico y suscribirte a nuestras entradas por correo? También puedes imprimir este artículo y por supuesto compartirlo en redes sociales si fue de tu agrado.
Gracias Maestro por prestarte a esta locura.
ResponderEliminarEsperemos que la idea del intercambio guste y en pago no pierdas demasiados lectores de tu blog :-D
Un saludo
Mucha propaganda con lo del blog favorito del mes, pero tú no viste la entrevista entera... ¿O tal vez me pones ese adjetivo precisamente por eso? XD
EliminarNo lo he leído completo pero por encimita se ve buenísimo, gracias. Haré algún experimento con esto ;-)
ResponderEliminarIndependientemente de que "me la sabía" no podia dejar de felicitarte por el gran tutorial que has hecho. Enhorabuena. muy bien documentado y explicado.
ResponderEliminarUn pequeño tip. Para forzar el inline-block en ie7+ie6() {*display:inline;*zoom:1;}
Tengo una preguntita, sería poco optimo utilizar para una sección "padre" con 2 columnas o 3 columnas dependiendo de la resolución de pantalla y filas variables, utilizando media queries asignarles un margen lateral derecho y con el pseudoselector :nth-childe(even) y el :nth-child(3n+1) quitarles ese margen en cada uno de los dos casos. Como consecuencias de esto al acarrear herencia del css principal y a su vez de otras mediaqueries con tamaños diferentes de margenes a veces debo sobreescribir alguno. Cabe destacar que los elementos si poseen ancho y que es de vital importancia que no se produzcan reflujos o cualquier tipo de anomalía en la carga, zoom, etc.
ResponderEliminarComo dato los elementos primero y último de cada columna deben estar pegados a los laterales del div padre que los contiene y el margen entre elementos si es posible que se autocalcule. Para así no tener que variarlo con cada media querie.
En un principio me centro en lo último que dijiste y en ese caso ya no se trata de que sea lo óptimo o no, sino de que funcione. Yo usaría, como dijiste un margen nulo a la izquierda para el primer elemento y cada tres (3n+1) y lo mismo a la derecha para los múltiplos de tres (3n) y luego, mediante media queries, ajustar para las medidas en las que cambian el número de columnas.
ResponderEliminarPero quizás, según el diseño, se podría hacer con márgenes negativos en el elemento padre y overflow:hidden para que las columnas siempre se quedaran "pegadas" por los lados. No sé, normalmente hay varias soluciones, pero depende mucho de lo que se quiera hacer exactamente.
Tal como me lo has explicado, no visualizo del todo lo que me preguntas. Si pudieras montar lo básico en un CodePen seguro que te podría contestar mejor, porque no sé qué quieres conseguir y quizás haya otra forma de hacerlo.
El mayor problema que tenía era que al intentar mostrar 3 noticias por fila en resoluciones grandes tenía que estar sobreescribiendo las propiedades que utilizaba en el css principal o mediaqueries que no tuvieran un max-width asignado y se heredaban, y siempre me ha parecido que mientras menos líneas de código se utilicen mejor y ahí ya me estaban saliendo unas cuantas de más... a la izquierda me ahorre el margen porque sólo utilizo margin-right ya que al comenzar "pegado" al lateral no se necesita un margin-left, la verdad que al final no me convenció el diseño de 3 noticias por filas en resoluciones grandes, y ya me he quedado con 2 jeje. Así que ya la pregunta se reduce a: quizás ni si quiera se tenga que usar margin-right? y simplemente mediante el uso de algunas combinaciones de reglas css de estas avanzadas que ponen por aquí jeje se quede todo centrado del golpe sin necesidad de declarar ningún margen específico.
ResponderEliminarNo "visualizo" exactamente lo necesitas, pero por lo que entendí quizás te venga bien algo tan sencillo como esto.
EliminarLo siento perdí de vista el blog, he estado a full de trabajo... y ahora reflexionando sobre el tema, los dos problemas que les veo y siguen estando en la opción que me recomiendas, es que al reducir el zoom mucho se suelen descolocar los elementos, quizás con esa opción se no del todo, pero por lo menos en lo que coinciden tu versión y la mía es que utilizan margenes con em o px para alinear los elementos, y en la tuya los margenes son fijos, en la mía solo hay margin-right sino es un elemento último de fila. El asunto es que al utilizar margenes fijos a veces cuando aplicas la técnica de mediaqueries para hacer responsive tienes que cambiarlos, y no se hasta que punto con % se soluciona o descuadra. Por lo que me da la impresión de que no va a ser la solución lo que me pasaste. Te dejo por aquí un ejemplo del diseño que utilizo "realfitness.es" por si quieres echarle un vistazo al css. Saludos y gracias por la ayudita de todas formas. Tienes un gran blog con contenidos muy útiles.
ResponderEliminarVale además como soy muy tonto,no me di cuenta la opción más simple y ahora escribiéndote se me vino a ocurrir utilizas margin-right:2.94% por ejemplo en lugar de con em o px y fuera con el zoom se mantienen las proporciones. Que risa me voy a dar cabezazos estuve par de horas buenas un día probandolo jajajaja y no di con eso...
ResponderEliminarCasi siempre hay varias formas de conseguir lo mismo ;)
Eliminar