🏠 Games Tutorials Dev blog JS code golf Other projects

Ordered and unordered lists

August 2013, january 2022

HTML lists... we all know them by heart: they exist since the first versions of HTML and XHTML, and they almost didn't change since then. They also work on all browsers.

Let's study their HTML.
<ul> means "unordered list", <ol> means "ordered list", and <li> means "list item".
Here is their simplest form (note that the </li> are optionals)

Demo:

<ul>
  <li>Element 1
  <li>Element 2
  <li>Element 3
</ul>

<ol>
  <li>Element 1
  <li>Element 2
  <li>Element 3
</ol>
Result:
  • Element 1
  • Element 2
  • Element 3

  1. Element 1
  2. Element 2
  3. Element 3

The li can also contain ul or ol sub-lists. (but we'll talk about that later)

The lists also have specific attributes:

  • <ul> (and its <li>s) can have a "type" attribute, with the value "circle", "square" or "disc". This allows to change their ticks ("circle" by default).
  • <ol> (and its <li>s) can also have a "type" attribute, with values like "A", "a", "I", "i", "1". This allows to set their number notation ("1" by default).
  • You should avoid the type attribute, and use CSS instead (we'll come to this later)
  • <ol> can have a "start" attribute telling where the numbering should begin, and its <li>s can have a "value" attribute to change their default number, and the following ones. (This works on IE6+)

Demo:

<ol start="10">
  <li>Element 10
  <li>Element 11
  <li>Element 12
  <li value="20">Element 20
  <li>Element 21
  <li>Element 22
  <li value="5">Element 5
  <li>Element 6
  <li>Element 7
</ol>
Which gives yus:
  1. Element 10
  2. Element 11
  3. Element 12
  4. Element 20
  5. Element 21
  6. Element 22
  7. Element 5
  8. Element 6
  9. Element 7
  • And finally, <ol> can have a "reversed" attribute (appeared with HTML5) allowing to count the elements from bottom up. But since it doesn't work on IE < 11, you should rather set a decreasing "value" to each <li> to get the same effect.

Now let's see their default CSS code, and their dedicated CSS properties:

<ul> and <ol> are normal blocks (display: block). They have a default padding-left that depends on the browser (around 40px). The ticks are included in this padding and they can't be selected as normal text with the mouse.

<ul> has disc-shaped bullets (list-style: disc outside none).

<ol> has numbers in front of each element (list-style: decimal outside none).

<li> have a special display (display: list-item), almost identical to display: block. They also have a list-style (inherited), but they can overload it individually.

The list-style property is a shorthand notation allowing to set three parameters:

  • list-style-type (that can have many many values),
  • list-style-position (that can have the value "inside", "outside" or "inherit". Inside allows them to contain their own ticks, instead of letting them stay in their parent's padding.)
  • list-style-image, which is "none" by default, but it can also be the url of an image. If the URL is invalid (or if the image isn't found), there is a fallback on the default list-style-type (disc, decimal, ...).


Now let's see the different problems that lists can cause us:

 • If you apply a CSS reset to your page, it will delete the paddings on ul and ol elements, and their ticks will be hidden.

Solution 1: put the ticks inside the li with this rule:

ul, ol { list-style-position: inside }
The ticks reappear, but we still lose the indentation of nested lists.
<ul>
  <li>list
  <li>list
    <ol>
      <li>sub-list
      <li>sub-list
    </ol>
</ul>
  • list
  • list
    1. sub-list
    2. sub-list


Solution 2 (the good one): don't change the ticks position, but re-set a padding-left to the lists, like this:
ul, ol { padding-left: 2em }
Result:
  • list
  • list
    1. sub-list
    2. sub-list
Indeed, the padding-left are cumulative, and so the nested lists are correctly indented.

 • If we nest ordered lists, their numbers will stay the same (decimal notation). A good typographic practice is to do this:

ol { list-style-type: decimal }
ol ol { list-style: upper-alpha }
ol ol ol { list-style:  lower-roman }
ol ol ol ol { list-style: lower-alpha }

Which allows nested lists as pretty as this, with up to four levels:
  1. level 1
  2. item
  3. item
    1. level 2
    2. item
    3. item
      1. level 3
      2. item
      3. item
        1. level 4
        2. item
        3. item


Let's talk about the original things that we can do with HTML lists:

  • A <li> can live without a <ol> or a <ul> around it. In this case, it will have a circle-shaped tick (on all the browsers).
  • A <ul> / <ol> can contain elements that are not <li>, or text. These elements won't have a tick or a number, contrary to <li> elements.
  • In modern browsers, lists can be reneered on many columns using the CSS property columns: 2;. But back in 2013, it required all kinds of hacks, as described in this article.
  • A list can look like a file tree with a simple 1px image and some ingenious CSS code: take a look at this.
  • The <li> elements can use one (or many) unicode character(s) as their ticks, thanks to CSS3 (and it works on IE8+):
    li { list-style: none }
    li:before { content: ">>"; margin:0 1em 0 -3em;  }
    Result:
    • Item 1
    • Item 2
    • Item 3

Cheers!
@MaximeEuziere