Closing the gap between list items in IE

A long-standing bug in Internet Explorer is the gaps it likes to insert between list items that contain block level elements, if there is any whitespace between the list items in the markup. You have probably seen it in action more times than you want to.

This bug was thought to have been fixed in IE 7 RC 1, and perhaps it was. That doesn’t really matter since the release version of IE 7 still suffers from it in certain circumstances. Just in case you’re looking for something that will fix this problem in both IE 6 and IE 7, I wanted to share this piece of knowledge. I originally thought this would soon be obsolete, but unfortunately that does not seem to be the case.

Let’s say you have a nice list of links marked up like this:

  1. <ul>
  2. <li>
  3. <a href="/">List item 1</a>
  4. </li>
  5. <li>
  6. <a href="/">List item 2</a>
  7. </li>
  8. <li>
  9. <a href="/">List item 3</a>
  10. </li>
  11. </ul>

You want the links to display below each other, so you use the following CSS:

  1. ul {
  2. margin:0;
  3. padding:0;
  4. list-style:none;
  5. }
  6. li {
  7. margin:0;
  8. padding:0;
  9. }
  10. li a {
  11. display:block;
  12. padding:0.5em;
  13. background:#ddd;
  14. }

The result will be a vertical list of links with large gaps between them in Internet Explorer up to and including IE 7 beta 3, and smaller gaps in the release version of IE 7. There should not be any gaps.

One suggested fix is assigning a width to the links. I don’t like doing that since I prefer controlling their width with their containing element. Setting their width to 100% doesn’t work either since in most cases a bit of padding will make the links easier to hit.

I’ve found that the following trick will make both IE 6 and 7 behave (wrapped in conditional comments here - move to your IE bugfix stylesheet before use):

  1. <!--[if lt IE 8]>
  2. <style type="text/css">
  3. li a {display:inline-block;}
  4. li a {display:block;}
  5. </style>
  6. <![endif]-->

Note that the declarations need to be in separate rules.

That’s it. No more gaps in IE 6 or IE 7.

Update (2006-10-20): I just noticed that there are cases where the bug will appear in the release version of IE 7. I’ll update this article with the details ASAP, hopefully later today.

Posted on October 16, 2006 in Browsers, CSS

Comments

  1. Do you create a specific stylesheet for IE? and then how do you attach that to the site?

    Is there a way to add this style to one of your existing stylesheets in a way that only IE will rread it?

    Sorry, I am just learning. Thanks so much.

  2. Freaky. But cool, much appreciated.

    I think the bug can also be fixed by setting the list-item to display: inline; too, although there might well be reasons not to do that.

    I have a feeling that setting something or other (The list-item? The list?) to height: 1%; fixes it too.

  3. October 16, 2006 by thepineapplehead

    @ Luis - Google for “conditional comments”. Use them to feed IE a different stylesheet.

    @ paul - 1% height is usually a haslayout fix. I don’t know if the mystical line-height bug is to do with hasLayout :?

    @ Rojer - thanks. Nice and simple :D

  4. @Luis: my current method is to have IE-specific stylesheets for every site, called in with conditional comments.

    Amongst the modern, widely-used browsers, IE (up to version 6, at least) stands alone as having more, and more severe, CSS rendering bugs, making IE-specific stylesheets necessary on every site if I want to code without going insane.

    So, perhaps something like this in your HTML:

    <link rel="stylesheet" type="text/css" href="stylesheet.css" media="screen, print" title="Default" />
    
    <!--[if lte IE 6]><link rel="stylesheet" type="text/css" href="stylesheet-lteIE6.css" media="screen, print" title="Default" /><![endif]-->
    
    <!--[if lte IE 5.5]><link rel="stylesheet" type="text/css" href="stylesheet-lteIE5.5.css" media="screen, print" title="Default" /><![endif]-->
    
  5. @thepineapplehead: Yeah, I might have been imagining that.

    I’m looking forward to reclaiming the bits of my brain currently dedicated to trying to remember IE’s CSS bugs :)

  6. October 16, 2006 by Matt King

    @pauldwaite - actually, height can be any value and it seems to fix the problem (at least in my experience).

  7. @Luis: sorry, I managed to cut some of my example code off. Here you go:

  8. @Luis: sorry, I managed to cut some of my example code off. Here you go:

    <link rel=”stylesheet” type=”text/css” href=”stylesheet.css” media=”screen, print” title=”Default” />

    <!—[if lte IE 6]><link rel=”stylesheet” type=”text/css” href=”stylesheet-lteIE6.css” media=”screen, print” title=”Default” /><![endif]—>

    <!—[if lte IE 5.5]><link rel=”stylesheet” type=”text/css” href=”stylesheet-lteIE5.5.css” media=”screen, print” title=”Default” /><![endif]—>

  9. October 16, 2006 by Roger Johansson (Author comment)

    Luis: Yes, I like to put my IE fixes in a stylesheet that only IE sees. I use Conditional Comments to make sure of that.

    pauldwaite: “height:whatever” fixes the problem in IE 6, but not in IE 7 (the betas).

  10. Nobody except web developers and IT professionals will have used the betas; and they’ll all have moved on to testing in RC1 by now. And they’ll move on from that to the full 7.0 release coming soon.

    The IE7 betas are like “dead browsers” which can be ignored, imho.

  11. October 16, 2006 by Roger Johansson (Author comment)

    Ben: I did say this would be obsolete soon :-).

    However, I have found that this method can be used to fix several other bugs in IE 7, so “display:inline-block” will still come in handy.

  12. Funky. I remember seeing this solution some time back, but didn’t remember it. Thanks for the info so we can get things to shape up in IE 6!

  13. If you’re afraid of hacks, adding a visible horizontal border to the li element will also remove the gap

    li { margin:0; padding:0; border-bottom: 1px solid #ddd; }

  14. October 16, 2006 by Bryan Sullivan

    The following will also work in both IE 6 and Firefox 1.5 without the need for conditional IE code. Try it out with the example above.

    
    ul, li {
        margin: 0;
        padding: 0;
        list-style: none;
        display: inline;
    }
    li a {
        display: block;
        padding: 0.5em;
        background: #ddd;
    }
    
  15. Roger, I’m pretty sure another way to fix this bug is to simply add the width property: 100%, #px, #em. As far as I know any of those will correct this issue.

    Mike

  16. Bryan: ick, a block-level element inside an inline one..

    I guess I am a purist after all.

  17. October 17, 2006 by Roger Johansson (Author comment)

    Jadwigo, Bryan: Thanks, having more options is always a good thing.

    Mike: Yes, that will fix the problem in IE 6. However, that causes problems when you add horizontal padding.

  18. Haven’t seen this before, not surprising since I’m not doing so much front-end work anymore. This does fix it but it’s a bit nasty. Adding conditional comments is problematic for maintenance and should be avoided. But certainly worth looking in to.

  19. The zoom:1.0 has replaced the height:1% in most of my ie-stylesheets. this adds the hasLayout property without breaking IE7. It works fine on this list-problem too.

  20. I know it’s not perfect (as per the previous comments), but it’s designed to get round a browser that is similarly imperfect. In this case I’d say two imperfections make an absolutely perfect solution. Good work.

  21. Sweet, thanks Roger.

    On a recent project I fixed this by hacking the html so there were no line-breaks between the <li>s:

    <li><a href="#">Link 1</a></li><li>
    <a href="#">Content</a></li><li>
    <a href="#" id="build">XHTML</a></li>
    

    Not pretty, but an option I suppose.

  22. (sorry, I thought that would output the code. It displays as I intended if you view the source code :)

  23. Excellent!!!!! I was just looking for a way to fix this last week!!!

  24. October 17, 2006 by Johan

    if you add a float property to the li: this works as well to get rid of the white space.

    Or do:

    <ul
    ><li>List item</li
    ><li>List item</li
    ><li>List item</li
    ><li>List item</li
    ></ul>
    
  25. The horizontal padding issue you mentioned is a good point, Roger. When I upgraded from IE6 to IE7 beta 2 (I have RC1 now), the nav menus on a few of my sites, like my blog, were messed up (they were fine with IE6, but not 7b2); they exhibited that whitespace bug. I fixed them by adding width to the anchor. To account for the padding I just decreased the width inside the container. I did this on my blog, as I mentioned, so when I read your comment reply I zipped on over there to check it out to see what the circumstances were and why it worked for me. The container is #sidebar and I set its width to 200px; The ul has no width defined. Neither does the li. I applied the width to my anchor — it looks like I decreased that by 15px to account for the 15px of total left/right padding, like so:

      li a {
        padding : 15px 5px 2px 10px;
        margin : 0;
        width : 185px;
        height : auto;
      }
    

    That worked for me, but now that you’ve said that I realize why it worked. I had no hard borders to conform to. Due to the lack of tight tolerances it didn’t produce ill-effects. Thanks for the insight.

    Mike

  26. October 17, 2006 by Johan

    It could be that IE requires the hasLayout property.

    Why cant we do anything like this:

    zoom always triggers hasLayout, but it’s not supported in IE5.0. (ingo chao)

    li {zoom:1}
    

    but since the gap is only viewable in horizontal lists between the list items

    I believe this does the trick

    li { float: left;}
    

    maybe you need to add display: inline as well?

    li { float: left; display:inline }
    
  27. October 17, 2006 by Johan

    Sorry for the mutiple posts but I think Roger’s solution works due to the hasLayout property in IE is set to true.

    InlineBlockLayout explanation

  28. Hi Roger, thanks for the info and fix, I needed it for a project I was working on!

    Strange though, that another site I’ve created using the EXACT method I was using BEFORE your fix works in IE6 and 7.

    Hmmm, strange.

  29. Hi Guys, that is a known issue simply solvable by adding a height and line-height to the anchor block element, That’s all! Try it.

  30. Thanks Roger, up to now I’ve been taking out all the whitespace to get round this bug but it makes the code a real pain to work with. Great tip.

  31. October 18, 2006 by Roger Johansson (Author comment)

    Egor: Conditional comments make maintenance easier in my experience.

    martin: I’ve never tried zoom, but now that you’ve mentioned it I’ll check it out. Thanks.

    Timbo: I fixed your comment :-).

    Johan: Yep, that will do it as well. But you don’t always want to float the list items, and getting rid of whitespace in the markup can be tricky when dealing with a CMS.

    Guiseppe: That will not work in the IE 7 betas.

  32. I wrote about this a year and a half or so ago. See White Space Bug Revisited. At its root, the buggy behavior is another manifestation of IE’s hasLayout—or in this case the lack of layout.

    A suggestion above gave the <li> layout, which will work if there are no markers and only single line items. The ultimate fix is to give <a> layout in any manner you see fit. It is making <a> a block element that triggers the bug, and giving it layout fixes it.

    cheers,

    gary

  33. Ack! Apparently one should not preview when entities such as < are used, as they get rendered in the textarea.

    To reiterate a portion above:

    Giving layout to the <li> element works only partially. There are issues with the list marker and with multi-line list items. Ordered lists have special issues.

    The bug is triggered by making <a> {display: block;}, and setting hasLayout for the <a> will fix it.

    cheers again,

    gary

  34. October 18, 2006 by Johan

    and getting rid of whitespace in the markup can be tricky when dealing with a CMS

    Good catch!

  35. “height:whatever” fixes the problem in IE 6, but not in IE 7 (the betas)

    Unbelievable. I don’t think I’ll worry about the betas, but unlucky that this happened.

  36. Tried today my sites with ie7, gosh, no problems, but i had big bugs in ie6.

  37. I like the way you optimistically assume IE8 will fix this problem. ;-)

  38. October 21, 2006 by Roger Johansson (Author comment)

    Mark: Yeah, maybe hoping that it will be fixed in IE 8 is a bit too optimistic ;-).

  39. It’s funny to read this post today, because just yesterday I discovered a method that seems to deal with the same problem at Vivabit: they insert a HTML comment starting at the end of one line and ending right before the first character of the next line, thus commenting out any line breaks and white space. Good to know a few different approaches, I’ve done it with the method Johan described so far.

  40. I think Timbo was right pointing out that this is caused by line-breaks/spaces in the source HTML. The problem is also not specifically related to lists and this fix will not catch all occurances.

  41. October 23, 2006 by Roger Johansson (Author comment)

    Martin: Yes, this is related to whitespace in the HTML. I mention that in the very first sentence actually ;-). The fix described here is specific to the li + a situation since that is the most common case when the bug occurs.

  42. Oops. Yes you did, didn’t you ;) I guess seeing the css hack made me think you missed the real cause of the unwanted behavior.

  43. October 27, 2006 by Sean The Prawn

    Alternatively, simply add a space before the </a> tag!

    <li>
    <a href="#">Link </a>
    </li>
    

    simple is as simple does…. ;)

  44. October 27, 2006 by Roger Johansson (Author comment)

    Sean: Wow, that actually works. Never heard of that trick before! It does require that you can actually edit the HTML though, which can be difficult when you are dealing with a CMS.

  45. @Luis, @pauldwaite: Concerning the use of IE-conditional comments. You may possibly find you need the converse, an if-not-IE conditional to feed CSS to more standards-compliant browsers. I use a technique inspired by Roger’s article on this subject, but with an added filter to keep IE/Mac separate. You can see this in action at tosg.org if you’re interested, although you will have to dig a little.

  46. I just got so utterly sick of the huge scary raft of different HTML whitespace-related layout bugs that I decided on a radical and vicious cure. I put together a little quick-and-dirty tool which rips out all the newlines from the HTML. (Windows users: I whipped it up using javascript+WSCRIPT, and it runs under the CSCRIPT scripting host.) I run it as part of the build process as a matter of course, and I can turn this tool on or off if I want to be able to read the output easily.

    If anyone wants the tool, which is only a few dozen lines of code, then just ask.

  47. December 5, 2006 by Sally Revell

    Thanks very much for documenting this problem and its solution - after spending a long time yesterday trying to resolve the 3 pixel gap issue in IE, it was a relief to come across a fix for list item gaps that worked first time! I’ll be sure to make this site a first port of call for css bugs in future!

  48. December 8, 2006 by Jesse Morrow

    Another solution for IE7:

    The solutions given above did not work for my complex situation. I am using UL/LI in a nested structure to render a collapsable/expandable directory tree structure. Here is a simplified example:

    <ul>
        <li><span>Folder</span>
            <ul>
                <li><span>Sub Folder</span>
                    <ul>...</ul>
                </li>
            </ul>
        </li>
        <li>...</li>
    </ul>
    

    The rendering bug in this case is a bit worse than just gaps between items - the gaps actually shift dynamically as you pass the mouse over them, even without any :hover CSS!

    Here is the CSS that fixed this for me on IE7 (haven’t tested others):

    ul li {display: inline-block !important;}
    

    Thanks for the posts above, hope my post helps someone too!

  49. @ Jesse: That works for me on IE 5.5, 6 and 7, but doesn’t cure the problem on 5.01. Thanks for the info!

  50. Hi there, I’ve been surfing about trying to find a finx for the following problem and I think you guys seem to be talking about a similar issue. Sorry, if it’s not relevent but I’m beginning to run out of ideas on this one. If you browse to my site www.theroundup.co.uk in Mozilla and click on the store option in the menu bar, you should see an intigrated Amazon aShop. Now, if you do the same thing in IE7 then the store doens’t appear. I’ve checked and double checked the settings, moved content in the php and made some changes to the CSS but non of it seems to be making a difference. For some reason, I just can’t get the iFrame to show in IE7. Seems to work in just about everything else. Would anyone be able to try and give me a hand with this? Thanks, Craig

  51. I just want to thank the author and all the people replied to the article and offered more solutions.

    I was really frustrated with my CSS layout until I found this article using Google.

    In the end I choose to use the solution of using the “display: inline-block;” as a trigger and switch back to “display: block;”.

    This way I can be sure that the fix is 100% safe for other browsers. …And it also keeps the fix separate from the code, which is so much easier to follow.

    P.S> I would really hate to change the HTML just to make CSS display right.

  52. Thanks very much, I had the gap problem with IE7 in combination with doctype.

    Took me 4-6 hours of trying all sorts of fixes, until I found this one.

    Had to do some css repositioning but it’s fine now!

    display:inline-block fixed it. Thanks again,

  53. By the way: I put the inline-block solution in an additional style sheet, in combination with the conditional CSS statement that only IE will support:

    < link rel=”stylesheet” Firefox-style> <!—[if IE]> <link rel=”stylesheet” IE-style> <![endif]—>

    I only put the IE-specific styles in the IE-stylesheet, all cross-browser css is in the FireFox-stylesheet

  54. Thanks for that, fixed a strange problem for me.

    I like to use display:block; on my lists so that the whole thing is a link, not just the text. IE6 and 7 would bump up an image below the list in the same div by about 5 px, but only when you move the mouse over it. Not a :hover thing because it stayed after you moved away. Also only when the last item was given an id for the CSS to highlight it (id=”selected”). Very strange.

    I still dont understand why, but this fixed it, thanks.

  55. March 15, 2007 by Franky Deeee

    Awesome folks, thanks for posting all this great info, and esp to Sean for his uber-easy one-space tricks. Works great in Win IE and saved me from pulling (more of) my hair out!!

  56. May 16, 2007 by Giulio Fabris

    Sincere thanks to Roger and the folks who came up with more solutions for this issue. I’ve been stuck at this the whole afternoon yesterday and today I can finally take the next step in the project I’m working on.

  57. Hmm, after switching to Vista and IE7 seems my old trick still is the one working for me atleast. Probably it’s my coding style and CSS, but your sollution Roger doesn’t work for me. What does work however, is setting width on the li and a, and set the li with a left float.

    Nice to see this anoying bug wasnt fixed for some strange reason in IE7, lovely!, :D

  58. Love Sean the Prawn’s fix… funny how one solution to the problem with extraneous whitespace is MORE extraneous whitespace. And since this bug is also in the IE7 build that ships with Vista, we can look forward to many more years of dealing with this one. Yay.

  59. @Jadwigo - the border technique works perfectly… thankyou!

Comments are disabled for this post (read why), but if you have spotted an error or have additional info that you think should be in this post, feel free to contact me.