Removing the whitespace from inline block elements

Warning This article was written over six months ago, and may contain outdated information.

There are two common methods of building a horizontal component, such as navigation: using floats; or setting the display property to inline-block. This latter approach makes child elements run in to the same horizontal line in the document flow but preserves their block behaviour, and is pretty effective because you don’t have to worry about clearing floats as you would in the alternative technique. It does, however, have a drawback.

Before I explain that drawback, let me set the scene with some very simple example markup of a list used for navigation:

<ul>
<li>Nav One</li>
<li>Nav Two</li>
<li>Nav Three</li>
<li>Nav Four</li>
</ul>

And some CSS to make it display horizontally:

li {
  display: inline-block;
  width: 25%;
}

As you can see in the following example, when this renders there’s a small amount of whitespace between each child item; this can cause a problem if you want to use percentage widths to fill the parent, as the whitespace forces the final element onto a new line.

  • Nav One
  • Nav Two
  • Nav Three
  • Nav Four

This is caused by the markup being broken over multiple lines; when items are displayed as inline-block any carriage returns or tabs in the markup are recognised as a whitespace character. That being the case, you can fix this problem by writing your markup with no space between the items:

<ul><li>Nav One</li><li>Nav Two</li><li>Nav Three</li><li>Nav Four</li></ul>

If you prefer a CSS approach the usual fix for this is to set a negative margin-right value on each child element, but I recently happened upon another approach: as each element is rendered as if it were a word in a sentence, it’s also possible to use a negative value on the word-spacing property of the parent:

ul { word-spacing: -0.26em; }

The value seems to be about 25% of the font size, except in Firefox where it seems to be 26%. Note that this is only relevant for font-size values of 16px or over; below that, the percentage should be increased. Anyway, the result is that the whitespace is removed:

  • Nav One
  • Nav Two
  • Nav Three
  • Nav Four

There is a drawback to this, in that the value of word-spacing is inherited by all of the child elements, so if they contain multiple-word values you’ll have to restore word-spacing to its default value:

li { word-spacing: 0; }
  • Nav One
  • Nav Two
  • Nav Three
  • Nav Four

The initial keyword would be even better here, but its use is somewhat limited as it’s not yet supported by Internet Explorer.

As this method potentially relies on using two properties, I’m not sure it’s any better than using a negative value on margin-right; really I just wanted to record this for future use, as I haven’t seen it documented elsewhere.

Update: I have to hold my hands up and admit that I didn’t properly test the first version of this article. The value of word-spacing is relative to font-size, so the value I originally used in my examples, 4px, is only relevant at the default font-size of 16px. The updated value I’ve used instead, 0.26em, works better in all of the browsers I’ve tested but you may need to double-check this yourself — there is certainly some unexpected behaviour in Safari.

The best approach might be an alternative suggested in the comments; set a font-size of 0 on the parent to remove the whitespace problem, then set the desired font size on the children; e.g.:

ul { font-size: 0; }
li { font-size: 1.6rem; }

14 comments on
“Removing the whitespace from inline block elements”

  1. RT @stopsatgreen: Blogged: Removing the whitespace from inline block elements http://t.co/t83DYyfeMb

  2. RT @stopsatgreen: Blogged: Removing the whitespace from inline block elements http://t.co/t83DYyfeMb

  3. Hey,

    Just tried word-spacing: 0 and it doesn’t work? http://jsfiddle.net/HRkvz/

  4. nice technique. is the spacing exactly 4px in every popular browser?

  5. lf you can live with that I would recommend you to omit the close li tag. That way any linebreak or whitespace after the content before the start li tag is part of content of the last li element, which won’t be rendered.

    Masataka Yakura [March 25th, 2013, 3:48 pm]

  6. Few things. First word-spacing: 0 means — set default wordspacing, which is about 0.25em. I recommend this article: http://webtypography.net/Rhythm_and_Proportion/Horizontal_Motion/2.1.1/

    Second, –4px or even –0.25em is not truly reliable. 4px is fixed and wrod-spacing is in default — relative to font size. –0.25em is better, but not perfect. Some borwsers have default value set to approximately 0.28em (IE as long as I remember). So you can have some problems with horizontally align elements break into second line because there is no enough room because of the word spacing. White-space: nowrap would effectively prevent these problems.

    I think the nice approach to word-spacing is setting font-size: 0 for parent element. End, for every child: font-size: 1rem :). Or — with fallback — font-size: 16px; font-size: 1rem;

    I remember, that inline-block elements in Chrome would ignore font-size: 0, and still apply 0.25em (of something) spaces between each other. But quick test shows that is not true anymore (or maybe I got something mixed up).

    Michał Czernow [March 25th, 2013, 8:48 pm]

  7. I think that measurement can be relative to font-size. Two other noteworthy methods:

    1) Place an opening comment tag after your closing life and the closing comment tag before your next opening line, to suck up the white space.

    2) Set the font-size of the containing element to 0, then reset the font-size on the child elements. This effectively nullifies the white space.

    Option #2 is my preferred method!

    // Anthony

    Anthony Hastings [March 25th, 2013, 10:28 pm]

  8. @Kyle, you missed out on ‘word-spacing: –4px‘ on your ‘ul‘ element.

    http://jsfiddle.net/HRkvz/1/

  9. RT @theystolemynick: Technique alternative pour contrer les (foutus) 4 pixels séparant des éléments en Inline-block http://t.co/KtToI6hPho

  10. Removing the whitespace from inline block elements http://t.co/P7F0v8ls4V #CSS

  11. Just a heads-up that your “examples” aren’t showing up in Opera, which makes the post pretty confusing :).

  12. Anthony, Michał, et al: Thanks, I have to admit this post wasn’t my finest hour; wrote it late and in a hurry then didn’t fact check it before I published. Have updated it to make a little more sense now.

    Onderhond: Opera 12, or new WebKit Opera?

  13. RT @gonzomir: Removing the whitespace from inline block elements http://t.co/pK10DSdkx8

  14. Heres my workaround: http://jsfiddle.net/HRkvz/7/