soy Kseso y esto EsCSS

Display: inline-block y sus espacios de separación. 8 soluciones más 1 universal

Display: inline-block y sus espacios de separación. 8 soluciones más 1 universal

·Por Kseso ✎ 47
Origen de la imagen: La colección de Internet Archive Book Images en Flickr

Lo siguiente seguro que lo has sufrido. Hacer uso de display: inline-block y encontrarte con esos px de separación entre los distintos elementos que mandan al traste nuestro diseño.

Desesperante.

Para quienes esto les resulte nuevo, es lo siguiente: 4 hijos con display: inline-block y una anchura del 25%. A priori deberían colocarse adyacentes y todos en la misma línea horizontal. Pero oh! sorpresa, nos encontramos con que el último hijo fuerza una segunda línea:


1º hijo
2º hijo
3º hijo
4º hijo

El ejemplo anterior responde a a los siguientes códigos:

<div class="pater"> <div>1º hijo</div> <div>2º hijo</div> <div>3º hijo</div> <div>4º hijo</div> </div>

Y su css asociado:

.pater > div { display: inline-block; width: 25%; /*** Sólo a efectos de visualización ***/ background: #F3F3A1; margin: 0; }

El porqué y de dónde provienen los espacios

Este comportamiento de los items con el valor inline-block de dejar un hueco entre cada uno de ellos es consecuencia de la parte que tienen de elemento en línea.

Las cajas con display: inline, por su naturaleza, se ven afectadas por dos propiedades: letter-spacing y word-spacing, ambas dependiente del tamaño de la tipografía font-size del padre.

Por eso, al estar situado cada ítem en una línea diferente, en el código que recibe el navegador para montar el DOM, lo computa no como salto de línea sino como un espacio en blanco tipográfico (no hay definido un pre y en este aspecto manda la parte de elemento en línea frente al comportamiento de los elementos de bloque).

Por eso todas las soluciones efectivas pasan por no generar dicho espacio de separación entre ítems en el DOM o hacerlo igual a cero jugando con propiedades que afectan a la tipografía.

Soluciones vía html

Todo junto y sin espacios

Es la que te encontrarás en la mayoría de las respuestas. Consiste en escribir en el html todos los items sin espacios en blanco ni saltos de línea:

<div class="pater"><div>1º hijo</div><div>2º hijo</div><div>4º hijo</div><div>4º hijo</div></div>
1º hijo
2º hijo
2º hijo
4º hijo

Eureka! Conseguido! uno a continuación del otro, sin nada que los separe y todos en la misma línea. Pero... se fue al traste todo nuestro empeño de tener nuestro html bien tabulado y estructurado.

Aprovecha las "particularidades" de html5

Como sabrás, html5 permite no cerrar ciertos elementos. Así que podemos utilizarlo para anular el espacio entre ítems en inline-block. Basta con optar por dejar el código del ejemplo con el que abría este artículo de la siguiente forma:

<ul class="pater"> <li>1º hijo <li>2º hijo <li>3º hijo <li>4º hijo </ul>

Manteniendo el mismo Css para ver los inline-block sin separación entre ellos:

  • 1º hijo
  • 2º hijo
  • 3º hijo
  • 4º hijo

Descompón la forma de escribir el html

Cambia la forma en que normalmente introduces los saltos de línea entre los elementos del html. Deja la apertura de un item a continuación del cierre de la precedente:

<ul class="pater"> <li>1º hijo</li><li> 2º hijo</li><li> 3º hijo</li><li> 4º hijo</li> </ul>
  • 1º hijo
  • 2º hijo
  • 3º hijo
  • 4º hijo

Añadiendo comentarios vacíos

<ul class="pater"> <li>1º hijo</li><!-- --><li>2º hijo</li><!-- --><li>3º hijo</li><!-- --><li>4º hijo</li> </div>
  • 1º hijo
  • 2º hijo
  • 3º hijo
  • 4º hijo

Soluciones vía Css

Pero si estamos ante una particularidad que genera Css, éste debería aportar alguna vía para arreglarlo. Y sí, las hay.

Pues vamos a ver los distintos métodos para vía Css corregir este comportamiento.

White-space: nowrap y Overflow: hidden

Echamos manos del "viejo" Css2.1 y su control de los espacios en blanco white-space junto al control de los desbordes con overflow para conseguirlo... a medias.
Todos alineados pero el espacio permanece. Y además hay una pequeña "trampa": quita el overflow y verás qué ocurre con el último hijo.

div.nowrap { overflow: hidden; white-space: nowrap; } div.nowrap > div.white-space { display: inline-block; white-space: normal; }
1º hijo
2º hijo
3º hijo
4º hijo

Márgenes negativos

Consiste en declarar un margin-right con valor negativo a los elementos declarados como inline-block. En las distintas pruebas que he hecho el valor está comprendido entre -0.26em a -0.29em. Un valor que podría ser válido curándonos en salud sería -0.3em

Separación entre letras negativa

Atacando el problema por lo escrito, que se lee. La separación también desaparece con un valor negativo para letter-spacing aplicado al contenedor y compensado en los hijos

.padre {letter-spacing: -0.35em} .hijo {letter-spacing: normal;}

Pero esta vía tiene su problema. La separación necesaria es función de cada tipo. Así para verdana=-0.33em / arial y times new roman=-0.28em / tahoma=-0.33em según mis pruebas.

Tamaño de la fuente

Y para terminar la guerra a los espacios en blanco de los elementos con position: inline-block nada como reducir el font-size del padre a cero (0) y compensarlo en los hijos.

.padre {font-size:0;} .hijo {font-size: 1rem;}
1º hijo
2º hijo
3º hijo
4º hijo

Si te fijas en este último ejemplo, el tamaño de la fuente en el hijo la he declarado en rem. La razón es obvia. No puedes usar "em" para el hijo. El cómputo se haría sobre el tamaño del padre y 0*X=0 siempre.

Hay que desechar las unidades que el consorcio define como "relativas" y los "porcentajes" y usar las de "medida" (px, pt, mm...) o las de "tamaño absoluto" ( xx-small | x-small | small | medium | large | x-large | xx-large )

Actualizado: 04/2012

La técnica del font-size:0; no funciona en el navegador de Android pre-Jellybean. En los posteriores a Jellybean sí los suprime, pero por desgracia no lo hace con todos. Ver pen.

Solución universal para los espacios en blanco de separación de inline-block

Actualizado: 07/2013

Todas las anteriores individualmente fallan en alguna situación o en algún navegador. Así que si buscas una forma con total garantía, incluidos los ie6 y superiores, te recomiendo este artículo del blog: Solución universal para Display: inline-block y sus espacios de separación. Hasta para ie6.

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

Esta solucción tuvo un momento que dejó de ser "universal" debido a un bug en los webkit/Blink. En la actualidad ya ha sido corregido como puedes ver en el pen de ejemplo.

Para una explicación detallada pasa por su artículo Solución universal para Display: inline-block y sus espacios de separación. Hasta para ie6.

Actualizado: 03/2016

Hoy por hoy (2016) la mejor solución 'universal' pasa por olvidarse de display: inline-block y usar en su lugar el flexbox. Sin duda.

avatar del Editor del blog

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 Don Kseso Kseso