A responsive data table should stay readable at narrow widths and zoom levels without hiding information or breaking its row-and-column relationships. For a compact table, width: 100% may be enough. For a wider one, contain horizontal scrolling within the table instead of forcing the whole page to scroll.
The original example was a small leaderboard for HTML5 games. Its screenshot and embedded demo are retained below; the code here adds semantic table markup, keyboard access, and a narrow-screen fallback.
Start with a semantic HTML table
Use native table elements for data that has real row and column relationships. A caption names the table, column headers identify each column, and a row header identifies each record. These associations help people understand the data with screen readers and other assistive technology. See the WAI Tables Tutorial for more examples.
<p id="orders-hint">On a narrow screen, scroll horizontally to see every column.</p>
<div
class="table-scroll"
role="region"
aria-labelledby="orders-caption"
aria-describedby="orders-hint"
tabindex="0"
>
<table>
<caption id="orders-caption">Weekly orders by product</caption>
<thead>
<tr>
<th scope="col">Product</th>
<th scope="col">Units</th>
<th scope="col">Change</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Starter kit</th>
<td>28</td>
<td>+4</td>
</tr>
<tr>
<th scope="row">Field guide</th>
<td>16</td>
<td>-2</td>
</tr>
</tbody>
</table>
</div>
The named, focusable region gives keyboard users a place to scroll when the table is wider than its container. Keep the instruction visible; do not rely on color or a hidden gesture to explain that more columns are available.
Add responsive layout and zebra stripes
Let a small table use the available width, and allow the wrapper to scroll if the table's content needs more space. The overflow-x property controls horizontal overflow; avoid shrinking text or removing columns just to make a wide table fit.
.table-scroll {
max-width: 100%;
overflow-x: auto;
}
.table-scroll:focus-visible {
outline: 3px solid #0b57d0;
outline-offset: 3px;
}
table {
width: 100%;
border-collapse: collapse;
color: #17212b;
}
caption {
padding: 0.5rem 0;
font-weight: 700;
text-align: left;
}
th,
td {
padding: 0.625rem 0.75rem;
border-bottom: 1px solid #b8c2cc;
text-align: start;
vertical-align: top;
}
thead th {
background: #24364b;
color: #fff;
}
tbody tr:nth-child(even) {
background: #edf3f1;
}
The tbody selector keeps the header styling separate from the alternating row colors. Stripe rows only as a visual aid: the text, borders, and semantic headers must still make the table understandable when background colors are unavailable.
If you are considering turning each row into a card on small screens, treat that as a separate layout and preserve the relationship between every value and its header. The CSS-Tricks responsive table example shows another pattern, but do not copy a visual transformation without checking its accessibility.
Check narrow screens, zoom, and keyboard use
Test the page at a viewport around 320 CSS pixels wide and at high zoom. The page itself should not gain a horizontal scrollbar; if the table needs more room, only its labeled region should scroll. WCAG's Reflow guidance permits two-dimensional scrolling for content that requires a two-dimensional layout, including some data tables; keep the rest of the page usable without horizontal scrolling.
Then check that:
- You can reach the table region with the keyboard and scroll to the last column.
- The table caption, row headers, and column headers make sense when read without the visual stripes.
- Focus remains visible, and no column or cell content disappears at narrow widths.
- The layout still works when users increase text size or use a high-contrast or forced-colors mode.
The original interactive demo is preserved here:
See the Pen Responsive Table with Zebra stripes by Kanishk Kunal on CodePen.