Home | All Questions | alt.html FAQ > CSS Presentation

How do I make a bulleted list that doesn't indent?

Indentation is browser behavior only, not part of the very concept of a bulleted list or, more properly, <ul> element (which need not be displayed as bulleted).

The proper way to suggest that a <ul> element be not displayed with indentation is a job for CSS. Here's a simple approach that shouldn't cause serious harm and that reduces the indentation significantly in most browsing situations:

<style type="text/css">
@media all {
 ul { margin-left: 0; }
 li { margin-left: 1em; }
}
</style>

The <ul> element is to be written quite normally then.


The following is a post from Eric Meyer, author of "Cascading StyleSheets - the Definitive Guide" and "Eric Meyer on CSS", both excellent CSS resources

The question which I was trying to answer was "how are lists styled by browsers?" This helps to answer the corollary question, "why don't IE5/Mac and NS6.1 seem to behave the same way when styling lists?"

First, I'm going to start with a pure list item-- no marker, and no containing list element-- hanging in a vacuum, which is to say it isn't yet part of a document. Picture it in layout limbo, waiting to be completely constructed before the browser puts it on the screen.

   ----------------------
   |This is a list item.|
   ----------------------

That box represents the content-area of the list item. Now, according to the box model, this box must be displayed within the parent element's content-area[1]. Therefore, we have:

  ------------------------
  |----------------------|
  ||This is a list item.||
  |----------------------|
  ||This is a list item.||
  |----------------------|
  ||This is a list item.||
  |----------------------|
  ------------------------

There are no margins or padding set for anything yet, so that outer box is the border of the UL, which at the moment is analogous to its content-area. Obviously I'm up against the limitations of ASCII art here, so I have to ask you to imagine that the "space" between the outer box and the list items isn't there, such that there are no pixels between the edges of the boxes.[2]

Now let's say that I want to add markers (bullets) to the list items. Markers are placed relative to the list items, but they do NOT change the layout of the UL! Thus:

  ------------------------
  |----------------------|
 *||This is a list item.||
  |----------------------|
 *||This is a list item.||
  |----------------------|
 *||This is a list item.||
  |----------------------|
  ------------------------

Visually, the markers are outside the content-area of the UL, but that's not the important part here. The markers are placed outside the "principal box" of the LI elements, not the UL. They're sort of like appendages to the list items, hanging outside the content-area of the LI but still attached to the LI[3].

In fact, we discover in CSS2:12.6.1 that the offset between the marker and its principal box is measured between the borders of the two. We don't have any borders here, so the distance between the marker boxes and the LI boxes is zero[4].

Okay, we're in the home stretch. We now have to figure out how this is going to appear in a document. At the moment, we have a situation analogous to the styles:

   ul, li {margin-left: 0; padding-left: 0;}

...because neither the list items nor the UL have any left margin. If we dropped this list into a document as-is, there would be no apparent indentation and the markers would be in danger of falling off the left edge of the browser window.

In order to avoid this and get some indentation, there are a number of options available to browser implementors. They could put margins on the LI elements, but that's not what they did[5]. Instead, they enforce the indentation through styles set on the UL element-- and that's where they part ways.

In IE5/Mac, and probably IE5.x/Win, the lists are indented by setting a left margin of 2.5em on the UL element. Thus we get:

       ------------------------
       |----------------------|
      *||This is a list item.||
       |----------------------|
      *||This is a list item.||
       |----------------------|
      *||This is a list item.||
       |----------------------|
       ------------------------

NS6.x, on the other hand, sets a padding of 2.5em for the UL element, so we end up with:

  -----------------------------
  |     ----------------------|
  |    *|This is a list item.||
  |     ----------------------|
  |    *|This is a list item.||
  |     ----------------------|
  |    *|This is a list item.||
  |     ----------------------|
  -----------------------------

So the markers remain attached to the LI elements, no matter where they are. The difference is entirely in how the UL is styled. We can only see the different if we try to set a background or border on the UL element.

This is also why markers are placed outside any border set for an LI element, assuming the value of 'list-style-position' is 'outside'. If it's changed to 'inside', then the markers are brought inside the LI's content, as though they're an inline box placed at the very beginning of the LI. It's sort of like 'display: run-in' but I'm not sure it's exactly analogous. This is why the specification talks about there being no change to the left edge of the LI element's position between having the marker inside versus outside.

Boil it all down, and what we're left with is this: if you want consistent rendering of lists between Explorer 5.x and Netscape 6.x, you need to set both the left margin and left padding of the UL element. We can ignore LI altogether for these purposes. If you want to reproduce the default display in Netscape 6.x, you write:

  ul {margin-left: 0; padding-left: 2.5em;}

If you're more interested in following the Explorer model, then:

  ul {margin-left: 2.5em; padding-left: 0;}

Of course, you can fill in your own preferred values. Split the difference and set both to 1.25em, if you like. If you want to reset lists to have no indentation, then you still have to zero out both padding and margin:

  ul {margin-left: 0; margin-right: 0;}

The end result being that neither browser is right or wrong about how they lay out lists (and if I remember aright, this discussion was sparked by a comment that implied that Netscape doesn't "get this right"). The two browsers I discussed are consistent in CSS terms, but don't use the same default styles. It took a while, and several test files, for me to work this out completely in my head, and I'd like to thank Al and Ian for spurring me into making the journey.

Footnotes

[1] I'm ignoring the potential effects of negative margins here, since that's a different (and similarly complicated) discussion.

[2] Eventually I think I'll turn this into a Web-based article so I can use GIFs to show examples, but that's for later.

[3] It's tough to liken markers to anything else in CSS, except maybe absolutely-positioned elements, but I didn't really want to go there since even that's an inexact match.

[4] We could have drawn little boxes around the markers, but that would unnecessarily complicate the picture.

[5] Try it yourself: create a list (or a set of nested lists) and then declare 'li {margin-left: 0;}'. If the layout doesn't change from the norm, then you know that list items have no left margin by default.

Recommended Resources

Discussion

Related Questions