Remove Whitespace Between Inline-Block Elements

Written by David Walsh on August 27, 2013 · 41 Comments

I remember being a young developer during the Internet Explorer 6 days and desperately wanting IE to adopt display: inline-block.  The inline-block value is incredibly useful when wanting to control margin and padding on "inline" elements without the need to `block and float` them.  One problem that arrises when you use inline-block is that whitespace in HTML becomes visual space on screen.  Gross.  There are a few ways to remove that space;  some of them are just as gross, one is reasonably nicer.

Solution 0: No Space Between Elements

The only 100% solution to this issue is to not put whitespace between those elements in the HTML source code:

<ul><li>Item content</li><li>Item content</li><li>Item content</li></ul>

Of course this is a mess to maintain but it's practical, logical, and most importantly...reliable.

Solution 1:  font-size: 0 on Parent

The best white-space solution is to set a font-size of 0 on the parent to the inline block elements.  So if you had a <UL> with inline-block <LI>'s, you'd do this:

.inline-block-list { /* ul or ol with this class */
	font-size: 0;
}

.inline-block-list li {
	font-size: 14px; /* put the font-size back */
}

To counteract the parent font-size setting, you must set a font-size for the list items, but that's usually fairly simple.   The only time it wouldn't be simple is if you're in a wicked cascade of relative units you can't easily calculate.  In most cases, however, this will be exactly what you need. Update: unless you care to support Android WebKit.

Solution 2:  HTML Comments

This solution is a bit gangsta but also works.  Using HTML comments as spacers between the elements works just as placing no space between elements would:

<ul>
	<li>Item content</li><!--
 --><li>Item content</li><!--
 --><li>Item content</li>
</ul>

In a word...gross.  In two words...really gross.  In three words...well, you get it.  But it works!

Solution 3:  Negative Margin

Much like solution two, this is regrettable.  You can take advantage of inline-block's flexibility to use a negative margin to negate the space:

.inline-block-list li {
	margin-left: -4px;
}

This is the worst solution because you have to account for variable, sometimes unpredictable spacing.  Avoid at all costs.

Solution 4:  Dropping Closing Angle

Another HTML-based hack solution is to simply place the closing > next to the start of the next tag:

<ul>
	<li>Item content</li
 ><li>Item content</li
 ><li>Item content</li>
</ul>

Not as ugly as the HTML comment hack but I know I'd probably remove that whitespace and not think about why it was there originally.

None of these solutions are ideal but the only alternative is not spacing/indenting your HTML which is also a crap solution.  This isn't a "be careful what you wish for scenario" because inline-block is still incredibly useful, but it is important that developers know how to deal with the space that comes with using it.

Comments

  1. Pavel Linhart August 27, 2013

    Solution 4: Don’t close LI tags + put opening UL and first LI on the same line
    Solution 5: Use a templating engine that collapses the whitespaces/linebreaks for you (eg. Smarty has a modifier for that)

    The 5th one is IMHO the best if you can use it, which is not always :)

  2. The font-size:0 hack doesn’t work cross browser. It’s as unreliable as the negative margin hack. Many mobile browsers override the font-size value with a minimum one to improve readability.

    There is no reliable and cross browser pure CSS solution. The only hacks that work are the ones involving the HTML itself (comments, leaving LI open, removing white space manually or at build time).

  3. For me Solution 1 is only valid if you don’t size your fonts with ems – which I do.

    And solution 2 could be troublesome when used in an agency setting. If another co-developer didn’t know that there must be html comments between list-items, things could go tits up.

    Even though Solution 3 is your least favourite (and I agree the spacing is sometimes inconsistent – usually 3 or 4 pixels) – this is the solution that I found my using in my work. If I pass my code onto another developer, there’s very little that could go wrong.

  4. agree with Pavel Linhart.
    And i used:

    Solution 6:
    put everything in one line.

  5. Note that the font-size:0 approach doesn’t work on Android browser according to Matt Stow.

    Also worth a look, the YUI3 grids, where they chose for this mess:

    .yui3-g {
        letter-spacing: -0.31em; /* Webkit: collapse white-space between units */
        *letter-spacing: normal; /* reset IE < 8 */
        *word-spacing: -0.43em; /* IE < 8: collapse white-space between units */
        text-rendering: optimizespeed; /* Webkit: fixes text-rendering: optimizeLegibility */
    }
    
    /* Opera as of 12 on Windows needs word-spacing.
       The ".opera-only" selector is used to prevent actual prefocus styling
       and is not required in markup.
    */
    .opera-only :-o-prefocus,
    .yui3-g {
        word-spacing: -0.43em;
    }
    
    .yui3-u {
        display: inline-block;
        zoom: 1; *display: inline; /* IE < 8: fake inline-block */
        letter-spacing: normal;
        word-spacing: normal;
        vertical-align: top;
        text-rendering: auto;
    }
  6. Pavel Linhart August 28, 2013

    Once there was this in the spec draft:
    http://www.w3.org/TR/2007/WD-css3-text-20070306/#white-space-collapse

    …and it got moved to CSS4 text :)
    http://dev.w3.org/csswg/css-text-4/#white-space-collapsing

    Sadly it looks like it has still a long way to go before getting implemented (or even finalized).

  7. Solution 2 is the only one that could stand up. It may be ugly but it works. Problem is that if you just take out the spaces like solution 0 then someone may put them back in. Using comments may look gross but they can mean something. Just write something in the comments so people know not to read them like:

    <ul>
    <li>Item content</li><!-- INLINE WHITESPACE DO NOT REMOVE
    --><li>Item content</li><!-- INLINE WHITESPACE DO NOT REMOVE
    --><li>Item content</li>
    </ul>

  8. I can’t wait to start using inline-block more boldly. I still have that awkward feeling whenever i use it, like it’s not really a legit property lol.

    I think Geert De Deckere’s answer is most suitable.

    • Inline-block is a close-enough representation of the self-contained “replaced element” like images, objects, videos, form controls, etc. that I would not feel bad for using it, or feel that it was not legit. There only time I would call into question whether it is legitimate to use inline-block is if the element to which you apply it is not some self-contained structure.

      As to the topic of the article, I think using the margin with an em unit matching the parent font size is best. Perhaps a :before pseudo-element can be used to pull the item into line? Hmm.

  9. Wouldn’t flexbox help? (in case you could use it for your project of course)

  10. I’m seeing this working for default 16px = 1em font size without gaps at all standard text zoom levels (ctrl + and ctrl -):

          .ib-parent {
            display: block;
            background-color: white;
            color: black;
          }
          .ib-child {
            display: inline-block;
            background-color: green;
            color: white;
            margin-left: -.33em;
          }
          .not-ib {
            display: inline;
            background-color: red;
            color: black;
          }
    
  11. We switched to using Haml for exactly this.
    It has an elegant way of keeping a clear structure and remove whitespace with the > and < characters.
    Highly recommend it.

  12. I prefer this solution:

    Item content
    Item content
    Item content

  13. I prefer this solution:

    Item content
    Item content
    Item content

    (sorry don’t understand how to put coude in a comment…)

  14. Great post David!

    Personnaly I really hate #0, #2, #3, #4, mostly because I hate ugly code.
    We use #1 but we set the font-size to 1rem on child elements and work our way from there…

    Rem Unit support: http://caniuse.com/#search=rem

    Thanks.

  15. Thanks, i think #1 is best, too
    i used float, something like this:
    ul>li {
    float: left;
    display: block;
    }
    ul {
    height: 30px;
    }
    now i will use your solution

  16. This is what I usually do: http://cdpn.io/rjbBo

    In short margin-left/right: -0.25em and then some nice styles to compensate, if needed. I don’t usually work with “fancy” fonts so I don’t know if it’s always compatible.
    Give me feedbacks if you want!

    • I’ll rectify my comment: I use this technique usually yes, but just in my HTML demos! For most of the “production” code I still rely on a good use of floats and clearfixes (sadly).

  17. I saw on one project we maintain, html was in php string and then it was preg_replace’d, lol.

  18. Should solution 4 be this instead?

    Item contentItem contentItem content

  19. Damn formatting. pre tag not working :(

    I was saying that “–” before closing “>” is probably wrong.

  20. David, I’m surprised you didn’t mention a JavaScript solution:

    var n = document.getElementById(‘nodeWithWhiteSpace’).firstChild;
    while(n){
    console.log(‘N’, n.nodeType, n);
    next = n.nextSibling;
    if(n.nodeType === 3 && !n.nodeValue.trim()){
    console.log(‘remove’);
    n.parentNode.removeChild(n);
    }
    n = next;
    }

  21. I use a variant of #4 that looks somewhat more consistent:
    <ul
    ><li>…</li
    ><li>…</li
    ><li>…</li
    ></ul>
    At least every li looks the same!

  22. Thanks for the tip, font-size: 0 on Parent seems to be work just fine

  23. float: left or margin-(left|right): -4px

    • I’m sorry to say that, but you totally missed the point.

      inline-block has many advantages over float, and the negative 4px is too arbitrary bceuase it depends on the font used and how it’s rendered by the browser.

  24. Tobias Aberg September 16, 2013

    Yahoo recently updated their letter-spacing solution. Apparently it relied on the good old web safe fonts that is installed on every single computer world wide, except for some weird linux hipster distro in beta that only has the monospaced powerline fonts.

    Their solution:
    “The solution that we ended up shipping is two-fold — it takes advantage of CSS3 Flexbox in modern browsers that support the spec, and sets a specific font stack on pure-g and pure-g-r for older browsers that don’t.” – http://blog.purecss.io/post/60789414532/how-we-improved-grids-in-pure-0-3-0

    The comments in the CSS makes it a bit unclear though.
    “The following font stack makes Pure Grids work on all known environments.

    Use flexbox when possible to avoid `letter-spacing` side-effects.”
    Sounds promising until then they mention side-effects, no details.

    I like this solution, it’s pretty simple to understand. So if someone thinks this is a really bad idea to use, speak now or I will spam the interwebs with cat sites using this from top to bottom!

  25. How about ‘white-space: nowrap;’ on the container. Seems to work on FF, Chrome and Safari.

  26. Adrian Harris November 27, 2013

    You better to use block element for such purposes, here is the difference between them: http://basicuse.net/articles/pl/textile/html_css/how_to_display_inline_elements_as_block_elements_and_visa_versa

  27. Jason P. Cochrane December 9, 2013

    There’s actually a really clean way to remove whitespace that’s both easy and semantic. It’s called a custom font with zero-width spaces. You just change the font on the container to the linked font, the children back again, and voila. Here’s a download to the font I just cooked up in font-forge with the css @font-face declaration included. Suit to taste. (This link is to Google Drive; click File > Download to save to your computer)

    https://drive.google.com/file/d/0B8W6UmdG-DTVbThfWkI5M1NYRVE/edit?usp=sharing

  28. I remember a solution involving a rarely-used CSS property, something like white-space-collapse:collapse; but I might be tripping…

  29. I tried Jason P. Cochrane’s solution, seems to be working fine but it would be good to know if anyone has found any draw backs, apart from the need to download a small font.

  30. Rick Finster January 27, 2014

    After floating doesn’t serve the ability to avoid auto-wrapping the content (even with defined overflow-behaviour), I nearly got to use #1 with the font-size. But then I thought of a more attractive method, which isn’t mentioned here yet but works perfectly: using a table.

    Just a instead of the inline-block, wrapped by

    and setting margin / padding / border of the td to 0. When CSS doesn’t serve enough, I think it’s ok to go back to the root and use tables for layout.

    Comments or shifte linebreaks were no possibility for me, because I had no 100% controll of the markup which was rendered serverside in last instance.

  31. Rick Finster January 27, 2014

    Important note:
    Table-Element must be set as inline-block for this solution.

  32. Thanks a lot David!

  33. Here’s a nice example of how to use negative word-spacing to remove the inline-block spaces. It works back to IE6: http://cdpn.io/BfIun

Be Heard

Tip: Wrap your code in <pre> tags or link to a GitHub Gist!

Use Code Editor
Older
Pure CSS Slide Up and Slide Down
Newer
Using Font Awesome Icons without <i> Tags