Display: inline-block y sus espacios de separación. 8 soluciones más 1 universal 15.3.16
8 forma diferentes más 1 universal, usando css o vía html, de eliminar la separación que aparece entre items con display: inline-block y la explicación del porqué sucede.
Display: inline-block y sus espacios de separación. 8 soluciones más 1 universal
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:
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>
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;
}
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;}
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.
Kseso
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
Curiosas e ingeniosas soluciones. Gracias!
ResponderEliminarMe he divertido con esto, muchas gracias!
ResponderEliminarHola 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
ResponderEliminarvertical-align: top;
Eliminarufff, me salvaste el dia jaj, tenia unproblema parecido :D
EliminarHola CristiandR
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 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
Este comentario ha sido eliminado por un administrador del blog.
ResponderEliminarEste comentario ha sido eliminado por un administrador del blog.
ResponderEliminarCapoooo GRACIAS con mayusculas.
ResponderEliminarbuenos hacks a tener en cuenta
ResponderEliminarmuy buen artículo, gracias por las pistas.
ResponderEliminarPues estaba viendo y probando y también puedes arreglando usando display: table-cell y border:collapse
ResponderEliminarCada valor conlleva unas características que le son propias y en el momento que cambias el valor de display... ya es otro tema.
ResponderEliminarGracias por la aportación, Alejandro
De gran ayuda =) quisiera saber si la forma quitando el final de la etiqueta li ,trae problemas adelante.Graciassss
ResponderEliminarMuchas 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
ResponderEliminarHola Jonatan
EliminarDe 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
excelente la solucion del margin negativo, louso enmis plantillas lopueden ver en www.soltics.com.ve
ResponderEliminarEstoy siguiendo tus consejos hace mucho y te agradezco que compartas tu conocimiento. Me he animado a preguntar por que tengo un problema existencial.
ResponderEliminarlogo
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*
u.u el post no se ve como esperaba pero en definitiva mi pregunta es la siguiente:
EliminarTengo 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?
Hola Raul
EliminarBlogger 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></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
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 :)
ResponderEliminarmuuuy util!!
ResponderEliminarPerfecto, gracias!
ResponderEliminarY que tal con esta:
ResponderEliminardisplay: inline-block;
margin-right: -4px;
Hola Carlos
EliminarEl 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.
Blognya bagus simple kerenn ~
ResponderEliminarFrom Indonesia ^_^
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?.
ResponderEliminarUn saludo.
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.
EliminarBuscá opciones sobre
"css" overflow
tiene 2 ó 3 valores que te pueden servir.
Está bien Furoya que de cuando en vez le quitéis algo de trabajo a vuestros mayores xD ;-)
EliminarQuizá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
¡Y no nos olvidemos de 'text-overflow' !.
EliminarHace 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.
Muchas gracias maestro
ResponderEliminarBuenas, parece ser que el problema estriba en que el navegador interpreta el salto de linea hecho entre las etiquetas como un espacio. Así pues, otra posible solución pasa por codificar el salto de linea en el contenido y no entre etiquetas.
ResponderEliminarSaludos!
Pero ¿cómo se codifican un salto de línea y un retorno de carro para que se vean en el editor de texto y no se interpreten en el HTML?.
EliminarMe deja alguna duda lo de "no entre etiquetas".
Gracias por el apunte, Mounsif Takkal
EliminarSi te fijas bien, tu "codificación del salto de línea en el contenido" no afectaría a la separación horizontal entre elementos. Dependiendo del valor de white-space afectaría a la altura del elemento.
Y al ser el espacio de separación resultante del letter-spacing las soluciones que lo impiden vía Html deben afectar a los elementos inline-block, no a su contenido.
Un saludo y gracias.
Sí, disculpen. No soy muy bueno explicandome. Quiero decir lo siguiente:
Eliminar[code]
<div id="main">
<div id="vermell"><div>d<iv id="blau">
<div><div id="verd"></div>
</div>
[/code]
Creo, Mounsif, que has sido víctima de blogger y sus limitaciones en el uso de ciertos carácteres, como el < ;-)
Eliminar¿Qué tal si creas un pen en codepen.io (aunque no estés registrado lo puedes hacer de forma anónima) y compartes aquí el enlace a la demo? Creo que será más fácil para todos.
Un saludo
Ah, ya. Creo que entendí. Es como el método que está en "Descompón la forma de escribir el html".
EliminarCuando leí sobre 'codificación' aluciné cosas sobre UTF-16, ASCII + &#htmlchar; ,EBCDIC500:international, o alguna que salvara el problema y yo no lo sabía.
Tampoco estaría tan errado, al final quitando el BOM (Byte Order Marker) se resuelven muchos errores.
;-)
EliminarHahaha, si, así es!
Provemos con codepen:
[pen]data-height="268" data-theme-id="0" data-slug-hash="qEyRjB" data-default-tab="result" data-user="mounsiftakkal" class='codepen'[/pen]
Gracias Mounsif
EliminarSí. Creo que Furoya supo comprender lo que planteabas mejor que yo.
La diferencia es que en el ejemplo del post yo dejo la apertura del elemento en la línea anterior y tú pasas el cierre a la siguiente. Ambos "descomponemos" o alteramos la "típica" forma de escribir los elementos en el html.
Un saludo y gracias.
Gracias a vosotros por este blog, es de enorme utilidad para el aprendizaje.
EliminarSaludos!
word-spacing: -1em;
ResponderEliminaren el contenedor padre
Mmmm...
EliminarNo es mala idea. Yo nunca lo probé.
Aunque puede haber alguna diferencia, porque word-spacing colapsaría según el ancho, y 'em' en realidad mide por el alto.
En cualquier caso, habrá que resetearlo en los hijos, porque es heredable.
Word-spacing no deja de ser una "variante" de letter-sapcing, Joefay. Creo.
EliminarY el valor final computado que se necesite para evitar el espacio y no encimar unas cajas con otras creo que ha de ser un número mágico, diferente en cada situación.
Un saludo y gracias por participar ;-)
Hola, fui conocedor de este problema del articulo desde hace algunos años. Y he usado algunas de las soluciones aquí descritas. Pero hasta hace unos días no me había planteado cual era el problema de Display: inline-block e inline y sus espacios de separación entre ellos y empecé investigar y saqué mis propias conclusiones, sacando información de aquí y allá. Al leer tu articulo me doy cuenta que poco tiene que ver con el análisis que has hecho del “porqué y de dónde provienen los espacios”. Sé que tu análisis es más acertado que el mío y llega más allá al concluir que es una particularidad que genera Css. Así y todo es un tema un poco difícil de coger y me gustaria preguntarte una cosa.
ResponderEliminarMi humilde conclusión sobre el porqué y de dónde provienen los espacios.
¿De dónde sale ese espacio entre las imágenes?
¿cómo podemos eliminarlo?
El culpable es el "espacio en blanco" en el código html
HTML considera espacio en blanco a los espacios en blanco, los tabuladores, los retornos de carro y el carácter de nueva línea (ENTER o Intro).
Tantos uno como los otros crean por sí solos nodos de texto (son del tipo object text) vacíos en el árbol DOM. De ahí viene ese espacio en blanco que separa las imágenes y que su tamaño depende del tipo y tamaño de letra que estemos utilizando y como dijimos no es otra cosa sino los nodos de texto creados, que aunque estén vacíos ocupan su lugar en el documento y en el caso concreto del título del artículo, tienen un tamaño, que se ve afectado por la propiedad css font-size como veremos más adelante.
Aquí te expongo mi duda.
Por ejemplo cuando comentas esto:
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.
Cuando dices ambas dependiente del tamaño de la tipografía font-size del padre y das la solución, reducir el font-size del padre a cero (0) y compensarlo en los hijos, es porque al reducir el font-size en el padre, letter-spacing y word-spacing se mantiene en 0 desapareciendo ese espacio. No lo afirmo es una pregunta.
Si puedes ampliar un poco la información del asunto.
Hola Isaac
Eliminar"¿Cuando dices ambas dependiente del tamaño de la tipografía font-size del padre y das la solución, reducir el font-size del padre a cero (0) y compensarlo en los hijos, es porque al reducir el font-size en el padre, letter-spacing y word-spacing se mantiene en 0 desapareciendo ese espacio?"
El espacio de separación computado entre letras y palabras además de variar de tipografía a tipografía por una cuestión de diseño de cada una también lo hace (y basado en esa separación por diseño) en función del font-size.
El valor computado de letter-spacing y word-spacing también afecta a los "espacios en blanco" tipográficos" (ya sean eso, espacios, tabulaciones o retornos de carro).
Al ir reduciéndolo los elementos a los que afectan (ya sean cajas "inline" o "inline-block" anónimas o no) se van a dibujar (paint) más próximas entre sí, llegando un momento que algunos de ellos se muestran encimados (como los caracteres tipográficos) o sin espacio de separación entre ellos.
Un saludo
Hola, lo que está claro entonces son algunos detalles.
ResponderEliminarComo por ejemplo que word-spacing es el que controla los espacios en blanco es decir cuando ponemos en el código un espacio tipográfico es la propiedad word-spacing el que le da la medida con el valor inicial normal, que indica que el navegador se encarga de determinar la separación óptima entre cada palabra del texto. Además y esto me desconcertó mucho no sabía que si se indica una medida, se considera que es el espaciado adicional que se añade a la separación normal de cada palabra. Así cuando miraba en el navegador el valor computado era 0px y estas palabras seguían apareciendo separadas.
Ya después lo que tu comentas de tipografiaría a tipografiaría puede haber distinta separación y todo en función del Font-sise del padre, que cuando mayor es más separación entre las palabras y cuanto menor menos separación, hasta reducirlo a ninguna separación entre palabras
Cuando comentas esto en el artículo:
ResponderEliminarEste 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.
Me ha desconcertado también, porque si te fijas y pones dentro de body solo dos palabras separadas pasa exactamente lo mismo, se ven afectadas aunque no tengas un boder para poder verlo más claro es decir, hay una separación entre ellas también que dependes de letter-spacing y word-spacing, ambas dependiente del tamaño de la tipografía font-size del padre. Y lo de los elementos en línea no hace falta que lo diga se sabe de sobras que les afecta todo esto como a los inline-block.