84

I have the following HTML:

    <ul>
        <li>
        <div>first</div>
        </li>
        <li>
        <div>first</div>
        </li>
        <li>
        <div>first</div>
        </li>
        <li>
        <div>first</div>
        </li>
    </ul>

and the following css rules:

        ul {
            padding: 0;
            border: solid 1px #000;
        }
        li {
            display:inline-block;
            padding: 10px;
            width: 114px;
            border: solid 1px #f00;
            margin: 0;
        }

        li div {
            background-color: #000;
            width: 114px;
            height: 114px;
            color: #fff;
            font-size: 18px;
        }

For some strange reason, the list items appear with a margin around them in both Firefox and Chrome. Looking at firebug, the list items do not have any margin at all, but there seems to be a void space between them.

If I later on add more list items via javascript using

$('<li><div>added via js</div></li>').appendTo($('ul'));

the "margin" doesn't appear around the new elements:

Unwanted margins

Any idea of what the hell's happening here?

kapa
  • 77,694
  • 21
  • 158
  • 175
Diego
  • 5,024
  • 6
  • 38
  • 47
  • 1
    Why not use `margin-right: -4px;` Is there a reason why that shouldn't work? –  May 30 '11 at 18:05
  • 1
    Negative right margin depends on font-size and font used. – yakunins Dec 19 '12 at 21:53
  • 2
    Seems like a lot of similar question get closed as the duplicate of this one, so a useful Chris Coyier link for future visitors: http://css-tricks.com/fighting-the-space-between-inline-block-elements/ – kapa Jan 28 '13 at 19:16

10 Answers10

119

This is caused by the display: inline-block;

li {
    display: inline-block;
    padding: 10px;
    width: 114px;
    border: solid 1px #f00;
    margin: 0;
}

Change it to float: left;.

I thought it was the padding but took a closer look and turns out it was the display :)

Example here.


After further research I have discovered that inline-block is a whitespace dependent method and renders a 4px margin to the right of each element.

To avoid this you could run all your lis together in one line, or block the end tags and begin tags together like this:

<ul>
        <li>
            <div>first</div>
        </li><li>
            <div>first</div>
        </li><li>
            <div>first</div>
        </li><li>
            <div>first</div>
        </li>
</ul>

Example here.

starball
  • 20,030
  • 7
  • 43
  • 238
Kyle
  • 65,599
  • 28
  • 144
  • 152
  • 3
    So it's a bug pertaining inline-block then, or is that the intended behaviour? In my opinion it doesn't make sense at all... – Diego Feb 11 '11 at 12:55
  • I think you're right. I honestly don't know why it would be adding new margins, then not on the new ones. It makes no sense. This is a fix but I'm still trying to figure out the reasons behind the "bug." – Kyle Feb 11 '11 at 13:03
  • Found out the bug and made a fix for you :) – Kyle Feb 11 '11 at 13:10
  • 11
    It's intended behaviour. `inline-block` was meant to emulate the behaviour of the `img` tag. Whitespace around an `inline-block` element will be rendered. – Kiran Jonnalagadda May 11 '11 at 13:20
  • float: left fixed it for me, thanks – bbedward Apr 26 '12 at 17:13
  • This is much better http://jsfiddle.net/t7dut/647/. Maybe rendering engines have changed since. – user1934286 Feb 21 '13 at 09:31
  • Ohh, man I wish I could give 50 upvotes for this. It gave answer to most of the questions. I always wondered why Twitter Bootstrap uses combination of `display:table` and `float:left` for column layout. This is the answer for that too. – Nihar Sawant Mar 30 '13 at 20:57
  • 4
    The article mentions that it is a margin but what is happening is the inline element is rendering the word-space and line-height of the element by default. Setting word-spacing: 0, and line-height: 0 on the parent container actually fixes this if you dont want to use float: left. – chadpeppers May 21 '13 at 20:12
  • Is possible to do this with dynamic content? –  Nov 20 '13 at 12:29
  • this helped me understand my similar problem, but my answer that worked best for me was `li { display:table-cell; }` – aequalsb Sep 09 '16 at 18:29
68

I found a very good trick to overcoming this very same issue. My list items in my top menu had whitespace margins between each after i dropped "float:left;" in favor of "display:inline-block;".

Try setting your font-size for the unordered list to "0", ie:

ul { font-size:0; }
li { font-size:18px; }

Worked for me.

Nikola K.
  • 7,093
  • 13
  • 31
  • 39
Ryan
  • 689
  • 5
  • 2
9

Seeing this post and the answers given, I thought I would explain what's going on here. This is not a bug, but is actually the intended behavior of inline-block.

The best way to illustrate why this is the correct behavior is with smileys in a paragraph:

<p>
  Hi, really glad to hear from you yesterday 
  <img src="annoying_smiley.gif"/><img src="annoying_smiley.gif"/>.
</p>

Images are, by default, displayed as inline-block (IE: a block element which obeys the inline flow - much like a single character of text). In this case you would want the two smileys to butt up next to each other, but you would still want a space between 'yesterday' and the first smiley.

Hope this explains it, and also explains why inline-block has taken so long to be fully supported; There aren't actually many use-cases for using it as intended.

To answer your question, your best bet would be to do this:

ul {
  height: some set height
       /* OR */
  overflow-y: auto;
}

ul li {
  float: left;
}
Nikola K.
  • 7,093
  • 13
  • 31
  • 39
Will Tomlins
  • 1,436
  • 16
  • 12
7

In my opinion and in this case the best thing to do is to remove the letter spacing of the li's parent and re-put it on the li!

So your CSS rule:

ul{
    padding: 0;
    border: solid 1px #000;
    letter-spacing  :-4px; /*Remove the letter spacing*/
}
li{
    display:inline-block;
    padding: 10px;
    width: 114px;
    border: solid 1px #f00;
    margin: 0;
    letter-spacing  :0px; /*Put back the letter spacing*/ 

}
Sir Crispalot
  • 4,792
  • 1
  • 39
  • 64
DontShootMe
  • 71
  • 1
  • 1
5

Remove all </li> tags.

<ul>
    <li>
        <div>first</div>
    <li>
        <div>first</div>
    <li>
        <div>first</div>
    <li>
        <div>first</div>
</ul>
mx0
  • 6,445
  • 12
  • 49
  • 54
  • ? you mean avoiding ul at all or just taking out the closing tags?? why you should break the markup? – Damien Pirsy Feb 11 '11 at 12:51
  • 5
    @Damien Pirsy: `` tag is optional, it's safe to omit it. Here's more info: http://stackoverflow.com/questions/3008593/html-include-or-exclude-optional-closing-tags – mx0 Feb 11 '11 at 13:29
  • That "fixes" the problem because it removes the unwanted whitespace between the end of first `
  • ` element and start of the second `
  • ` element. The same result can be achieved by *not* using any indention in the source code, which I consider much better style.
  • – Mikko Rantalainen Jul 02 '13 at 07:33