Lesson 9 of 20

HTML Lists

Three Kinds of List

HTML has three list elements, and choosing between them is a question about your content rather than about how you want it to look. An unordered list, <ul>, is for items whose order carries no meaning — a list of skills, a set of features, a navigation menu. An ordered list, <ol>, is for items where the sequence is part of the information — steps in an installation guide, ranks in a result table, chapters in a book. A description list, <dl>, pairs terms with their descriptions.

The test for ordered versus unordered is easy: if shuffling the items would change what the list tells the reader, it is ordered. "Connect the battery, then switch on the board, then upload the sketch" breaks if you shuffle it. "HTML, CSS, JavaScript" does not.

Both <ul> and <ol> hold their items in <li> elements, and the element names are worth reading as words: unordered list, ordered list, list item. The bullets and the numbers are the browser's default styling, and CSS can change or remove them entirely without changing what the list means.

Example
<!-- Order does not matter -->
<h3>What you need</h3>
<ul>
  <li>Arduino Uno board</li>
  <li>Two infrared sensors</li>
  <li>USB cable</li>
</ul>

<!-- Order is the point -->
<h3>How to run your first sketch</h3>
<ol>
  <li>Connect the board with the USB cable</li>
  <li>Select the correct port in the IDE</li>
  <li>Click Upload and wait for the confirmation</li>
</ol>

<!-- Terms and their meanings -->
<dl>
  <dt>HTML</dt>
  <dd>The markup language that gives a page its structure.</dd>
  <dt>CSS</dt>
  <dd>The language that controls how that structure looks.</dd>
</dl>
  • <ul> — unordered list; shuffling the items changes nothing
  • <ol> — ordered list; the sequence is part of the meaning
  • <dl> — description list; pairs of terms and descriptions
  • <li> — one item, used inside both <ul> and <ol>
  • <dt> and <dd> — the term and its description, used inside <dl>

What May Go Inside a List

The rule about list structure is strict in one direction and generous in the other. Directly inside a <ul> or <ol>, you may put <li> elements and essentially nothing else. Writing a paragraph, a heading or loose text as a direct child of a list is invalid, and the browser will move it out of the list when it builds the DOM — so your careful styling suddenly applies to something sitting outside the list.

Inside an <li>, however, you can put almost anything: several paragraphs, a heading, an image, a form, another whole list. This is what makes lists genuinely useful for real page structure rather than only for short bullet points. A list of club events where each item has a title, a date and a description is a perfectly good use of <ul>.

One consequence of this catches people out. Because <li> can hold block content, a list item containing a paragraph gets the paragraph's default margins as well, so the spacing looks larger than in a list of plain text items. That is expected behaviour, not a bug — adjust it in CSS if you do not want it.

Example
<!-- Invalid: loose content directly inside <ul> -->
<ul>
  <li>First item</li>
  <p>This paragraph does not belong here.</p>
  <li>Second item</li>
</ul>

<!-- Valid: rich content, but always inside an <li> -->
<ul class="event-list">
  <li>
    <h3>Robotics Challenge</h3>
    <p>12 March, Electronics Lab</p>
    <p>Teams of three. Bring your own chassis.</p>
    <a href="events/robotics.html">Full details</a>
  </li>
  <li>
    <h3>Coding Contest</h3>
    <p>14 March, Computer Centre</p>
  </li>
</ul>
Notes
  • The closing </li> is technically optional in HTML5 because the browser can work out where an item ends. Write it anyway. Omitting it makes lists with nested content genuinely hard to read, and it hides exactly the kind of mistake described in the next section.

Nesting Lists — the Mistake Almost Everyone Makes

A nested list goes inside the list item it belongs to, before that item's closing tag. It does not go between two list items. This is the most common list error in beginner code, and because browsers repair it silently, it produces a page that looks nearly right and behaves oddly.

Think about what nesting means. A sub-list is a sub-list of something — the subjects belong to Semester 1, not to the list of semesters in general. Putting the sub-list inside the Semester 1 item is what records that relationship. Putting it between items records nothing, and the browser has to guess.

The visible symptoms are inconsistent indentation, a bullet appearing where you did not want one, and CSS rules such as li > ul failing to match anything. If a nested list is misbehaving, check the closing tags first: the sub-list's </ul> must come before the parent item's </li>. Indenting properly makes this immediately visible.

You can nest as deeply as you like and mix the types freely — an ordered list of steps where one step contains an unordered list of required parts is perfectly normal. In practice, more than three levels usually means the content wants to be split into sections with headings instead.

Example
<!-- Wrong: the sub-list sits between items, not inside one -->
<ul>
  <li>Semester 1</li>
  <ul>
    <li>Data Structures</li>
    <li>Digital Logic</li>
  </ul>
  <li>Semester 2</li>
</ul>

<!-- Right: the sub-list is inside the item it belongs to -->
<ul>
  <li>Semester 1
    <ul>
      <li>Data Structures</li>
      <li>Digital Logic</li>
    </ul>
  </li>
  <li>Semester 2
    <ul>
      <li>Operating Systems</li>
    </ul>
  </li>
</ul>

<!-- Mixing types is fine -->
<ol>
  <li>Gather the parts:
    <ul>
      <li>Arduino Uno</li>
      <li>Motor driver</li>
    </ul>
  </li>
  <li>Wire the motors to the driver</li>
</ol>
Notes
  • Indent nested lists by two spaces per level as shown. It costs nothing, and it turns this whole class of bug into something you spot while typing rather than while debugging.

Controlling the Numbering

Ordered lists have a few attributes that genuinely change meaning rather than appearance, so they belong in HTML rather than in CSS. start sets the first number, which you need when a list continues after an interruption such as a screenshot or a note. reversed counts downwards, which is right for a countdown or a ranking read from last to first. value on an individual <li> forces that item's number and renumbers the rest from there.

type changes the marker style — 1 for numbers, A or a for letters, I or i for Roman numerals. This one sits on the boundary: it is presentational, and the CSS property list-style-type does the same job. The argument for the attribute is that in some documents, such as legal or academic text, the reader may refer to "clause (iv)", so the numbering style is part of the content. For ordinary pages, prefer CSS.

For unordered lists there is no meaningful equivalent — the old type attribute on <ul> is obsolete. Change bullet styles with list-style-type, and remove them entirely with list-style: none, which is what you do for a navigation menu.

Example
<!-- Continuing after an interruption -->
<ol>
  <li>Connect the battery</li>
  <li>Switch on the board</li>
</ol>

<p>Check that the power LED is lit before continuing.</p>

<ol start="3">
  <li>Open the IDE</li>
  <li>Upload the sketch</li>
</ol>

<!-- Roman numerals, and a countdown -->
<ol type="i">
  <li>Definitions</li>
  <li>Scope</li>
</ol>

<ol reversed>
  <li>Third place</li>
  <li>Second place</li>
  <li>First place</li>
</ol>

/* Bullet and number styling belongs in CSS */
ul.menu {
  list-style: none;
  padding-left: 0;
}
  • start="3" — begin numbering at 3
  • reversed — count downwards; it takes no value, the attribute's presence is enough
  • type="A", "a", "I", "i", "1" — marker style on <ol>
  • <li value="7"> — force one item's number, and continue from there
  • list-style-type and list-style: none in CSS — for everything that is purely visual

Lists Are for Structure, Not Just Bullet Points

The most useful thing to understand about lists is that their value survives the removal of the bullets. When a screen reader meets a <ul>, it announces something like "list, five items" and lets the user step through them or skip the whole thing. That count is genuinely helpful — it tells a listener how much is coming before they commit to it.

This is why navigation menus should be marked up as lists even though every real site styles the bullets away. A menu is a set of links, the browser can report how many there are, and the user can jump past it. A row of loose <a> tags inside a <div> looks identical on screen and offers none of that.

Description lists are underused and worth remembering. They are the right choice for a frequently-asked-questions block, a glossary of terms, or a set of specifications where each label has a value. A term may have more than one description, and several terms may share one description — the structure is more flexible than it first appears.

Example
<!-- A navigation menu is a list of links -->
<nav>
  <ul class="menu">
    <li><a href="index.html">Home</a></li>
    <li><a href="events.html">Events</a></li>
    <li><a href="gallery.html">Gallery</a></li>
    <li><a href="contact.html">Contact</a></li>
  </ul>
</nav>

<!-- Specifications as a description list -->
<dl>
  <dt>Microcontroller</dt>
  <dd>ATmega328P</dd>

  <dt>Operating voltage</dt>
  <dd>5 V</dd>

  <dt>Digital pins</dt>
  <dd>14, of which 6 provide PWM output</dd>
</dl>
Notes
  • A quick check on any page you build: would the content still make sense if every bullet and number disappeared? If yes, your lists are marking real structure. If a "list" was only ever there to get indentation, it should have been a <div> with CSS padding.
Ask AI