Table Like It's 2023

by Amy Carney published on

In this article:

Hello, Website Builders!

Hey, you. Yes, you. Let's talk about tables on the web.

It's almost 2023. Yet tabular data is still being delivered in ways that aren't accessible. From a visually disabled person's perspective, it's horrifying.

Data tables aren't given semantic HTML to clarify its information relationships. Table markup is still used for page layouts, yet they're aren't flagged as such. The Web Alamanac reported how infrequent caption (a table's title) and role=presentation (indicating layout-only) were used in 2022 to improve accessibility.

I'm embarrassed on behalf of my fellow developers, who should be more up-to-date with their craft and aware of current standards and best practices. My hope is to persuade you to make better choices as you build your website.

A little history

Table markup has been available since 1994, despite not being an official HTML 3.2 recommendation until 1997. If you were writing front-end code at that time, you probably did what a lot of us did: use table for layout AND tabular data. We didn't have many alternatives then. It didn't help that the specification stated that tables could be used for "layout purposes."

But that was then. We have better options now. HTML 4.01 gave us separate stylesheets. CSS iterations have given us multiple ways to layout pages, including:

  • CSS grid,
  • flexbox,
  • multi-columns, and
  • positioning rules.

Yet, 28 years later, the inaccessible tables I've seen (and remediated) have me scratching my head. Are today's developers learning from old knowledge delivered in tutorials and Stack Overflow answers? Despite reliable, easy-to-access resources, like MDN (Mozilla Developer's Network), table and data abuse are still happening.

What is a table?

To know when and how to use a table, you need to understand what a table is. A table is for tabular data.

WHATWG's (Web Hypertext Application Technology Working Group) HTML Living Standard states about tables, "The table represents data with more than one dimension, in the form of a table."

If you're less familiar with the HTML Living Standard, you may recognize MDN. MDN describes an HTML table as, "tabular data — that is, information presented in a two-dimensional table comprised of rows and columns of cells containing data."

Who benefits from tables?

Ok, maybe you already know what a table is.

But do you know who benefits from proper table markup and styling? By "proper table markup", I mean the table element, not div or img elements.

Generally, people with visual and cognitive disabilities benefit.

Specifically, people who:

  • use a screen reader,
  • magnify their screen,
  • use Windows High Contrast Mode,
  • use dark mode,
  • use custom stylesheets,
  • copy & paste,
  • import data into other programs, and
  • save pages as PDFs.

To be honest, I'm hard-pressed to find anyone who doesn't benefit from thoughtful markup and styling of table data.

What does a table look like?

By this point, we know a table looks like a 2D grid of rows and columns. Is there more to consider? Yes!

We want to help people make visual sense of a table. To be more inclusive, content creators, designers, and developers should evaluate their choices when it comes to:

  • contrast between background color and foreground text,
  • font family, size, and spacing,
  • border visibility, color, and thickness,
  • color choices that can be overwritten by custom stylesheets and Windows High Contrast Mode, and
  • hover-activated changes that exclude keyboard and mobile device users.

As someone visually disabled, who needs strong contrast and screen magnification, I need borders that stand out. When I magnify my screen, a solid line guides me along each row. As I rely on strong contrast between background, border, and text, I need borders and backgrounds to not be a light gray. Not to mention, if I use Windows High Contrast Mode that day, your background colors will disappear.

What does a table sound and feel like?

But what about people who don't rely on visual cues? Specifically, people who rely on text-to-speech (screenreader) software to read content and convey the context of the content (headings, tables, images, etc.).

Screen reader semantics

A table is self-explanatory by conveying its child relationships between data points. Cells are associated with the column and row they sit in. HTML elements have this accessibility built-in.

I highly recommend you watch Léonie Watson's demonstration "How screen readers navigate data tables", approximately 2 minutes to watch.

You should also read her accompanying blog post about how screen readers navigate data tables.

Screen reader keyboard shortcuts

Did you know screen readers allow users to navigate with keyboard shortcuts? They can jump from table to table and interact with columns, rows, and cells within a table.

WebAIM provides helpful instructions on how to get started to test with a screen reader:

If you need a better sense of which screen readers are used the most, checkout WebAIM's latest Screen Reader User Survey.

Don't forget about mobile screen reader users. They have access to touch gestures to quickly jump between tables and navigate within a table, too. But some mobile device users pair their phone or tablet with a keyboard, giving them access to keyboard commands.

Learn more about the screen reader user's experience

Feel intimidated by screen readers? Check out these resources to get an introduction to screen readers and how people use them:

Your markup choices can make or break a user's experience.

(Re)learning tables (1994 - 2022)

This is my largest section, by far. If you feel you need to move forward, here is my TL;DR (too long, didn't read):

  • It's OK to use table in 2023! Make that tabular data make sense to everyone.
  • It's not OK to arrange tabular data in divs and spans, or other unrelated markup.
  • It's not OK to use an img of a table, which is inaccessible for many folks.
  • Update your table model knowledge; some elements and attributes have changed in the past 28 years.

If you're still with me, here we go.

As I said, a lot has changed since 1994. We have more HTML elements to construct more meaningful (context for content) webpages. Styles have broken free from the building blocks of HTML to create a separate layer of aesthetics.

When should you use a table?

Maybe you're still torn about if you should use a table or not.

Here's a few questions you can ask yourself:

  • Do I have tabular data (grid of items related to one another)?
  • Do I have an image (img) of a table?
  • Does my table element have a role=presentation attribute on it?
  • Does my table use obsolete attributes, like border, cellspacing, or cellpadding with a value of 0?

If you said, "yes" to the first two items, then you probably should use table. If you said, "yes" to the last two items, you probably should use CSS to design your layout instead.

Speaking of CSS, today we have the advantage of separating architecture from aesthetics. Several HTML table attributes are now obsolete, to be replaced by CSS properties. Let's dive into the HTML building blocks, then bring up the decorative part again.

How to markup tables

Ready to make that table now?

Let the HTML Living Standard be your guide:

"Expected children [of the table model] include, in this order:

  1. optionally a caption element,
  2. followed by zero or more colgroup elements,
  3. followed optionally by a thead element,
  4. followed by either zero or more tbody elements OR one or more tr elements,
  5. followed optionally by a tfoot element, optionally intermixed with one or more script-supporting elements."

What does that look like for those who write or generate HTML?

<table> <!-- required -->
<caption></caption> <!-- optional, but ensure table has an accessible name -->
<colgroup> <!-- 0 or more -->
<thead> <!-- thead optional -->
<tr> <!-- tr required -->
<th scope="row"></th>
<tbody> <!-- tbody optional, 0 or more -->
<th scope="row"></td>
<tfoot></tfoot> <!-- tfoot optional -->

A note about table model elements

If you started coding tables in the 1990s, you may feel that table markup was simpler then. Did you know HTML 4.01 introduced new elements for row and column groups to the table model?

If you haven't already, consider adding these elements (from the HTML Living Standard) to your toolbox:

The ability to group rows and columns are useful for granular styling or organization of data. They are not essential for accessibility at this time.

A note on deprecated attributes

Even in 2022, I've seen old attributes hanging around that have been dumped in the obsolete bin. It's time for a markup refresh, if you're still using obsolete attributes.

Obsolete (deprecated) table attributes
tablealign, bgcolor, border, cellspacing, cellpadding, frame, rules, summary, width
captionalign, valign
colgroupalign, bgcolor, char, charoff, valign
tralign, bgcolor, char, charoff, valign
thalign, nowrap, valign, width, height

WCAG levels unlocked

The appropriate use of the table element now welcomes everyone to your site and app. But you get something out of it, too! Your project has come further in achieving accessibility success and unlocking new levels of the Web Content Accessibility Guidelines (WCAG).

Here are some WCAG success criteria (SC) you've managed to tackle with your user-driven approach:

Depending on your content, design, table width, and approach, you may have even covered:

No guarantees on those "bonus" criteria. But they are worth learning and exploring how to apply in the context of your page and website.

Go, you!

When tables get complicated

Sometimes you don't want to reach for table because it's complicated, for one reason or another:

  • You were given a graphic of a table, rather than text content, and don't have an easy way to make it real text, despite the existence of ExtractTable, which converts data from images.
  • You're using a framework like Rails or a CMS like WordPress that generates HTML, and you can't edit it or it's difficult to edit.
  • You struggle with CSS.
  • The default design is ugly and doesn't "fit" into your site's design.

Maybe at this point, you've gotten past those issues, and you're really trying. But sometimes tables are just... hard. You've been asked to put form inputs in there. Your table needs to be dynamically sortable. Or you have loads of information, but it barely fits on a large viewport, and horizontally overflows on a small viewport.

It's OK to get frustrated. We've all encountered challenges when given a complex design idea. And some solutions are imperfect.

What I'm sharing in this article is meant to lead you in the right direction. Categorizing and building things is hard in real life.

You could learn from Adrian Roselli, who has tackled some of the hard issues:

And there are others to learn from, too:

Other things to beware

You've done your research, you've created solutions, but sometimes you still run into problems. Keep these things in mind:

  • Nested tables can break a screen reader user's experience. Try rearranging your table, or make multiple tables to keep them simple.
  • Tables with lots of columns are hard to wrangle for the different screen sizes out there. There is no perfect solution. Experiment with ways to help the data reflow and stack without losing its context and relationships.
  • Changing the CSS display value on the table element breaks the semantics of the table and breaks a screen reader user's experience.
  • In Safari 16, VoiceOver for Mac will read a caption as the table's name, but will not see a nested heading level in:
    • the Web Rotor headings list, and
    • the "next heading" keyboard shortcut.
  • HTML generators and Markdown commonly exclude some table elements and attributes, like caption and scope.

Go forth, and make good tables

Whew! I feel like I could jabber on and on about the importance of table markup.

However, here are the main things I want you to remember :

  • Don't use table for layouts.
  • Avoid nesting tables and simplify data relationships, where possible.
  • Ensure each table has an accessible name, whether it be:
    • table > caption
    • table aria-label={Table name}
    • figure > figcaption + table;
    • h{#} id={table-name} + table aria-labelledby={heading id} (use with caution).
  • This shouldn't have to be said, but don't ARIA overload a table.
  • Test your work with a screen reader or, even better, a proficient screen reader user.
  • Take a deep breath and try not to overthink it.

I urge you in the coming year, use real tables for tabular data!

Learn HTML (including tables) for free

Testing tools

Special thanks

This write-up wouldn't be possible without the generous time and critical review from my friends and accessibility allies:

About Amy Carney

Amy Carney (she/her) is a Certified Professional in Web Accessibility (CPWA) through the International Association of Accessibility Professionals (IAAP). She owns and operates Digilou, an independent web accessibility consultation and web design LLC. While getting CPWA-certified, she documented her journey on 100 Days of A11y to share with others who wanted to get started with web accessibility. She’s been practicing web design + development for almost 10 years, 5 of which she’s been an accomplice for accessibility.

Twitter: @click2carney
Mastodon: @click2carney
Github: digilou
LinkedIn: carneyamy