ul vs ol: order that matters, or doesn't

Free preview 3 min to read

Two tags, one test to choose between them

<ul>
  <li>Blue T-Shirt</li>
  <li>Red Hoodie</li>
  <li>Black Jeans</li>
</ul>
<ol>
  <li>Add items to your cart</li>
  <li>Enter shipping details</li>
  <li>Confirm payment</li>
</ol>

Apply one test every time, as the Semantic HTML courses did for article/section/aside: if you shuffled the items, would the meaning change? A cart's contents mean the same in any order, so they get <ul> (unordered list). Checkout steps happen in sequence, and shuffling them makes the instructions wrong, so they get <ol> (ordered list).

Both share the same child: li

<ul>
  <li>Item one</li>
</ul>
<ol>
  <li>Item one</li>
</ol>

<li> (list item) is the only valid direct child of either list type. The container (ul or ol) carries the ordering claim; li is the same either way.

The default visual styling is a convention, not the meaning

Browsers show bullets for <ul> and numbers for <ol> by default. That reinforces the claim visually, but the claim lives in the tag. The Semantic HTML: layout course said the same of header/main/footer. Picking a tag because a numbered list "looks nicer" repeats that mistake.

A common, genuine mistake: ol for visual emphasis alone

<!-- Wrong: features have no real sequence -->
<ol>
  <li>Free shipping</li>
  <li>30-day returns</li>
  <li>Lifetime warranty</li>
</ol>

These three features carry no inherent order: nothing changes if "Lifetime warranty" is read first. A numbered list here makes a false claim: that position 1, 2, 3 mean something, when they don't. <ul> is the honest choice, even though a numbered badge might look visually appealing in a design mockup.

Where Rails generates these from real data

<ul>
  <% @cart_items.each do |item| %>
    <li><%= item.name %></li>
  <% end %>
</ul>
<ol>
  <% @checkout_steps.each do |step| %>
    <li><%= step.description %></li>
  <% end %>
</ol>

The collection being iterated is often a strong hint. If its order is incidental, like a query with no meaningful ORDER BY, use <ul>. If position encodes a sequence, use <ol>.

How this course is organized

  • Lesson 2: why lists are more than visual: the list role and item count
  • Lesson 3: the CSS trap: list-style: none can hide a list from Safari's VoiceOver
  • Lesson 4: nested lists and the one structural rule that matters
  • Lesson 5: <ol>'s extra attributes: start, reversed, type
  • Lesson 6: <dl>, lists of pairs
  • Lesson 7: structuring a real navigation menu and FAQ end to end

Key takeaways

  • The test: would shuffling the items change the meaning? If no, <ul>; if yes, <ol>.
  • <li> is the only valid direct child of either list type: the container tag alone carries the ordering claim.
  • Default bullets and numbers reinforce the claim visually; the tag makes it. Choosing a tag for its look repeats the mistake the Semantic HTML courses warned about.
  • A numbered list on inherently unordered content (like a feature list) makes a false claim about sequence that doesn't exist.
Lesson 1 of 7 · free

Keep going with lesson 2

Lists are not just visual: the list role and item count

Shows how ul and ol give screen readers the list role and an item count that typed bullets lack.

A free account also gives you the quizzes, your progress and notes, and the discussion.

Type to start searching...