Best Practices for List Spacing (both UL & OL)

Hi, I’m looking for some tips and advice for best methods to control the spacing in standard lists throughout my site. Mostly concerned with spacing between list items, but also with left-indent issues across all browsers. These are NOT menus.

I have usually added bottom margin or padding to my li’s to control the space between them, but then I have to factor this space in to the bottom list item and what comes after it. Ultimately, it would be preferable to control the space above and below the entire list (UL) without being affected by the spacing of the individual list items. But I’m assuming this is not really possible, huh?!?

Then, I am also wondering about best methods for producing consistent left indents across all browsers. Are there advantages to using padding vs. margin vs. text-indent, etc.

Lastly, I’m trying to use ems on a current site to control font-sizing instead of the usual pixels. But lists are presenting problems as they are so nested. Any tips for keeping the ‘cascade’ under control in a list but still being able to have precisely sized type throughout (sometimes differently sized)?

THANKS!!!

I usually just set a desired line height to space them to the desired hight.

ul li, ol li {
     line-height:160%; /*or whatever height you like*/
}

As far as the left margin, 3em seems to work fine for me.

ul, ol {
     margin-left:3em;
}

Hope this helps!

The problem with using a large line-height on a LI is the huge space that it gives if the text wraps to another line. As the OP has stated these are not menus but just typical UL/OL, in that case there is usually more than one word and possibly a complete sentence.

Mostly concerned with spacing between list items, but also with left-indent issues across all browsers. These are NOT menus.

As far as the default left indent of the LI you should always reset the margin and padding. <UL>s and <OL>s have a list indent, applied via left margin on IE and left padding on FF, therefore both of these should be controlled. I typically use padding-left after I have zeroed out the IE’s default left-margin.


ul,ol {
margin:0;
padding:0 0 0 2em;
}

I have usually added bottom margin or padding to my li’s to control the space between them, but then I have to factor this space in to the bottom list item and what comes after it. Ultimately, it would be preferable to control the space above and below the entire list (UL) without being affected by the spacing of the individual list items. But I’m assuming this is not really possible, huh?!?
If you want true spacing between the LIs’ then that’s what margins are for. Padding adds space on the inside of an element though it can be used to simulate margins it is not the same. To control space above and below the UL you should be using margins. You will need to understand how collapsing margins work and then you can use them in your favor. If there are floats set anywhere on the UL or LI then margins will not collapse between floats. As long as these are not menus then I see no reason to be using floats on the LI, so at least that should not be an issue. You may want to float the UL though, so any vertical margins set on it would not be collapsing in that case.

I have a simple method to ensure they appear identically across browsers, I remove all padding and margins from the list (and it’s items) like within a CSS reset mechanism and then scale the items themselves using a bottom padding (for spacing) and a left margin (for pushing it into the left while retaining the bullet). :slight_smile:

If you want true spacing between the LIs’ then that’s what margins are for. Padding adds space on the inside of an element though it can be used to simulate margins it is not the same. To control space above and below the UL you should be using margins. You will need to understand how collapsing margins work and then you can use them in your favor.

Yeah, that’s what I assumed and what I usually do. I guess it only becomes an issue when the margins for your LI’s are more than what you want for the elements following the entire list (such as a heading or paragraph). Then the larger margin on the LI’s would win out over the smaller margin you may prefer for after the list. Just have to try to style accordingly I suppose.

And I usually use margin for the left-indent as well, but I think IE treats this differently when you are using list-style ‘outside’, correct? In IE, it looks like my list is hanging out in the margin a few pixels, where in other browsers it is flush. I don’t like to use list-style ‘inside’ in case there is enough text to wrap. It doesn’t indent the next line(s) properly.

  • Any better way to create an equal left-indent with bullets or numbered lists in IE AND the others??

THANKS!

Then the larger margin on the LI’s would win out over the smaller margin you may prefer for after the list. Just have to try to style accordingly I suppose.
Yes, that is how collapsing margins work. One thing that trips people up also when they try to set margins on the LI is that they fail to force the UL to establish margin clearance for it’s child LIs’. That goes back to the basic collapsing margin principles. If you want to [URL=“http://reference.sitepoint.com/css/collapsingmargins#collapsingmargins__fig_css-box-model_collapsing-margins4”]uncollapse child margins then the parent either needs top/bottom borders or padding (1px top/bottom padding will do it) or the overflow property applied to it.

Here is a simple example of collapsing margins working in my favor all the way through the page <H1> ,<UL> ,<P>

They all have 1em margins and I have set overflow:hidden on the UL to establish margin clearance. A BG color on the UL and LIs’ shows what is going on. I also set a width on the UL to force the long strings of text to wrap in the LI, that shows why you would not want to depend on line-height for spacing.

It renders the same in all my browsers. :wink:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Cross Browser List Margins</title>
<style type="text/css">
body {
    font-size:100&#37;;
    margin:0;
    padding:0;
    background:#333;
}
h1 {
    font-size:2em;
    margin:.5em;
    background:#FFF;
}
p {
    margin:1em;
    background:#FFF;
}
ul {
    width:20em;
    margin:1em;
    padding:0 0 0 1em;
    background:lime;
    overflow:hidden;/*establish margin clearance for li*/
}
li {
    margin:1em;
    padding:.25em;
    background:#FFF;
}
</style>
</head>
<body>
    <h1>Cross Browser List Margins</h1>
    <ul>
        <li>List item with a long string of text</li>
        <li>List item with a longer string of text: List item with a longer string of text</li>
        <li>List item with a long string of a text long string of text</li>
        <li>List item with a longer string of text: List item with a longer string of text</li>
    </ul>
    <p>Lorem ipsum dolor sit amet consectetuer pellentesque nibh Aenean augue id. Vestibulum lorem consequat 
    urna dolor eros id pellentesque dui Morbi libero. At Vestibulum ipsum Curabitur vestibulum vel leo Morbi 
    Cum feugiat Sed. Consequat id laoreet tortor Quisque cursus sapien est ut ligula pharetra. Ultrices dui 
    Vivamus quis elit Quisque enim pharetra nisl feugiat tincidunt.</p>
</body>
</html>

From a technical perspective, I suppose you might be able to overcome this with a negative margin on the <ul>, or another solution would be to give the <li>s a top margin rather than a bottom margin, and then you can use :first-child to avoid a big ugly space at the top.

From a design perspective, I’d be wary of a design that has bigger gaps between list items than after the final list item - it’s likely to look unbalanced and awkward. If you’ve got a 0.5em gap (or whatever) between items, the chances are you will want at least a 0.5em gap after the last item.

If you want to uncollapse child margins then the parent either needs top/bottom borders or padding (1px top/bottom padding will do it) or the overflow property applied to it.

Interesting. Although, using overflow:hidden is kind of doing the opposite of what I would guess it might do. When it is NOT applied, the margins of the LI’s aren’t added to the margin of the UL, but when it IS applied they are added. I would have guessed that using a ‘hidden’ value might have actually ‘cut-off’ the margins that extended beyond the parent container.

From a technical perspective, I suppose you might be able to overcome this with a negative margin on the <ul>, or another solution would be to give the <li>s a top margin rather than a bottom margin, and then you can use :first-child to avoid a big ugly space at the top.

OK. These are good suggestions that actually might work. What are the limitations, though, with using the :first-child selector? Does it fail only in IE6? Or do other IE flavors struggle. This would be my first choice if it is fully compatible.

From a design perspective, I’d be wary of a design that has bigger gaps between list items than after the final list item - it’s likely to look unbalanced and awkward. If you’ve got a 0.5em gap (or whatever) between items, the chances are you will want at least a 0.5em gap after the last item.

True. True. I agree, and this situation might not come up. I think I was mostly trying to understand the concepts and make sure I had total control over the placement of the list inline with the other elements on the page.


Now I just need to figure out how to get equivalent left-indents on lists in both IE and other browsers. I think the problem may be more apparent on ordered lists than unordered lists, but I’ll have to check further.

  • Any good tips or links to a ‘best’ solution for this? I seem to recall this possibly being an unachievable goal without serious hacking.

Yes, the overflow property can be confusing but once you understand it’s side effects you can use it to contain floats and uncollapse margins. As I stated in my first post margins reside on the outside of an element, they are not inner elements that hang out of the parent so they are not effected by any overflow:hidden clipping.

As I understand it, the overflow property (other than visible) introduces a new formatting context. It confirms the position of all it’s child elements and then securely encloses them if they are within the parent. That is why the margins of the first and last child of an overflow box do not collapse through the parent.

You can’t use it all the time though, for example you can’t use it on dropdown menus. It would do it’s normal job then and hide anything that protruded. I just used it on my example instead of using top padding.

Other than removing the list-styles and then reapplying them manually in spans set up in some crazy html it won’t happen.

You are not going to get x-browser pixel perfection on the list marker position with standard HTML formatting of an OL/UL. It is the UA that determines the position of the list marker and there is no way to position them other than their default. The best thing to do is just come to terms with it and realize that the viewers are not going to be inspecting the list markers like we do. A sufficient left padding on the UL is the best way to handle them and then just let them have their way.

IE6/7 seem to be the most inconsistent when compared to all other browsers. Take this code below for example and it roughly gives me these results.

Using 16px as my default browser font-size and medium in IE.

IE6/7 : The OL bullet is visible flush to the inner left edge. The UL marker is out of sight to the left.

IE8, FF3 & Opera: The OL bullet renders in the same place yet it’s size varies. The UL marker resides in the same place in all of them.

(Safari & Chrome) Webkit: The OL bullet is shifted left and resides half in and half out. The UL marker is shifted about 1px more to the left than the all other modern browsers.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Cross Browser List Margins</title>
<style type="text/css">
body {
    font-size:100&#37;;
    margin:0;
    padding:0;
    background:#FF0;
    border:20px solid red;
}
ol,ul {
    width:20em;
    margin:1em 0;
    padding:1px 0;
    background:#0F0;
}
li {
    margin:1em;
    padding:.25em;
    background:#FFF;
}
</style>
</head>
<body>

    <ul>
        <li>List item with a long string of text</li>
        <li>List item with a longer string of text: List item with a longer string of text</li>
        <li>List item with a long string of a text long string of text</li>
        <li>List item with a longer string of text: List item with a longer string of text</li>
    </ul>
    
    <ol>
        <li>List item with a long string of text</li>
        <li>List item with a longer string of text: List item with a longer string of text</li>
        <li>List item with a long string of a text long string of text</li>
        <li>List item with a longer string of text: List item with a longer string of text</li>
    </ol>

</body>
</html>

Other than removing the list-styles and then reapplying them manually in spans set up in some crazy html it won’t happen.

Ok, thanks a lot! This at least may save me hours of trying to figure it out :wink:

So the template I’m using for this site (it’s a Joomla site) already had a separate style sheet for IE setup. There are only a couple lines in it, but this is probably the best way to tackle these impossible consistency issues. It sure seems simpler than spending hours and hours trying every hack imaginable, only to find they only half-work. In the case of the ordered lists I was styling, I just had to add about 4px more to the left margin so that the numbers would show up properly.

Thanks for all the great tips!