Media
Embed audio, video, and responsive images. Continue →
Tables present data in a structured, easy-to-scan format. But tables need to be built correctly to be accessible to everyone. This tutorial covers semantic table structure and best practices.
What you’ll learn:
<table>, <tr>, <td>, and <th> elementsPrerequisites:
A table has rows and columns. Use these elements:
<table>: Container for the entire table<tr>: Table row<th>: Table header cell<td>: Table data cellKey points:
<th> for headers<td> for cells<th> for header cells, never plain text in <td>Organize your table with semantic sections:
<thead>: Table header section (usually the first row)<tbody>: Main data rows<tfoot>: Summary row or footer (appears below tbody visually)Add a caption describing the table:
The <caption> should be the first child of <table>. It appears above the table and helps users understand its purpose.
For screen readers to understand table data, you need to connect headers to cells. Use the scope attribute:
The scope attribute tells screen readers:
scope="col": This header describes a columnscope="row": This header describes a rowscope="colgroup": This header describes multiple columnsscope="rowgroup": This header describes multiple rowsFor tables with merged cells:
colspan="2": Cell spans 2 columnsrowspan="2": Cell spans 2 rowsFor complex tables, use the headers attribute to explicitly link cells to their headers:
<table> <thead> <tr> <th id="name">Name</th> <th id="age">Age</th> <th id="city">City</th> </tr> </thead> <tbody> <tr> <td headers="name">Alice</td> <td headers="age">28</td> <td headers="city">New York</td> </tr> </tbody></table>Each <th> gets a unique id. Each <td> lists the relevant header IDs in its headers attribute.
Here’s a realistic sports statistics table:
Tables on small screens need special handling. While HTML doesn’t handle this directly, you can use data attributes:
<table> <thead> <tr> <th scope="col">Name</th> <th scope="col">Email</th> <th scope="col">Status</th> </tr> </thead> <tbody> <tr> <td data-label="Name">Alice Johnson</td> <td data-label="Status">Active</td> </tr> </tbody></table>Then use CSS to display these labels on small screens. This is more advanced and requires CSS knowledge.
Don’t use tables for layout! Use them only for actual tabular data:
<!-- Bad: Using table for layout --><table> <tr> <td>Header</td> </tr> <tr> <td>Sidebar</td> <td>Main Content</td> </tr> <tr> <td>Footer</td> </tr></table>
<!-- Good: Use semantic HTML and CSS --><header>Header</header><aside>Sidebar</aside><main>Main Content</main><footer>Footer</footer>Tables are:
Use CSS Grid or Flexbox for layout instead.
When creating tables:
<th> for headers, never <td>scope attribute to all <th> elements<thead>, <tbody>, <tfoot> to organize sections<caption> describing the table<th scope="row"> for row headersCreate a table for your data:
Try:
<table>, <tr>, <th>, <td> for table structure<thead>, <tbody>, <tfoot> to organize table sections<th> for headers with scope attribute<caption> to describe the tablecolspan and rowspan sparinglyMedia
Embed audio, video, and responsive images. Continue →
Metadata
Optimize with SEO meta tags and structured data. Continue →