Creating Lists (<ul>, <ol>, <li>) and Nested Lists

Lists organize related items. HTML provides three list types: unordered, ordered, and description lists.

Unordered List (<ul>) and List Item (<li>)

  <ul>
    <li>Item 1</li>
    <li>Item 2
        <ul>
            <li>Subitem 2.1</li>
            <li>Subitem 2.2</li>
        </ul>
    </li>
    <li>Item 3</li>
</ul>
  

Renders as a bulleted list with nested sub-items under “Item 2”.

  • <ul> defines an unordered (bulleted) list
  • <li> marks each list item
  • Nest <ul> inside <li> for sub-lists

Ordered List (<ol>) and List Item (<li>)

  <ol>
    <li>First item</li>
    <li>Second item</li>
    <li>Third item
        <ol type="a">
            <li>Subitem 3.1</li>
            <li>Subitem 3.2</li>
        </ol>
    </li>
    <li>Fourth item</li>
</ol>
  

Useful attributes on <ol>:

Attribute Values Effect
type 1, a, A, i, I Numbering style
start number Starting index
reversed boolean Count down

Description List (<dl>, <dt>, <dd>)

For term/definition pairs — glossaries, metadata, FAQs:

  <dl>
    <dt>HTML</dt>
    <dd>HyperText Markup Language — structures web content.</dd>
    <dt>CSS</dt>
    <dd>Cascading Style Sheets — styles presentation.</dd>
</dl>
  

List Best Practices

  • Use <ul> for unordered collections; <ol> when sequence matters (steps, rankings)
  • Keep nesting shallow — more than 3 levels hurts readability
  • For navigation menus, wrap links in <li> inside <nav><ul>
  • Style bullets with CSS list-style-type, not extra characters in HTML
  nav ul { list-style: none; padding: 0; display: flex; gap: 1rem; }
  

Structuring Data with Tables

Tables display tabular data — not page layout (use CSS Grid/Flexbox for layout).

Basic Table Structure

  <table>
    <caption>Monthly Sales</caption>
    <thead>
        <tr>
            <th scope="col">Month</th>
            <th scope="col">Revenue</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>January</td>
            <td>$12,400</td>
        </tr>
        <tr>
            <td>February</td>
            <td>$15,200</td>
        </tr>
    </tbody>
    <tfoot>
        <tr>
            <th scope="row">Total</th>
            <td>$27,600</td>
        </tr>
    </tfoot>
</table>
  

Table Structure

Element Purpose
<table> Container for tabular data
<caption> Accessible title (first child of <table>)
<thead> / <tbody> / <tfoot> Group header, body, footer rows
<tr> Table row
<th scope="col/row"> Header cell — tells assistive tech what it labels
<td> Data cell

Spanning Cells

  <tr>
    <th scope="row">Q1</th>
    <td colspan="2">Combined Jan–Mar</td>
</tr>
<tr>
    <td rowspan="2">Spans two rows</td>
    <td>Cell B</td>
</tr>
  

Accessibility for Lists and Tables

  • Never use tables for layout — screen readers announce row/column counts
  • Always use <th scope="..."> for header cells
  • For complex tables, add <th id="..." scope="col"> and <td headers="...">
  • Lists inside <nav> should use <ul> with <li><a> links

Common Mistakes and Fixes

Problem Solution
<li> outside <ul>/<ol> Wrap every <li> in a list parent
Missing <tbody> Browsers insert one, but explicit markup is clearer
Using <table> for columns Use CSS Grid or Flexbox instead
Empty <td> for spacing Use CSS padding/margin

Troubleshooting

Nested list numbers restart unexpectedly

  • Nested <ol> elements restart by default — set start or use CSS counter-reset

Table columns misaligned

  • Check colspan/rowspan values; validate with DevTools Elements panel

Screen reader reads table incorrectly

  • Add <caption>, use <thead>, and set scope on every <th>

Lists and tables are foundational HTML tools — use them semantically, style with CSS, and keep accessibility in mind from the start.