Tables: Beyond Rows and Columns

There are many semantic HTML tags covered under WCAG SC 1.3.1: Info and Relationships, but in this article, we’ll zoom in on one of the most misunderstood, the table.

You might be thinking: “Do we really need tables when we already have semantic tags like lists?”

It’s a valid question. Lists (<ul>, <ol>, <dl>) are fantastic for presenting structured information, but when data grows beyond a simple one-to-one relationship, tables step in as the powerhouse.

Lists vs. Tables: When Does a Table Make Sense?

Imagine you want to display personal details. Using a description list, the information looks clean and simple:

<h2>Personal Details</h2>
  <dl>
  <dt>Full Name</dt>
  <dd>Tom Henry</dd>
  <dt>Date of Birth</dt>
  <dd>01-Jan-1999</dd>
  <dt>Gender</dt>
  <dd>Male</dd>
  <dt>Country</dt>
  <dd>Australia </dd>
  <dt>Company</dt>
  <dd>Google</dd>
</dl>

It would look like this:

Description list shwoing the data described in the markup

That’s great for a single person’s data. But what if you have multiple people’s details?

A list would stretch the page endlessly, making it harder for users (especially screen reader users) to locate specific information. This is where a table becomes the clear winner:

<table>
  <thead>
<tr>
    <th>Full Name</th>
    <th>Date of Birth</th>
    <th>Gender</th>
    <th>Country</th>
    <th>Company</th>
  </tr>
</thead>
<tbody>
  <tr>
    <td>Tom Henry</td>
    <td>01-Jan-1999</td>
    <td>Male</td>
    <td>Australia</td>
    <td>Google</td>
  </tr>
  <tr>
    <td>Stifen Watson</td>
    <td>02-Jan-2000</td>
    <td>Male</td>
    <td>U.S.</td>
    <td>TPGi</td>
  </tr>
</tbody>
</table>

This will look like:

The data described in the markup shown as table with rows and columns.

Now, the same information is organized in rows and columns. Users can scan by column (e.g., find all employees from India) or by row (see all details of one person) in an instant.

Defining the Data Table

A well-structured table is more than just rows and cells. For screen readers and other assistive technologies, the right markup tells the story:

The data table’s semantic structure is already explained in the Tables Tutorial | Web Accessibility Initiative (WAI) | W3C. but just to be on the same page, here’s the basic concept of defining a data table:

  • <table> defines the table
  • <tr> defines each row.
  • <td> holds the data.
  • <th> indicates headers. Column headers are defined together as a row of <th> elements, while row headers are defined as a single <th> within each row of <td>.

This semantic structure allows assistive technologies to announce relationships like: “Date of Birth, 01-01-2000.” Instead of just reading “01-01-2000” without context.

Labeling the Table

When there’s only one table on a page, users usually know what it represents. But if you have multiple tables, things get tricky.

For example, screen reader might announce both tables simply as: “Table with 3 rows and 5 columns.”

JAWS speech viewer screenshot:

JAWS speech viewer describing two tables with the same apparent data.

NVDA speech viewer screenshot:

NVDA speech viewer describing two tables with the same apparent data.

Confusing, right?

That’s why naming tables is important. You can do this using the <caption> element:

<table>
    <caption>2025 Employees Details</caption>
    ...
</table>

<table>
    <caption>2024 Employees Details</caption>
    ...
</table>

JAWS announcement:

  • “table with 5 columns and 3 rows 2025 Employees Details, Column 1, Row 1” for the first table.
  • “table with 5 columns and 3 rows 2024 Employees Details, Column 1, Row 1” for the second table.

JAWS speech viewer describing two tables with the same apparent data but identified by different captions.

NVDA announcement:

  • “2025 Employees Details table with 3 rows and 5 columns” for the first table.
  • “2024 Employees Details table with 3 rows and 5 columns” for the second table.

NVDA speech viewer describing two tables with the same apparent data but identified by different captions.

Problem solved! Users now know exactly what each table represents.

Alternatively, aria-label or aria-labelledby can also be used to define the label for the table.

<table aria-label=”2024 Employees Details”>
    ...
</table>
Note: Defining a caption or a name is not required by WCAG. If you skip it, it’s not considered a failure. However, it is recommended as a best practice, specifically when more than one table is present.

If a table is complex or requires extra explanation, you can add an aria-describedby attribute to provide a short description. This helps screen reader users understand the table’s purpose and structure before navigating through its data.

<p id="tableDesc">
  This table provides employee details, including department, role, and seminar participation status for 2024.
</p>
<table aria-describedby="tableDesc">
...
</table>

JAWS announcement:

“Table with 4 columns and 2 rows. This table provides employee details, including department, role, and seminar participation status for 2024. Column l, Row 1 Employee Name”

JAWS speech viewer describing a table, including the table description.

NVDA announcement:

“Table with 2 rows and 4 columns This table provides employee details, including department, role, and seminar participation status for 2024.”

NVDA speech viewer describing a table, including the table description.

Note: The older summary property served a similar purpose in earlier HTML versions, but it is now deprecated in HTML5. While some assistive technologies may still recognize it, it’s best practice to use aria-describedby for long-term compatibility.

Layout table

A layout table is a table used purely for visual arrangement of content rather than for presenting data. In layout tables, there is no meaningful relationship between cells, and the table is only used for decorative or structural purposes.

Layout tables are acceptable in WCAG and can be used to arrange page elements such as headers, sidebars, and footers. However, this approach works visually, but it introduces accessibility challenges. Screen readers and other assistive technologies interpret tables semantically — announcing rows, columns, and headers — which can confuse users when no real data relationship exists.

For this reason, table markup should not be used for page design or visual layout.

What Not to Use in Layout Tables

Assistive technologies depend on table elements like <th> and <caption> to announce structure and meaning. Including these in layout tables misleads users by suggesting relationships that don’t actually exist.

For layout tables, avoid:

  • headers attribute
  • scope attribute
  • summary attribute
  • <th> element
  • <caption> element

Although WCAG does not prohibit the use of layout tables, CSS-based layouts are strongly recommended to preserve the proper semantic meaning of HTML table elements. When a table is used purely for layout, the <th> element, headers attribute, and scope attribute should not be used, since there is no actual relationship between data cells.

Likewise, the <caption> element and summary attribute should not be used, as they are intended to provide descriptions for data tables, not layout structures.


<table>
<tbody>
  <tr>
    <td colspan="2" >
      <h1>Header Area</h1>
    </td>
  </tr>
  <tr>
    <td>
      <p>Sidebar content goes here. <br>Links or navigation. </p>
    </td>
    <td>
      <p>Main page content goes here. <br>This is where the main article, text, or image would be placed. </p>
    </td>
  </tr>
</tbody>
</table>

When read by a screen reader, this table is treated as layout-only, and table structure is ignored.

Screen reader announces:

“heading level 1 Header Area. Sidebar content goes here. Links or navigation. Main page content goes here. This is where the main article, text, or image would be placed.”

JAWS speech screenshot:

JAWS speech viewer describing the text content of a table

NVDA speech screenshot:

NVDA speech viewer describing the text content of a table

Identifying Layout Tables

If your markup is long and complex, the easiest way to confirm whether a table is being treated as a layout table is to inspect the accessibility tree. In such cases, you’ll see the table identified as a “LayoutTable” rather than a semantic data table.

Accessibility Tree showing LayoutTable as a sub-branch of RootWebArea

Making Layout Tables Invisible to Assistive Tech

Alternatively, role="presentation" or role="none" can be applied to remove the semantic meaning of a table from the accessibility API, even if elements like <table> or <th> are present.

<table role=”presentation”>
 ...
</table>

With this approach, the entire table structure is ignored in the accessibility tree, and only the actual content inside the table is exposed to assistive technologies.

Accessibility Tree showing LayoutTable sub-branch of RootWebArea replaced by Ignored

Making Tables Responsive While Preserving Accessibility

Tables often contain large amounts of data, which can make them difficult to view on smaller screens. While many developers try to make tables “fit” by hiding columns or reflowing them into lists, these approaches can break relationships between data cells and headers.

A simple and effective way to handle this is to make the table scrollable horizontally.

<div style="overflow-x: auto;">
  <table>
    ...
  </table>
</div>

Table too wide for viewport shown with horizontal scrollbar

The overflow-x: auto; property allows users to scroll horizontally when the table width exceeds the viewport.

Conclusion

In my opinion, tables are one of the most powerful semantic tools in HTML, but they’re also among the most misunderstood. While lists and other tags can handle simple cases, tables shine when it comes to organizing and presenting complex datasets. A well-structured table does more than group information—it creates meaningful relationships between data and headers, making content more accessible for everyone, especially users of assistive technologies.

At the same time, tables should never be misused for layout purposes. Layout tables may still “work” visually, but can introduce barriers when screen readers announce them as data. By choosing semantic HTML elements appropriately and relying on CSS for layout, developers can create content that is both visually appealing and accessible to all users.

Resources

Like to be notified about more articles like this? Subscribe to the Knowledge Center Newsletter. It not only gives you summaries and links to our technical blog posts but also TPGi webinars, podcasts, and business blog posts – as well as accessibility and web tech conferences and other events, and a reading list of other relevant articles. You get one email a month, it’s free, requires just your email address, and we promise we won’t share that with anyone. Check the archive.
Categories: Technical

About Akash Shukla

Akash is an Accessibility Engineer at TPGi with over six years of experience in making digital content accessible to everyone. He is a Certified Professional in Web Accessibility (CPWA) and has expertise in WCAG conformance, assistive technologies, and creating accessible websites. Before joining TPGI, he worked as an Accessibility Consultant at Deque Systems. He is passionate about building inclusive digital experiences and promoting accessibility best practices.

Comments

thomas says:

Nice article, but I am missing a section about filtering and sorting.
That would make the article complete.

Add Your Comment