HTML Tables & Lists
Accessible Table Structure
<table>
<caption>Q4 2024 Sales by Region</caption> <!-- table title for screen readers -->
<thead>
<tr>
<th scope="col">Region</th>
<th scope="col">Q3</th>
<th scope="col" aria-sort="descending">Q4</th> <!-- sorted column -->
<th scope="col">Change</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Europe</th> <!-- row header -->
<td>$1.2M</td>
<td>$1.8M</td>
<td><span aria-label="up 50%">↑ 50%</span></td>
</tr>
<tr>
<th scope="row">Americas</th>
<td>$2.1M</td>
<td>$2.4M</td>
<td><span aria-label="up 14%">↑ 14%</span></td>
</tr>
</tbody>
<tfoot>
<tr>
<th scope="row">Total</th>
<td>$3.3M</td>
<td>$4.2M</td>
<td><span aria-label="up 27%">↑ 27%</span></td>
</tr>
</tfoot>
</table>Spanning Cells
<table>
<tr>
<th colspan="3">2024 Summary</th> <!-- spans 3 columns -->
</tr>
<tr>
<th>Q1</th>
<th>Q2</th>
<th>Q3</th>
</tr>
<tr>
<td rowspan="2">$1M</td> <!-- spans 2 rows -->
<td>$1.2M</td>
<td>$1.4M</td>
</tr>
<tr>
<!-- first cell is occupied by rowspan above -->
<td>$1.3M</td>
<td>$1.5M</td>
</tr>
</table>Complex Tables with headers attribute
<!-- For complex tables where scope is ambiguous -->
<table>
<tr>
<td></td>
<th id="mon">Monday</th>
<th id="tue">Tuesday</th>
</tr>
<tr>
<th id="morning">Morning</th>
<td headers="mon morning">9am meeting</td>
<td headers="tue morning">Code review</td>
</tr>
<tr>
<th id="afternoon">Afternoon</th>
<td headers="mon afternoon">Sprint planning</td>
<td headers="tue afternoon">1:1</td>
</tr>
</table>Lists
<!-- Unordered list — bullet points -->
<ul>
<li>Item one</li>
<li>Item two
<ul>
<li>Nested item</li>
</ul>
</li>
</ul>
<!-- Ordered list — numbered -->
<ol>
<li>First step</li>
<li>Second step</li>
</ol>
<!-- Ordered list attributes -->
<ol type="A"> <!-- A, B, C ... -->
<ol type="i"> <!-- i, ii, iii ... -->
<ol start="5"> <!-- start from 5 -->
<ol reversed> <!-- count down -->
<!-- Definition list — term and definition pairs -->
<dl>
<dt>HTML</dt>
<dd>HyperText Markup Language — the structure of web pages</dd>
<dt>CSS</dt>
<dd>Cascading Style Sheets — the presentation layer</dd>
<dt>HTTP</dt>
<dt>HTTPS</dt> <!-- multiple terms can share a definition -->
<dd>Protocol for web communication</dd>
</dl>Table Accessibility Checklist
Always include <caption> or aria-label describing the table's purpose
Use <th> with scope="col" for column headers and scope="row" for row headers
Use <thead>, <tbody>, <tfoot> to structure the table semantically
Avoid using tables for layout — use CSS Grid or Flexbox instead
Don't use empty <th> cells — use aria-hidden="true" if truly needed
Test with screen reader (NVDA/VoiceOver) — tables are announced differently by different readers
Avoid complex merged cells when simpler layout would work
Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free