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:

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:

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

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.

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

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.