Tables
Before you add a table
Think about whether you really need to use a table
Using a table can make it easier for a user to compare and scan information, but it can also cause accessibility issues. Never use a table:
- for fewer than 2 rows of data
- if there's a simpler way to present the information, such as, in a paragraph of text
Use a table for exact values and information that's too detailed for text.
Simplify your table
Make sure your table is as simple as possible:
- it must only contain information that's necessary, don't add extra information on the off chance someone might want it
- don’t make tables with other tables inside them (nested tables)
- consider splitting a large, complex table into smaller, simpler tables
Stacking table
By default, use the .table-responsive
class in the <table>
tag to create a table that stacks on smaller screens.
First column heading | Second column heading |
---|---|
First row and first column of data | First row and second column of data |
Second row and first column of data | Second row and second column of data |
- HTML5
<table class="table table-responsive">
<caption>
This is the table caption
</caption>
<thead>
<tr>
<th scope="col">First column heading</th>
<th scope="col">Second column heading</th>
</tr>
</thead>
<tbody>
<tr>
<td>First row and first column of data</td>
<td>First row and second column of data</td>
</tr>
<tr>
<td>Second row and first column of data</td>
<td>Second row and second column of data</td>
</tr>
</tbody>
</table>
This creates a striped table with a caption, 2 columns with headings and 2 rows of data (no row headings).
Add row headings
If the first column contains row headings, you must change the first <td>
of each row within the table body to <th scope="row">
.
First column heading | Second column heading |
---|---|
First row heading | First row and first column of data |
Second row heading | Second row and first column of data |
- HTML5
<table class="table table-responsive">
<caption>
This is the table caption
</caption>
<thead>
<tr>
<th scope="col">First column heading</th>
<th scope="col">Second column heading</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">First row heading</th>
<td>First row and first column of data</td>
</tr>
<tr>
<th scope="row">Second row heading</th>
<td>Second row and first column of data</td>
</tr>
</tbody>
</table>
Add headings to the stacked table
Column headings
You can use the .with-headings
class in the <table>
tag, along with the React.js snippet, to make the column headings show within each cell when the table is stacked on smaller screens.
First column heading | Second column heading |
---|---|
First row and first column of data | First row and second column of data |
Second row and first column of data | Second row and second column of data |
- HTML5
- React.js
<table class="table table-responsive with-headings">
<caption>
This is the table caption
</caption>
<thead>
<tr>
<th scope="col">First column heading</th>
<th scope="col">Second column heading</th>
</tr>
</thead>
<tbody>
<tr>
<td>First row and first column of data</td>
<td>First row and second column of data</td>
</tr>
<tr>
<td>Second row and first column of data</td>
<td>Second row and second column of data</td>
</tr>
</tbody>
</table>
import React, { useEffect } from "react";
import "../sass/style.scss";
const enhanceTable = (table) => {
if (table.getAttribute("data-enhanced")) return;
const heads = Array.from(table.querySelectorAll("thead th, thead td"), ({ innerHTML }) =>
innerHTML.trim()
);
table.querySelectorAll("tbody tr").forEach((row) => {
row.querySelectorAll("th, td").forEach((item, index) => {
item.innerHTML = `<span class='table_mobile'>${heads[index]}:</span><span>${item.innerHTML.trim()}</span>`;
});
});
table.setAttribute("data-enhanced", true);
};
const ResponsiveDemo = ({ children }) => {
useEffect(() => {
document.querySelectorAll("table.table-responsive.with-headings").forEach(enhanceTable);
}, []);
return (
<div className="live-example">
<div className="bccds">
<div className="aui">{children}</div>
</div>
</div>
);
};
export default ResponsiveDemo;
Make the text in the first cell of each row a heading
You can use the .bigger-heading
class in the <table>
tag to make the text in the first cell of each row larger when the table is stacked on smaller screens.
First column heading | Second column heading |
---|---|
First row and first column of data | First row and second column of data |
Second row and first column of data | Second row and second column of data |
- HTML5
<table class="table table-responsive bigger-heading">
<caption>
This is the table caption
</caption>
<thead>
<tr>
<th scope="col">First column heading</th>
<th scope="col">Second column heading</th>
</tr>
</thead>
<tbody>
<tr>
<td>First row and first column of data</td>
<td>First row and second column of data</td>
</tr>
<tr>
<td>Second row and first column of data</td>
<td>Second row and second column of data</td>
</tr>
</tbody>
</table>
Use the .with-headings and .bigger-heading classes in combination
You can use the .with-headings
and .bigger-heading
classes in combination, along with the React.js snippet. This makes the first cell of each row larger, so it acts as a heading, and the column headings show in the following cells, when the table is stacked on smaller screens.
First column heading | Second column heading |
---|---|
First row and first column of data | First row and second column of data |
Second row and first column of data | Second row and second column of data |
- HTML5
- React.js
<table class="table table-responsive with-headings bigger-heading">
<caption>
This is the table caption
</caption>
<thead>
<tr>
<th scope="col">First column heading</th>
<th scope="col">Second column heading</th>
</tr>
</thead>
<tbody>
<tr>
<td>First row and first column of data</td>
<td>First row and second column of data</td>
</tr>
<tr>
<td>Second row and first column of data</td>
<td>Second row and second column of data</td>
</tr>
</tbody>
</table>
import React, { useEffect } from "react";
import "../sass/style.scss";
const enhanceTable = (table) => {
if (table.getAttribute("data-enhanced")) return;
const heads = Array.from(table.querySelectorAll("thead th, thead td"), ({ innerHTML }) =>
innerHTML.trim()
);
table.querySelectorAll("tbody tr").forEach((row) => {
row.querySelectorAll("th, td").forEach((item, index) => {
item.innerHTML = `<span class='table_mobile'>${heads[index]}:</span><span>${item.innerHTML.trim()}</span>`;
});
});
table.setAttribute("data-enhanced", true);
};
const ResponsiveDemo = ({ children }) => {
useEffect(() => {
document.querySelectorAll("table.table-responsive.with-headings").forEach(enhanceTable);
}, []);
return (
<div className="live-example">
<div className="bccds">
<div className="aui">{children}</div>
</div>
</div>
);
};
export default ResponsiveDemo;
Alternative tables
There are edge cases where a stacked table will cause problems for a user. In these cases, you can use a wrapping or scrolling table instead.
Wrapping table
Use the .table
class in the <table>
tag to make the text wrap in the table, so it stays within the viewport.
First column heading | Second column heading |
---|---|
First row and first column of data | First row and second column of data |
Second row and first column of data | Second row and second column of data |
- HTML5
<table class="table">
<caption>
This is the table caption
</caption>
<thead>
<tr>
<th scope="col">First column heading</th>
<th scope="col">Second column heading</th>
</tr>
</thead>
<tbody>
<tr>
<td>First row and first column of data</td>
<td>First row and second column of data</td>
</tr>
<tr>
<td>Second row and first column of data</td>
<td>Second row and second column of data</td>
</tr>
</tbody>
</table>
Scrolling table
Use the .table-responsive
class in a <div>
tag to make the table scroll horizontally on smaller screens.
First column heading | Second column heading |
---|---|
First row and first column of data | First row and second column of data |
Second row and first column of data | Second row and second column of data |
- HTML5
<div class="table-responsive">
<table class="table">
<caption>
This is the table caption
</caption>
<thead>
<tr>
<th scope="col">First column heading</th>
<th scope="col">Second column heading</th>
</tr>
</thead>
<tbody>
<tr>
<td>First row and first column of data</td>
<td>First row and second column of data</td>
</tr>
<tr>
<td>Second row and first column of data</td>
<td>Second row and second column of data</td>
</tr>
</tbody>
</table>
</div>
Remove stripy rows
Tables are stripy by default. Use the .table-no-stripe
class in the <table>
tag to remove the stripes, so the background is just white.
First column heading | Second column heading |
---|---|
First row and first column of data | First row and second column of data |
Second row and first column of data | Second row and second column of data |
- HTML5
<table class="table table-responsive table-no-stripe">
<caption>
This is the table caption
</caption>
<thead>
<tr>
<th scope="col">First column heading</th>
<th scope="col">Second column heading</th>
</tr>
</thead>
<tbody>
<tr>
<td>First row and first column of data</td>
<td>First row and second column of data</td>
</tr>
<tr>
<td>Second row and first column of data</td>
<td>Second row and second column of data</td>
</tr>
</tbody>
</table>