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

Por 30 Comentarios

8 forma diferentes, usando css o vía html, de eliminar la separación que quedan entre items con display: inline-block y una explicación del porqué sucede

Archivado en —

display:inline-block y sus espacios en blancoLo 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 esta posición y una anchura del 25%. A priori deberían colocarse adyacentes en la misma línea horizontal. Pero oh! sorpresa, nos encontramos esto:


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; }

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 las etiquetas. Así que podemos utilizarlo para anular el espacio entre items 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 </div>

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> </div>
  • 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 bug.

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 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.

El porqué y de dónde provienen los espacios

Lo que ahora me queda pendiente es averiguar de dónde o el porqué de esos espacios en blanco.
Este comportamiento de los items con el valor inline-block de dejar un hueco entre cada uno de ellos creo que puede ser a que aplica la propiedad letter-spacing del padre a los hijos, pues en ese aspecto es dominante la parte que el hijo conserva de elemento en línea.
Pero es una suposición. ¿Tú que opinas y cómo ves estos parches?

Publicado el por y Archivado en —

Cartas al Editor [ 30 ]

El autor de artículo y el blog estaremos encantados de leer tu opinión, críticas, corrrecciones, matizaciones, ampliaciones o cualquier comentario que su lectura te sugiera. Y lo agradecemos... siempre que esté hecho con educación, buenas maneras y respeto.
Para publicar código envuélvelo con la etiqueta [code] [/code].
Para insertar Pens de @codepen mira esta guía.

  1. Curiosas e ingeniosas soluciones. Gracias!

    ResponderEliminar
  2. Me he divertido con esto, muchas gracias!

    ResponderEliminar
  3. Hola tengo un problema cuando dentro de los div hijos pongo un H2 o H3 o cualquier H y un parrafo p y les pongo margin:0 o algun otro valor, el hijo contenedor genera un margen arriba y la caja(hijo) se baja como puedo solucionar esto, el error aparece solamante cuando modifico el margen de los H o P

    ResponderEliminar
  4. Hola CristiandR
    Como 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 de sus usuarios.
    En la web encontrará multitud de sitios que sí cumplen y tienen ese objetivo.

    Además es imposible localizar qué lo produce y cómo solventarlo sin analizar el código.

    No obstante todo lo anterior quizás le convenga leer sobre el concepto "margin-collapse":
    http://www.w3.org/TR/CSS2/box.html

    ResponderEliminar
  5. Este comentario ha sido eliminado por un administrador del blog.

    ResponderEliminar
  6. Anónimo19/8/12

    Este comentario ha sido eliminado por un administrador del blog.

    ResponderEliminar
  7. Anónimo3/11/12

    Capoooo GRACIAS con mayusculas.

    ResponderEliminar
  8. Anónimo30/11/12

    buenos hacks a tener en cuenta

    ResponderEliminar
  9. mmfilesi16/12/12

    muy buen artículo, gracias por las pistas.

    ResponderEliminar
  10. Pues estaba viendo y probando y también puedes arreglando usando display: table-cell y border:collapse

    ResponderEliminar
  11. Cada valor conlleva unas características que le son propias y en el momento que cambias el valor de display... ya es otro tema.

    Gracias por la aportación, Alejandro

    ResponderEliminar
  12. De gran ayuda =) quisiera saber si la forma quitando el final de la etiqueta li ,trae problemas adelante.Graciassss

    ResponderEliminar
  13. Muchas Gracias,me sirvio bastante.Quisiera saber si la forma de solucionar esto,quitando el final de la etiqueta li, trae problemas mas adelante en el tema de porcentaje o adaptabilidad de la web.Gracias

    ResponderEliminar
    Respuestas
    1. Hola Jonatan
      De entrada recuerda que esa práctica depende del doctype que se utilice. Sólo permitido con Html5.

      De todas formas soy de la vieja escuela, de aquel mantra que dice: "Cierra todo lo que abras"

      Puedes ampliar un poc el tema en el artículo "No es lo mismo, no da igual, elemento que tag"

      Un saludo

      Eliminar
  14. excelente la solucion del margin negativo, louso enmis plantillas lopueden ver en www.soltics.com.ve

    ResponderEliminar
  15. Estoy siguiendo tus consejos hace mucho y te agradezco que compartas tu conocimiento. Me he animado a preguntar por que tengo un problema existencial.



    logo


    menu




    Le puse un max-width a .contenedor de 960px y mi problema es que al momento de poner

    .contenedor div{
    display: inline-blocl;
    }

    para que se me alineen horizontalmente, los divs logo y menú no respetan el max-width y se salen de esos márgenes. Dejandolos en display: block respetan ese margen. ¿por qué sucede eso y qué puedo hacer para solucionarlo?

    PD: USO DIVS y SPANS por que no me permitió publicar con div*

    ResponderEliminar
    Respuestas
    1. u.u el post no se ve como esperaba pero en definitiva mi pregunta es la siguiente:

      Tengo un div* contenedor con otros 2 adentro. El contenedor tienes un ancho máximo de 960px pero al darle propiedad inline-block a los div de adentro se me escapan de los margenes. ¿Qué puedo hacer?

      Eliminar
    2. Hola Raul
      Blogger es algo puñetero y rácano en el uso de etiquetas html en los comentarios.
      Permite muy poquitas y el resto las marca como comentario con errores.

      Para código (en este blog) mete todo dentro de la etiqueta <em>&lt/em>
      Los signos de mayor que (<) hay que escribirlos con su entidad html correspondiente: & lt; (sin el espacio que separa el carácter & de la l).

      Sobre tu consulta: hay algo que impide que actúe el limitante de la anchura declarada al div .contenedor. O lo que es lo mismo, tienes alguna declaración css (directa o por herencia) que anula el comportamiento normal.
      Porque el comportamiento normal sería que en caso de no caber en la misma línea los divs contenidos en .contenedor pasasen a la linea inferior. No que aumente el width de .contenedor

      Algunos culpables podrían ser:
      .- que tu .contenedor no sea un elemento por naturaleza de bloque (i.e. un span)
      .- que siendo de bloque hayas cambiado su valor de display.
      .- que haya alguna declaración que afecte a la gestión de los espacios en blanco y generación de nuevas líneas (white-space,...)
      .- ...

      Si puedes colocar un enlace a tu realización, mejor. Si no la tienes en línea construye una demo en codepen o similares donde se vea ese comportamiento.

      Un saludo

      Eliminar
  16. Gracias por tu pronta respuesta. La verdad es que estoy comenzando en esto de html5 y debo confesar mi nivel noob. Gracias a tus post he progresado bastante no obstante descubrí mi error y se trataba de que estaba aplicándole los atributos a los div sin escribir la clase que los contenía. "#hader div*{" y tenía q declararlo como "#header .contenedor div*{" una noobada de proporciones. Muchas gracias nuevamente por responder :)

    ResponderEliminar
  17. Y que tal con esta:
    display: inline-block;
    margin-right: -4px;

    ResponderEliminar
    Respuestas
    1. Hola Carlos
      El problema de los valores negativos (para márgenes o separación de letras) es que son "valores mágicos". Esto es, el espacio de separación es función del diseño de cada familia tipográfica y del tamaño de la misma (font-size).
      Así que un valor concreto sólo será válido para una circunstancia muy concreta.

      Gracias por el apunte.
      Un saludo.

      Eliminar
  18. Blognya bagus simple kerenn ~
    From Indonesia ^_^

    ResponderEliminar
  19. Hola, estoy buscando una funcion que sirve para que no se muestre el texto que se sale de su bloque, es decir, en las tiendas online suele haber una parte de Bienvenido, Manuel Perez Ejemplo, Salir, si resulta que en lugar de Manuel te llamas MariaPurisimaDeLaConcepción Perez Ejemplo, Salir ya el texto es mucho mas grande que su bloque y lo que hace es salir se fuera o partirlo y poner una parte abajo y otra arriba (cosa que tampoco quiero), ¿como sehacía para que el texto que sobra del bloque simplemente no lo escriba?.

    Un saludo.

    ResponderEliminar
    Respuestas
    1. No sé si el dueño del circo te estará preparando una respuesta, pero igual ya que pasé por el blog y te vi me adelanto.
      Buscá opciones sobre

      "css" overflow

      tiene 2 ó 3 valores que te pueden servir.

      Eliminar
    2. Está bien Furoya que de cuando en vez le quitéis algo de trabajo a vuestros mayores xD ;-)

      Quizás sólo complementar tu sugerencia con la propiedad que gestiona los espacios en blanco y creación de nuevas líneas:
      white-space

      Y puestos a complementar, indicarle a Crazy00_00 la conveniencia de llamar a las cosas por su nombre.
      Lo que él está buscando es una propiedad css que junto al valor que mejor se adapte a sus necesidades conforman la declaración que solucionará su problema.
      Las funciones css (que haberlas haylas) son otra cosa que no aplican en su caso.

      Creo que te podrán ser de ayuda estos artículos:
      Sintaxis de Css y Glosario de términos (1)
      Vocabulario y Glosario de términos Css (2)

      Un saludo

      Eliminar
    3. ¡Y no nos olvidemos de 'text-overflow' !.
      Hace poco me enteré sobre los puntos suspensivos al comienzo y no sólo al final del párrafo. Nunca los había visto y en algún momento los voy a probar.

      Es cierto lo de la "función", lo había visto, pero no dije nada porque después de leer a un hoygan indonesio uno se vuelve más tolerante con todo.

      Eliminar
  20. Muchas gracias maestro

    ResponderEliminar