<table> Table

Tabular data laid out in rows and columns.

<table> is for tabular data, meaning information that naturally falls into rows and columns, like a train timetable or a price list. Inside goes an optional <caption>, then <thead>, <tbody> and <tfoot> holding rows (<tr>) of cells.

Page layout is a job for CSS. Mark header cells with <th> so screen readers can announce them. border, cellpadding, bgcolor and similar attributes are obsolete; do that styling in CSS.

The table element in the HTML Living Standard (opens in a new tab) includes advice on describing tables plus the full processing model. Begin with the Table Basics lesson.

Syntax

<table>
  <tr>
    <th>Header</th>
  </tr>
  <tr>
    <td>Data</td>
  </tr>
</table>

When to use it

Would the data make sense in a spreadsheet with headings? Then it is a <table>. Readers look up a value by its row and column, as in a bus timetable, a comparison of subscription plans, sports results, a nutrition label, a gradebook or a calendar month.

A single column of name-value pairs is lighter as a dl. A grid of cards or photos is a CSS job on normal elements. It has no headers to announce, and table markup would have screen readers reporting rows and columns that mean nothing.

By default the browser sizes columns from their content. One long URL or product code can push a table far past its container. For predictable columns add table-layout:fixed with a width, and let long words break with overflow-wrap:anywhere on the cells.

Live example

Edit the code and watch the preview.

<table>
  <caption>Pet ages</caption>
  <thead>
    <tr>
      <th scope="col">Name</th>
      <th scope="col">Age</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Milo</td>
      <td>3</td>
    </tr>
    <tr>
      <td>Rex</td>
      <td>5</td>
    </tr>
  </tbody>
</table>

More examples

Plan comparison with row headers

The column headers name the plans, the row headers name the features, and each has the right scope. A screen reader can then read both headers with every data cell, like Storage, Pro: 100 GB.

<table>
  <caption>Plan comparison</caption>
  <thead>
    <tr>
      <td></td>
      <th scope="col">Free</th>
      <th scope="col">Pro</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">Storage</th>
      <td>5 GB</td>
      <td>100 GB</td>
    </tr>
    <tr>
      <th scope="row">Price per month</th>
      <td>$0</td>
      <td>$8</td>
    </tr>
  </tbody>
</table>

Timetable with fixed layout

Under table-layout:fixed the column widths come from the first row and the table width. The longest content no longer decides. The long stop name wraps inside its cell and the table keeps its size.

<style>
.times{table-layout:fixed;width:100%;max-width:400px;border-collapse:collapse}
.times th,.times td{border:1px solid #999;padding:4px;overflow-wrap:anywhere}
</style>
<table class="times">
  <caption>Bus 42, weekdays</caption>
  <tr>
    <th scope="col">Stop</th>
    <th scope="col">First</th>
    <th scope="col">Last</th>
  </tr>
  <tr>
    <td>Central Station Northern Entrance Bus Terminal</td>
    <td>5:40</td>
    <td>23:10</td>
  </tr>
  <tr>
    <td>Market Square</td>
    <td>5:52</td>
    <td>23:22</td>
  </tr>
</table>

Tip: Use tables for data. Do layout in CSS.

Browser support

Tables are one of the oldest parts of HTML, and every browser and screen reader handles them. display:table in CSS can't stand in for one. It lays boxes out like a table and adds no table semantics. In the same way, role="presentation" on a table strips its meaning for assistive technology.

Accessibility

Mark header cells with th and name the table with a caption. Screen readers can then announce the right headers with each cell (WCAG 1.3.1). Simple and complex headers are both covered in the W3C tables tutorial (opens in a new tab).

Common mistakes

Wrong

<table>
  <tr><td>Name</td><td>Age</td></tr>
  <tr><td>Ana</td><td>31</td></tr>
</table>

Right

<table>
  <caption>Team members</caption>
  <tr><th scope="col">Name</th><th scope="col">Age</th></tr>
  <tr><td>Ana</td><td>31</td></tr>
</table>

Use th for header cells and a caption for the table's name.

Frequently asked questions

Should I use HTML tables for page layout?

No. Tables are for tabular data, where rows and columns relate to each other: timetables, price lists, statistics. Screen readers announce row and column positions, so a layout table confuses their users, and layout tables are hard to make responsive too. Lay pages out with CSS and save <table> for real data. If you were after a grid layout, read the Tables Are Not Layout lesson.

How do I make a table responsive on mobile?

Wrap it in a container with overflow-x:auto. On a narrow screen the table then scrolls sideways and keeps its structure intact. Give the wrapper tabindex="0", a role of region and a label so keyboard users can scroll it too. Converting the table into blocks with CSS can strip its table semantics, so avoid that. To build and style a table fast, an HTML table generator (opens in a new tab) gives you the markup with a live preview.

Practise it

Related tables elements