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; }
RT @stopsatgreen: Blogged: Removing the whitespace from inline block elements http://t.co/t83DYyfeMb
pixelpanda [March 25th, 2013, 14:02]
RT @stopsatgreen: Blogged: Removing the whitespace from inline block elements http://t.co/t83DYyfeMb
eyelearn_tips [March 25th, 2013, 14:06]
Hey,
Just tried word-spacing: 0 and it doesn’t work? http://jsfiddle.net/HRkvz/
Kyle [March 25th, 2013, 14:10]
nice technique. is the spacing exactly 4px in every popular browser?
Anton [March 25th, 2013, 15:23]
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, 15:48]
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, 20:48]
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, 22:28]
@Kyle, you missed out on `word-spacing: -4px` on your `ul` element.
http://jsfiddle.net/HRkvz/1/
Chen Zihui [March 26th, 2013, 02:28]
RT @theystolemynick: Technique alternative pour contrer les (foutus) 4 pixels séparant des éléments en Inline-block http://t.co/KtToI6hPho
fab_i_1 [March 26th, 2013, 09:05]
Removing the whitespace from inline block elements http://t.co/P7F0v8ls4V #CSS
victorbritopro [March 26th, 2013, 10:08]
Just a heads-up that your “examples” aren’t showing up in Opera, which makes the post pretty confusing :).
onderhond [March 27th, 2013, 12:17]
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?
Peter [March 27th, 2013, 14:28]
RT @gonzomir: Removing the whitespace from inline block elements http://t.co/pK10DSdkx8
petyosi [March 28th, 2013, 22:09]
Heres my workaround: http://jsfiddle.net/HRkvz/7/
Ruben [April 17th, 2013, 12:04]