Tables (or grids as UX designers are calling them) are used to display, manipulate and organise large amounts of data. The grid can be a fairly complex interface element with loads of functionality. An example of where a grid can be suitable is when you are to display an overview of e.g. documents or register posts. Read more about tables/grids in the UX Guidelines.
Use when
You are to display large amounts of data in a structured way
The user needs to be able to sort, search, filter or otherwise manipulate the data
On this page you can find multiple types of grid table component and the style variants:
<divclass="table-responsive"><tableclass="table no-margin"><thead><tr><thscope="col">#</th><thscope="col">First Name</th><thscope="col">Last Name</th><thscope="col">Username</th></tr></thead><tbody><tr><thscope="row">1</th><td>Mark</td><td>Otto</td><td>@mdo</td></tr><tr><thscope="row">2</th><td>Jacob</td><td>Thornton</td><td>@fat</td></tr><tr><thscope="row">3</th><td>Larry</td><td>the Bird</td><td>@twitter</td></tr><tr><thscope="row">4</th><td>Stan</td><td>Lucas</td><td>@mdo</td></tr><tr><thscope="row">5</th><td>Ben</td><td>Johnas</td><td>@fat</td></tr><tr><thscope="row">6</th><td>John</td><td>Snow</td><td>@fb</td></tr></tbody><tfoot><tr><tdcolspan="2">Users listed in this table: <b>6</b></td><tdcolspan="2"><divclass="d-flex justify-content-end"><buttonclass="btn btn-primary mb-0">Confirm</button><buttonclass="btn btn-default mb-0">Cancel</button></div></td></tr></tfoot></table></div>
Plain tables
For plain styling — light padding and no striped rows or horizontal dividers — add the class .table-plain (together with the base class) to any <table>.
<divclass="table-responsive"><tableclass="table table-plain no-margin"><thead><tr><thscope="col">#</th><thscope="col">First Name</th><thscope="col">Last Name</th><thscope="col">Username</th></tr></thead><tbody><tr><thscope="row">1</th><td>Mark</td><td>Otto</td><td>@mdo</td></tr><tr><thscope="row">2</th><td>Jacob</td><td>Thornton</td><td>@fat</td></tr><tr><thscope="row">3</th><td>Larry</td><td>the Bird</td><td>@twitter</td></tr><tr><thscope="row">4</th><td>Stan</td><td>Lucas</td><td>@mdo</td></tr><tr><thscope="row">5</th><td>Ben</td><td>Johnas</td><td>@fat</td></tr><tr><thscope="row">6</th><td>John</td><td>Snow</td><td>@fb</td></tr></tbody><tfoot><tr><tdcolspan="5"><navclass="d-flex justify-content-end"aria-label="Page navigation for the data grid"><ulclass="pagination"><li><labelfor="quantityPerPage">Show per page:</label></li><li><selectclass="quantity mr-8"name="perPage"id="quantityPerPage"><optionselectedvalue="24">6</option><optionvalue="52">18</option><optionvalue="75">32</option><optionvalue="100">64</option></select></li><li><buttonclass="go2first btn"disabledaria-label="go-to-first">Go to first page</button></li><li><buttonclass="prev btn disabled"tabindex="-1"aria-disabled="true"aria-label="Previous">Previous page</button></li><li><b>6</b></li><liclass="of"><span>of</span></li><li><b>367</b></li><li><span>items</span></li><li><buttonclass="next btn"aria-label="Next">Next page</button></li><li><buttonclass="go2last btn"aria-label="go-to-last">Go to lat page</button></li><li><labelclass="ml-8"for="jumpToPage">Jump to page:</label></li><li><inputtype="number"name="pageJump"id="jumpToPage"placeholder="0"size="2"min="1"max="62"></li></ul></nav></td></tr></tfoot></table></div>
For this style you need to add the .has-errorclass to table row tag (<tr>). To indent the error icon just wrap it in container with the .indent-error class, the indent works only for the first table cell.
Create responsive tables by wrapping any .table in .table-responsive to make them scroll horizontally on small devices (under 992px). When viewing on anything larger than 992px wide, you will not see any difference in these tables.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur quis nisi eleifend, sagittis ligula tempor, facilisis ligula. Integer non nunc non tortor faucibus mattis porttitor ac massa vestibulum vel ipsum vitae. Sed fringilla consequat libero, blandit pulvinar metus lobortis sit amet.
Skills:
Manager
Level:
83%
Click to see the error message
Jacob
Thornton
@fat
Validation got interrupted!
Summary:
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur quis nisi eleifend, sagittis ligula tempor, facilisis ligula. Integer non nunc non tortor faucibus mattis porttitor ac massa vestibulum vel ipsum vitae. Sed fringilla consequat libero, blandit pulvinar metus lobortis sit amet.
Skills:
Technician
Level:
70%
Larry
the Bird
@twitter
Summary:
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur quis nisi eleifend, sagittis ligula tempor, facilisis ligula. Integer non nunc non tortor faucibus mattis porttitor ac massa vestibulum vel ipsum vitae. Sed fringilla consequat libero, blandit pulvinar metus lobortis sit amet.
Skills:
Designer
Level:
85%
Stan
Lucas
@mdo
Summary:
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur quis nisi eleifend, sagittis ligula tempor, facilisis ligula. Integer non nunc non tortor faucibus mattis porttitor ac massa vestibulum vel ipsum vitae. Sed fringilla consequat libero, blandit pulvinar metus lobortis sit amet.
Skills:
Developer
Level:
90%
John
Snow
@fb
Summary:
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur quis nisi eleifend, sagittis ligula tempor, facilisis ligula. Integer non nunc non tortor faucibus mattis porttitor ac massa vestibulum vel ipsum vitae. Sed fringilla consequat libero, blandit pulvinar metus lobortis sit amet.
Skills:
Project Owner
Level:
100%
Ben
Johnas
@fat
Summary:
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur quis nisi eleifend, sagittis ligula tempor, facilisis ligula. Integer non nunc non tortor faucibus mattis porttitor ac massa vestibulum vel ipsum vitae. Sed fringilla consequat libero, blandit pulvinar metus lobortis sit amet.
Skills:
Junior Designer
Level:
35%
Selected: 0 out of 6 items
<style>.checkbox.checkbox-outline.custon-checkbox-expandRowinput[type=checkbox] + label::after {
display: block;
width: 1rem;
height: 0.6rem;
top: 0.75rem;
left: 0.4rem;
border: 0;
background-color: var(--caret-default-bg);
-webkit-mask-position: 00;
mask-position: 00;
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-size: 1rem0.6rem;
mask-size: 1rem .6rem;
-webkit-mask-image: url(../assets/img/arrow-large.svg);
mask-image: url(../assets/img/arrow-large.svg);
transform: rotate(0deg);
transition: transform .25s;
}
.checkbox.checkbox-outline.custon-checkbox-expandRowinput[type=checkbox]:checked + label::after {
transform: rotate(180deg);
}
.custom-error-function:focus-visible {
outline: 0.2rem solid var(--radio-checkbox-focus-border-color);
outline-offset: -0.2rem;
}
.custom-error-function:focus-visible.tooltip {
display: block;
}
tr.custom-rowStyletd { pointer-events: none; }
tr.custom-rowStyle.hidden {
display: none;
}
/* Override nth-child colors with manual classes */#demoTabletbodytr.row-even > th,
#demoTabletbodytr.row-even > td {
background-color: var(--table-alt-bg) !important;
}
#demoTabletbodytr.row-odd > th,
#demoTabletbodytr.row-odd > td {
background-color: var(--table-bg) !important;
}
/* Make expandable rows inherit parent row background color */tr.row-odd + tr.custom-rowStyletd {
background-color: var(--table-bg) !important;
}
tr.row-even + tr.custom-rowStyletd {
background-color: var(--table-alt-bg) !important;
}
/* Remove border between active row and its expandable content */tr.active + tr.custom-rowStyle > th,
tr.active + tr.custom-rowStyle > td {
border-top-color: transparent !important;
}
</style><tableid="demoTable"class="table table-active no-margin"><colgroup><colwidth="3.6rem"><colwidth="3.6rem"><col><col><col></colgroup><thead><tr><thclass="no-hover"></th><thscope="col"><divclass="checkbox m-0"><inputtype="checkbox"id="checkbox-00"name="selectAllRow"><labelfor="checkbox-00"></label></div></th><thscope="col">First Name</th><thscope="col">Last Name</th><thscope="col">Username</th></tr></thead><tbody><tr><thscope="row"><divclass="checkbox checkbox-outline custon-checkbox-expandRow m-0"><inputtype="checkbox"id="expandRow-01"name="expandRow"data-target="row-01"><labelfor="expandRow-01"></label></div></th><td><divclass="checkbox m-0"><inputtype="checkbox"id="selectRow-01"name="selectRow"><labelfor="selectRow-01"></label></div></td><td>Mark</td><td>Otto</td><td>@mdo</td></tr><trid="row-01"class="custom-rowStyle table-expandable-content hidden"><tdcolspan="5"class="no-border p-32"><divclass="row"><divclass="col-7"><h4>Summary:</h4><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur quis nisi eleifend, sagittis ligula tempor, facilisis ligula. Integer non nunc non tortor faucibus mattis porttitor ac massa vestibulum vel ipsum vitae. Sed fringilla consequat libero, blandit pulvinar metus lobortis sit amet.</p></div><divclass="col-2 offset-1 d-flex flex-column justify-content-center"><span>Skills: </span><divclass="h2"><b>Manager</b></div></div><divclass="col-2 d-flex flex-column justify-content-center"><span>Level: </span><divclass="h2"><b>83%</b></div></div></div></td></tr><trclass="has-error"><thscope="row"><spanclass="indent-error custom-error-function"data-target="error-row-02"tabindex="0"><spanclass="vismaicon vismaicon-sm vismaicon-filled vismaicon-error"></span><divclass="tooltip tooltip-error"role="tooltip"style="top: -50%; left: calc(100% + 0.8rem);"><divclass="tooltip-inner text-nowrap">
Click to see the error message
</div></div></span><divclass="checkbox checkbox-outline custon-checkbox-expandRow m-0"><inputtype="checkbox"id="expandRow-02"name="expandRow"data-target="row-02"><labelfor="expandRow-02"></label></div></th><td><divclass="checkbox m-0"><inputtype="checkbox"id="selectRow-02"name="selectRow"><labelfor="selectRow-02"></label></div></td><td>Jacob</td><td>Thornton</td><td>@fat</td></tr><trid="error-row-02"class="custom-rowStyle table-expandable-content hidden"><tdcolspan="5"class="no-border"><spanclass="label label-danger">Validation got interrupted!</span></td></tr><trid="row-02"class="custom-rowStyle table-expandable-content hidden"><tdcolspan="5"class="no-border p-32"><divclass="row"><divclass="col-7"><h4>Summary:</h4><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur quis nisi eleifend, sagittis ligula tempor, facilisis ligula. Integer non nunc non tortor faucibus mattis porttitor ac massa vestibulum vel ipsum vitae. Sed fringilla consequat libero, blandit pulvinar metus lobortis sit amet.</p></div><divclass="col-2 offset-1 d-flex flex-column justify-content-center"><span>Skills: </span><divclass="h2"><b>Technician</b></div></div><divclass="col-2 d-flex flex-column justify-content-center"><span>Level: </span><divclass="h2"><b>70%</b></div></div></div></td></tr><trclass="active"><thscope="row"><divclass="checkbox checkbox-outline custon-checkbox-expandRow m-0"><inputtype="checkbox"id="expandRow-03"name="expandRow"data-target="row-03"checked><labelfor="expandRow-03"></label></div></th><td><divclass="checkbox m-0"><inputtype="checkbox"id="selectRow-03"name="selectRow"><labelfor="selectRow-03"></label></div></td><td>Larry</td><td>the Bird</td><td>@twitter</td></tr><trid="row-03"class="custom-rowStyle table-expandable-content"><tdcolspan="5"class="no-border p-32"><divclass="row"><divclass="col-7"><h4>Summary:</h4><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur quis nisi eleifend, sagittis ligula tempor, facilisis ligula. Integer non nunc non tortor faucibus mattis porttitor ac massa vestibulum vel ipsum vitae. Sed fringilla consequat libero, blandit pulvinar metus lobortis sit amet.</p></div><divclass="col-2 offset-1 d-flex flex-column justify-content-center"><span>Skills: </span><divclass="h2"><b>Designer</b></div></div><divclass="col-2 d-flex flex-column justify-content-center"><span>Level: </span><divclass="h2"><b>85%</b></div></div></div></td></tr><tr><thscope="row"><divclass="checkbox checkbox-outline custon-checkbox-expandRow m-0"><inputtype="checkbox"id="expandRow-04"name="expandRow"data-target="row-04"><labelfor="expandRow-04"></label></div></th><td><divclass="checkbox m-0"><inputtype="checkbox"id="selectRow-04"name="selectRow"><labelfor="selectRow-04"></label></div></td><td>Stan</td><td>Lucas</td><td>@mdo</td></tr><trid="row-04"class="custom-rowStyle table-expandable-content hidden"><tdcolspan="5"class="no-border p-32"><divclass="row"><divclass="col-7"><h4>Summary:</h4><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur quis nisi eleifend, sagittis ligula tempor, facilisis ligula. Integer non nunc non tortor faucibus mattis porttitor ac massa vestibulum vel ipsum vitae. Sed fringilla consequat libero, blandit pulvinar metus lobortis sit amet.</p></div><divclass="col-2 offset-1 d-flex flex-column justify-content-center"><span>Skills: </span><divclass="h2"><b>Developer</b></div></div><divclass="col-2 d-flex flex-column justify-content-center"><span>Level: </span><divclass="h2"><b>90%</b></div></div></div></td></tr><trclass=""><thscope="row"><divclass="checkbox checkbox-outline custon-checkbox-expandRow m-0"><inputtype="checkbox"id="expandRow-05"name="expandRow"data-target="row-05"><labelfor="expandRow-05"></label></div></th><td><divclass="checkbox m-0"><inputtype="checkbox"id="selectRow-05"name="selectRow"><labelfor="selectRow-05"></label></div></td><td>John</td><td>Snow</td><td>@fb</td></tr><trid="row-05"class="custom-rowStyle table-expandable-content hidden"><tdcolspan="5"class="no-border p-32"><divclass="row"><divclass="col-7"><h4>Summary:</h4><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur quis nisi eleifend, sagittis ligula tempor, facilisis ligula. Integer non nunc non tortor faucibus mattis porttitor ac massa vestibulum vel ipsum vitae. Sed fringilla consequat libero, blandit pulvinar metus lobortis sit amet.</p></div><divclass="col-2 offset-1 d-flex flex-column justify-content-center"><span>Skills: </span><divclass="h2"><b>Project Owner</b></div></div><divclass="col-2 d-flex flex-column justify-content-center"><span>Level: </span><divclass="h2"><b>100%</b></div></div></div></td></tr><tr><thscope="row"><divclass="checkbox checkbox-outline custon-checkbox-expandRow m-0"><inputtype="checkbox"id="expandRow-06"name="expandRow"data-target="row-06"><labelfor="expandRow-06"></label></div></th><td><divclass="checkbox m-0"><inputtype="checkbox"id="selectRow-06"name="selectRow"><labelfor="selectRow-06"></label></div></td><td>Ben</td><td>Johnas</td><td>@fat</td></tr><trid="row-06"class="custom-rowStyle table-expandable-content hidden"><tdcolspan="5"class="no-border p-32"><divclass="row"><divclass="col-7"><h4>Summary:</h4><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur quis nisi eleifend, sagittis ligula tempor, facilisis ligula. Integer non nunc non tortor faucibus mattis porttitor ac massa vestibulum vel ipsum vitae. Sed fringilla consequat libero, blandit pulvinar metus lobortis sit amet.</p></div><divclass="col-2 offset-1 d-flex flex-column justify-content-center"><span>Skills: </span><divclass="h2"><b>Junior Designer</b></div></div><divclass="col-2 d-flex flex-column justify-content-center"><span>Level: </span><divclass="h2"><b>35%</b></div></div></div></td></tr></tbody><tfoot><tr><tdcolspan="3">Selected: <bid="nbrSelectedItems">0</b> out of <b>6</b> items</td><tdcolspan="2"><divclass="d-flex justify-content-end"><buttonclass="btn btn-primary mb-0">Confirm</button><buttonclass="btn btn-default mb-0">Cancel</button></div></td></tr></tfoot></table><script>
(function() {
const expandRows = document.querySelectorAll('#demoTable [name="expandRow"]');
const tbody = document.querySelector('#demoTable tbody');
functionupdateRowColors() {
const allRows = Array.from(tbody.querySelectorAll('tr'));
let visibleIndex = 0;
allRows.forEach(row => {
if (row.classList.contains('custom-rowStyle')) {
return;
}
if (visibleIndex % 2 === 0) {
row.classList.add('row-odd');
row.classList.remove('row-even');
} else {
row.classList.add('row-even');
row.classList.remove('row-odd');
}
visibleIndex++;
});
}
updateRowColors();
expandRows.forEach(rowTrigger => {
const parentRow = rowTrigger.closest('tr');
rowTrigger.addEventListener('change', () => {
parentRow.classList.toggle('active', rowTrigger.checked);
});
});
})();
</script>