Data table
The data table can be used for displaying data in a structured form. It can be extended with functions and various kinds of content based on the use case.
Data tables are meant to display big chunks of data enabling you to include certain data manipulation elements alongside the data itself.
The component consists of 2 elements: a flix-data-table-wrapper
and the flix-data-table
itself.
Both elements are equally important for the modifiers to work properly.
Modifiers
These are are the available class modifiers for each element:
Wrapper modifiers
flix-data-table-wrapper--collapsed
- Makes the table width smaller by adapting to its content instead of filling the entire available horizontal space.
flix-data-table-wrapper--responsive
- Triggers a responsive horizontal scroll on screens bellow `sm` breakpoint.
flix-data-table-wrapper--scrollable
- Creates a scrollable table wrapper when vertical space is limited.
Table modifiers
flix-data-table--small
- A smaller table with less paddings in the cells.
flix-data-table--sticky-header
- On scrollable tables, this makes table header stick to the top while scrolling.
flix-data-table--plain
- Removes the "zebra" color effect from the rows.
flix-data-table--show-cols
- Shows dividers for all table columns.
Examples
Complete
The default markup of a data table include the headers in the columns, so the headers must have
scope="col|colgroup"
that identify the data on each column. E.g.: "This column shows Prices".
The footers are optional and can be safely omitted if your use case does not call for them. They are show in this example for completion purposes, and so you have a reference of what they look like and what can be achieved.
The caption is also optional, and it can be used to provide a description for the table. If you wish to add one, it must be included before the table content, but it will be visually rendered bellow.
The th
elements represent a header and can have one of four scopes: "col", "row", "colgroup" or
"rowgroup".
Please check the th element documentation on MDN for more information on header scopes.
The complete example bellow also shows a pager component for controlling the data table, when using
data table controls, add another wrapper data-table-controls
to add the correct space between the
data table component and its controls underneath.
<div class="flix-data-table-controls">
<div class="flix-data-table-wrapper">
<table class="flix-data-table"><caption>Trips: Page 1 of 5</caption><thead class="flix-data-table__header"><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="col">
Name
<button aria-label="Sort rows by name" type="button" class="flix-btn flix-btn--link flix-btn--square flix-btn--sm flix-data-table__sorter-btn">
<flix-icon class="flix-btn__icon" aria-hidden="true" name="arrow-big-down"></flix-icon>
</button>
</th><th class="flix-data-table__th" scope="col">
Time
<button aria-label="Sort rows by time" type="button" class="flix-btn flix-btn--link flix-btn--square flix-btn--sm flix-data-table__sorter-btn">
<flix-icon class="flix-btn__icon" aria-hidden="true" name="arrow-big-up"></flix-icon>
</button>
</th><th class="flix-data-table__th flix-has-text-right" scope="col">
<button aria-label="Sort rows by price" type="button" class="flix-btn flix-btn--link flix-btn--square flix-btn--sm flix-data-table__sorter-btn">
<flix-icon class="flix-btn__icon" aria-hidden="true" name="expand"></flix-icon>
</button>
Price
</th><th class="flix-data-table__th flix-has-text-right" scope="col">
<button aria-label="Sort rows by seats" type="button" class="flix-btn flix-btn--link flix-btn--square flix-btn--sm flix-data-table__sorter-btn">
<flix-icon class="flix-btn__icon" aria-hidden="true" name="expand"></flix-icon>
</button>
Seats
</th><th class="flix-data-table__th" scope="col">
Options
</th></tr></thead><tbody class="flix-data-table__body"><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">AB 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">BC 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">CD 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">DE 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">EF 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">FG 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">GH 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr></tbody><tfoot class="flix-data-table__footer"><tr class="flix-data-table__row"><th class="flix-data-table__td" scope="row">Totals</th><td class="flix-data-table__td"></td><td class="flix-data-table__td flix-has-text-right">1399.93€</td><td class="flix-data-table__td flix-has-text-right">203</td><td class="flix-data-table__td"></td></tr></tfoot></table>
</div>
<nav class="flix-pager" aria-label="Data table pagination">
<ul class="flix-pager__list">
<li class="flix-pager__item">
<button class="flix-pager__link flix-pager__link--prev flix-pager__link--disabled" aria-disabled="true" disabled="">
<span class="flix-sr-only">Previous page</span>
</button>
</li>
<li class="flix-pager__item">
<button type="button" class="flix-pager__link" aria-current="page">
1
</button>
</li>
<li class="flix-pager__item">
<button type="button" class="flix-pager__link">
2
</button>
</li>
<li class="flix-pager__item">
<button type="button" class="flix-pager__link">
3
</button>
</li>
<li class="flix-pager__item">
<button type="button" class="flix-pager__link">
4
</button>
</li>
<li class="flix-pager__item">
<button type="button" class="flix-pager__link">
5
</button>
</li>
<li class="flix-pager__item">
<button type="button" class="flix-pager__link flix-pager__link--next">
<span class="flix-sr-only">Next page</span>
</button>
</li>
</ul>
</nav>
</div>
Plain
The plain modifier should be applied to the data table element and removes the "zebra" color effect from the rows.
<div class="flix-data-table-wrapper">
<table class="flix-data-table flix-data-table--plain"><thead class="flix-data-table__header"><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="col">Name</th><th class="flix-data-table__th" scope="col">Time</th><th class="flix-data-table__th" scope="col">Price</th><th class="flix-data-table__th" scope="col">Seats</th><th class="flix-data-table__th" scope="col">Options</th></tr></thead><tbody class="flix-data-table__body"><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">AB 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td">22.99€</td><td class="flix-data-table__td">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">BC 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td">22.99€</td><td class="flix-data-table__td">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">CD 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td">22.99€</td><td class="flix-data-table__td">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">DE 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td">22.99€</td><td class="flix-data-table__td">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">EF 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td">22.99€</td><td class="flix-data-table__td">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">FG 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td">22.99€</td><td class="flix-data-table__td">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">GH 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td">22.99€</td><td class="flix-data-table__td">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr></tbody><tfoot class="flix-data-table__footer"><tr class="flix-data-table__row"><th class="flix-data-table__td" scope="row">Totals</th><td class="flix-data-table__td"></td><td class="flix-data-table__td">1399.93€</td><td class="flix-data-table__td">203</td><td class="flix-data-table__td"></td></tr></tfoot></table>
</div>
Selectable
To create selectable rows you must include at least one column with a small checkbox, that is usually the first column. The checkbox enables keyboard users to easily select the rows by focusing on their respective checkboxes.
To toggle selected rows pay attention to the following:
- You may also add a click handler to toggle the row selection when the user clicks the row element, but you MUST always allow users to select the rows with only the keyboard, this is usually done with the small checkboxes that should be clearly labelled;
- Ensure the "checked" state of the checkbox and the "selected" state of the row are kept in sync. If their states do not match it can lead to user confusion, specially for screen reader users.
- The selected rows must have
aria-selected="true"
attribute for screen readers. The unselected rows may have "false" value on this attribute, but this is not required. - Add
flix-data-table__row--selected
modifier to the row element to show it in the highlighted color.
<div class="flix-data-table-wrapper">
<table class="flix-data-table"><thead class="flix-data-table__header"><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="col">
<div class="flix-checkbox flix-checkbox--sm flix-checkbox--no-label">
<input class="flix-checkbox__input" type="checkbox" id="example-table-checkbox-all" value="all"/>
<label class="flix-checkbox__label" for="example-table-checkbox-all">
<span class="flix-sr-only">Select all rows</span>
</label>
</div>
</th><th class="flix-data-table__th" scope="col">Name</th><th class="flix-data-table__th" scope="col">Time</th><th class="flix-data-table__th flix-has-text-right" scope="col">Price</th><th class="flix-data-table__th flix-has-text-right" scope="col">Seats</th><th class="flix-data-table__th" scope="col">Options</th></tr></thead><tbody class="flix-data-table__body"><tr class="flix-data-table__row"><td class="flix-data-table__td">
<div class="flix-checkbox flix-checkbox--sm flix-checkbox--no-label">
<input class="flix-checkbox__input" type="checkbox" id="example-table-checkbox-0" value="0"/>
<label class="flix-checkbox__label" for="example-table-checkbox-0">
<span class="flix-sr-only">Select row AB 123</span>
</label>
</div>
</td><th class="flix-data-table__th" scope="row">AB 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><td class="flix-data-table__td">
<div class="flix-checkbox flix-checkbox--sm flix-checkbox--no-label">
<input class="flix-checkbox__input" type="checkbox" id="example-table-checkbox-1" value="1"/>
<label class="flix-checkbox__label" for="example-table-checkbox-1">
<span class="flix-sr-only">Select row BC 123</span>
</label>
</div>
</td><th class="flix-data-table__th" scope="row">BC 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row flix-data-table__row--selected" aria-selected="true"><td class="flix-data-table__td">
<div class="flix-checkbox flix-checkbox--sm flix-checkbox--no-label">
<input class="flix-checkbox__input" type="checkbox" id="example-table-checkbox-2" checked="" value="2"/>
<label class="flix-checkbox__label" for="example-table-checkbox-2">
<span class="flix-sr-only">Select row CD 123</span>
</label>
</div>
</td><th class="flix-data-table__th" scope="row">CD 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><td class="flix-data-table__td">
<div class="flix-checkbox flix-checkbox--sm flix-checkbox--no-label">
<input class="flix-checkbox__input" type="checkbox" id="example-table-checkbox-3" value="3"/>
<label class="flix-checkbox__label" for="example-table-checkbox-3">
<span class="flix-sr-only">Select row DE 123</span>
</label>
</div>
</td><th class="flix-data-table__th" scope="row">DE 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><td class="flix-data-table__td">
<div class="flix-checkbox flix-checkbox--sm flix-checkbox--no-label">
<input class="flix-checkbox__input" type="checkbox" id="example-table-checkbox-4" value="4"/>
<label class="flix-checkbox__label" for="example-table-checkbox-4">
<span class="flix-sr-only">Select row EF 123</span>
</label>
</div>
</td><th class="flix-data-table__th" scope="row">EF 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row flix-data-table__row--selected" aria-selected="true"><td class="flix-data-table__td">
<div class="flix-checkbox flix-checkbox--sm flix-checkbox--no-label">
<input class="flix-checkbox__input" type="checkbox" id="example-table-checkbox-5" checked="" value="5"/>
<label class="flix-checkbox__label" for="example-table-checkbox-5">
<span class="flix-sr-only">Select row FG 123</span>
</label>
</div>
</td><th class="flix-data-table__th" scope="row">FG 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><td class="flix-data-table__td">
<div class="flix-checkbox flix-checkbox--sm flix-checkbox--no-label">
<input class="flix-checkbox__input" type="checkbox" id="example-table-checkbox-6" value="6"/>
<label class="flix-checkbox__label" for="example-table-checkbox-6">
<span class="flix-sr-only">Select row GH 123</span>
</label>
</div>
</td><th class="flix-data-table__th" scope="row">GH 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr></tbody></table>
</div>
Sortable
Sorting the rows can be done via the column headers. You can add a button with arrow icons next to the headers you want to sort, and then attach your click handlers to this button.
- The buttons must be correctly labelled and identified as "Sort by ..." for screen reader users.
- Add the
flix-data-table__sorter-btn
class name to the sorting button to fix the label and icon alignemnt. - The button can be added before or after the label, depending on your use case.
You can also use the alignment helpers to align the content of the cells as you prefer.
The example bellow also shows the effect of the flix-data-table--small
modifier applied to the
table to make the cells smaller.
<div class="flix-data-table-wrapper">
<table class="flix-data-table flix-data-table--small"><caption>Trips: Page 1 of 5</caption><thead class="flix-data-table__header"><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="col">
Name
<button aria-label="Sort rows by name" type="button" class="flix-btn flix-btn--link flix-btn--square flix-btn--sm flix-data-table__sorter-btn">
<flix-icon class="flix-btn__icon" aria-hidden="true" name="arrow-big-down"></flix-icon>
</button>
</th><th class="flix-data-table__th" scope="col">
Time
<button aria-label="Sort rows by time" type="button" class="flix-btn flix-btn--link flix-btn--square flix-btn--sm flix-data-table__sorter-btn">
<flix-icon class="flix-btn__icon" aria-hidden="true" name="arrow-big-up"></flix-icon>
</button>
</th><th class="flix-data-table__th flix-has-text-right" scope="col">
<button aria-label="Sort rows by price" type="button" class="flix-btn flix-btn--link flix-btn--square flix-btn--sm flix-data-table__sorter-btn">
<flix-icon class="flix-btn__icon" aria-hidden="true" name="expand"></flix-icon>
</button>
Price
</th><th class="flix-data-table__th flix-has-text-right" scope="col">
<button aria-label="Sort rows by seats" type="button" class="flix-btn flix-btn--link flix-btn--square flix-btn--sm flix-data-table__sorter-btn">
<flix-icon class="flix-btn__icon" aria-hidden="true" name="expand"></flix-icon>
</button>
Seats
</th><th class="flix-data-table__th" scope="col">
Options
</th></tr></thead><tbody class="flix-data-table__body"><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">AB 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">BC 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">CD 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">DE 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">EF 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">FG 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">GH 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr></tbody><tfoot class="flix-data-table__footer"><tr class="flix-data-table__row"><th class="flix-data-table__td" scope="row">Totals</th><td class="flix-data-table__td"></td><td class="flix-data-table__td flix-has-text-right">1399.93€</td><td class="flix-data-table__td flix-has-text-right">203</td><td class="flix-data-table__td"></td></tr></tfoot></table>
</div>
Scrollable and Sticky Header
To make a scrollable data table you can use the following modifiers:
flix-data-table-wrapper--scrollable
- Adds this modifier on the wrapper to make the data table scrollable.
- A fixed height or max height for the wrapper will make it work as the "window" while the user can scroll the long data table inside.
flix-data-table--sticky-header
- Optionally add this modifier to the data table element to make the header stick to the top while scrolling.
<div class="flix-data-table-wrapper flix-data-table-wrapper--scrollable" style="height:300px">
<table class="flix-data-table flix-data-table--sticky-header"><thead class="flix-data-table__header"><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="col">
Name
<button aria-label="Sort rows by name" type="button" class="flix-btn flix-btn--link flix-btn--square flix-btn--sm flix-data-table__sorter-btn">
<flix-icon class="flix-btn__icon" aria-hidden="true" name="arrow-big-down"></flix-icon>
</button>
</th><th class="flix-data-table__th" scope="col">
Time
<button aria-label="Sort rows by time" type="button" class="flix-btn flix-btn--link flix-btn--square flix-btn--sm flix-data-table__sorter-btn">
<flix-icon class="flix-btn__icon" aria-hidden="true" name="arrow-big-up"></flix-icon>
</button>
</th><th class="flix-data-table__th flix-has-text-right" scope="col">
<button aria-label="Sort rows by price" type="button" class="flix-btn flix-btn--link flix-btn--square flix-btn--sm flix-data-table__sorter-btn">
<flix-icon class="flix-btn__icon" aria-hidden="true" name="expand"></flix-icon>
</button>
Price
</th><th class="flix-data-table__th flix-has-text-right" scope="col">
<button aria-label="Sort rows by seats" type="button" class="flix-btn flix-btn--link flix-btn--square flix-btn--sm flix-data-table__sorter-btn">
<flix-icon class="flix-btn__icon" aria-hidden="true" name="expand"></flix-icon>
</button>
Seats
</th><th class="flix-data-table__th" scope="col">
Options
</th></tr></thead><tbody class="flix-data-table__body"><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">AB 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">BC 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">CD 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">DE 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">EF 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">FG 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">GH 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr></tbody><tfoot class="flix-data-table__footer"><tr class="flix-data-table__row"><th class="flix-data-table__td" scope="row">Totals</th><td class="flix-data-table__td"></td><td class="flix-data-table__td flix-has-text-right">1399.93€</td><td class="flix-data-table__td flix-has-text-right">203</td><td class="flix-data-table__td"></td></tr></tfoot></table>
</div>
Collapsed
The flix-data-table-wrapper--collapsed
modifier can be added to the wrapper to stop the data table
from expanding all the way. This way the data table will only occupy as much space as it needs
depending on its content.
This is useful for data tables with fewer columns where horizontal space is limited.
<div class="flix-data-table-wrapper flix-data-table-wrapper--collapsed">
<table class="flix-data-table"><caption>Trips: Page 1 of 5</caption><thead class="flix-data-table__header"><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="col">
Name
<button aria-label="Sort rows by name" type="button" class="flix-btn flix-btn--link flix-btn--square flix-btn--sm flix-data-table__sorter-btn">
<flix-icon class="flix-btn__icon" aria-hidden="true" name="arrow-big-down"></flix-icon>
</button>
</th><th class="flix-data-table__th" scope="col">
Time
<button aria-label="Sort rows by time" type="button" class="flix-btn flix-btn--link flix-btn--square flix-btn--sm flix-data-table__sorter-btn">
<flix-icon class="flix-btn__icon" aria-hidden="true" name="arrow-big-up"></flix-icon>
</button>
</th><th class="flix-data-table__th flix-has-text-right" scope="col">
<button aria-label="Sort rows by price" type="button" class="flix-btn flix-btn--link flix-btn--square flix-btn--sm flix-data-table__sorter-btn">
<flix-icon class="flix-btn__icon" aria-hidden="true" name="expand"></flix-icon>
</button>
Price
</th><th class="flix-data-table__th flix-has-text-right" scope="col">
<button aria-label="Sort rows by seats" type="button" class="flix-btn flix-btn--link flix-btn--square flix-btn--sm flix-data-table__sorter-btn">
<flix-icon class="flix-btn__icon" aria-hidden="true" name="expand"></flix-icon>
</button>
Seats
</th><th class="flix-data-table__th" scope="col">
Options
</th></tr></thead><tbody class="flix-data-table__body"><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">AB 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">BC 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">CD 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">DE 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr></tbody><tfoot class="flix-data-table__footer"><tr class="flix-data-table__row"><th class="flix-data-table__td" scope="row">Totals</th><td class="flix-data-table__td"></td><td class="flix-data-table__td flix-has-text-right">799.96€</td><td class="flix-data-table__td flix-has-text-right">116</td><td class="flix-data-table__td"></td></tr></tfoot></table>
</div>
Show columns and column groups
flix-data-table--show-cols
- When applied to the data table enables dividers for the columns..
flix-data-table__col--divider
- Adds a divider for the respective column.
flix-data-table__col--collapsed
- Makes the respective column "collapsed" so it is only as wide as the content in it.
<div class="flix-data-table-wrapper">
<table class="flix-data-table flix-data-table--show-cols"><thead class="flix-data-table__header"><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="col">Name</th><th class="flix-data-table__th" scope="col">Time</th><th class="flix-data-table__th flix-has-text-right" scope="col">Price</th><th class="flix-data-table__th flix-has-text-right" scope="col">Seats</th><th class="flix-data-table__th" scope="col">Options</th></tr></thead><tbody class="flix-data-table__body"><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">AB 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">BC 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">CD 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">DE 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr></tbody><tfoot class="flix-data-table__footer"><tr class="flix-data-table__row"><th class="flix-data-table__td" scope="row">Totals</th><td class="flix-data-table__td"></td><td class="flix-data-table__td flix-has-text-right">1399.93€</td><td class="flix-data-table__td flix-has-text-right">203</td><td class="flix-data-table__td"></td></tr></tfoot></table>
</div>
The data table also supports column groups and adds two modifiers for the individual columns.
The colgroup
element should be added inside the table element, after the caption element if you
have one, and before any thead, tbody or tfoot elements.
Check the colgroup documentation on MDN for more information on how to configure columns with this element.
<div class="flix-data-table-wrapper">
<table class="flix-data-table"><colgroup>
<col class="flix-data-table__col flix-data-table__col--divider flix-data-table__col--collapsed"/>
<col class="flix-data-table__col"/>
<col class="flix-data-table__col"/>
<col class="flix-data-table__col"/>
<col class="flix-data-table__col"/>
<col class="flix-data-table__col flix-data-table__col--divider"/>
</colgroup><thead class="flix-data-table__header"><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="col">
<div class="flix-checkbox flix-checkbox--sm flix-checkbox--no-label">
<input class="flix-checkbox__input" type="checkbox" id="example-table-checkbox-all" value="all"/>
<label class="flix-checkbox__label" for="example-table-checkbox-all">
<span class="flix-sr-only">Select all rows</span>
</label>
</div>
</th><th class="flix-data-table__th" scope="col">
Name
<button aria-label="Sort rows by name" type="button" class="flix-btn flix-btn--link flix-btn--square flix-btn--sm flix-data-table__sorter-btn">
<flix-icon class="flix-btn__icon hydrated" aria-hidden="true" name="arrow-big-down" role="img"></flix-icon>
</button>
</th><th class="flix-data-table__th" scope="col">
Time
<button aria-label="Sort rows by time" type="button" class="flix-btn flix-btn--link flix-btn--square flix-btn--sm flix-data-table__sorter-btn">
<flix-icon class="flix-btn__icon hydrated" aria-hidden="true" name="arrow-big-up" role="img"></flix-icon>
</button>
</th><th class="flix-data-table__th flix-has-text-right" scope="col">
<button aria-label="Sort rows by price" type="button" class="flix-btn flix-btn--link flix-btn--square flix-btn--sm flix-data-table__sorter-btn">
<flix-icon class="flix-btn__icon hydrated" aria-hidden="true" name="expand" role="img"></flix-icon>
</button>
Price
</th><th class="flix-data-table__th flix-has-text-right" scope="col">
<button aria-label="Sort rows by seats" type="button" class="flix-btn flix-btn--link flix-btn--square flix-btn--sm flix-data-table__sorter-btn">
<flix-icon class="flix-btn__icon hydrated" aria-hidden="true" name="expand" role="img"></flix-icon>
</button>
Seats
</th><th class="flix-data-table__th" scope="col">
Options
</th></tr></thead><tbody class="flix-data-table__body"><tr class="flix-data-table__row"><td class="flix-data-table__td">
<div class="flix-checkbox flix-checkbox--sm flix-checkbox--no-label">
<input class="flix-checkbox__input" type="checkbox" id="example-table-checkbox-0" value="0"/>
<label class="flix-checkbox__label" for="example-table-checkbox-0">
<span class="flix-sr-only">Select row AB 123</span>
</label>
</div>
</td><th class="flix-data-table__th" scope="row">AB 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><td class="flix-data-table__td">
<div class="flix-checkbox flix-checkbox--sm flix-checkbox--no-label">
<input class="flix-checkbox__input" type="checkbox" id="example-table-checkbox-1" value="1"/>
<label class="flix-checkbox__label" for="example-table-checkbox-1">
<span class="flix-sr-only">Select row BC 123</span>
</label>
</div>
</td><th class="flix-data-table__th" scope="row">BC 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row flix-data-table__row--selected" aria-selected="true"><td class="flix-data-table__td">
<div class="flix-checkbox flix-checkbox--sm flix-checkbox--no-label">
<input class="flix-checkbox__input" type="checkbox" id="example-table-checkbox-2" checked="" value="2"/>
<label class="flix-checkbox__label" for="example-table-checkbox-2">
<span class="flix-sr-only">Select row CD 123</span>
</label>
</div>
</td><th class="flix-data-table__th" scope="row">CD 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr></tbody></table>
</div>
Complex headers
You can create complex table headers by making use of the colspan
and rowspan
attributes.
Check the Column and row spanning example on MDN for more information on how to use these attributes and what do they mean.
They can also be applied to footers if you have a summary for only a set number of columns but not all of them.
<div class="flix-data-table-wrapper">
<table class="flix-data-table"><caption>Trips: Page 1 of 5</caption><thead class="flix-data-table__header"><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="col" rowspan="2">
Name
<button aria-label="Sort rows by name" type="button" class="flix-btn flix-btn--link flix-btn--square flix-btn--sm flix-data-table__sorter-btn">
<flix-icon class="flix-btn__icon hydrated" aria-hidden="true" name="arrow-big-down" role="img"></flix-icon>
</button>
</th><th class="flix-data-table__th" scope="colgroup" colSpan="3">
Availability
</th><th class="flix-data-table__th" scope="col" rowspan="2">
Options
</th></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="col">
Time
<button aria-label="Sort rows by time" type="button" class="flix-btn flix-btn--link flix-btn--square flix-btn--sm flix-data-table__sorter-btn">
<flix-icon class="flix-btn__icon hydrated" aria-hidden="true" name="arrow-big-up" role="img"></flix-icon>
</button>
</th><th class="flix-data-table__th flix-has-text-right" scope="col">
<button aria-label="Sort rows by price" type="button" class="flix-btn flix-btn--link flix-btn--square flix-btn--sm flix-data-table__sorter-btn">
<flix-icon class="flix-btn__icon hydrated" aria-hidden="true" name="expand" role="img"></flix-icon>
</button>
Price
</th><th class="flix-data-table__th flix-has-text-right" scope="col">
<button aria-label="Sort rows by seats" type="button" class="flix-btn flix-btn--link flix-btn--square flix-btn--sm flix-data-table__sorter-btn">
<flix-icon class="flix-btn__icon hydrated" aria-hidden="true" name="expand" role="img"></flix-icon>
</button>
Seats
</th></tr></thead><tbody class="flix-data-table__body"><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">AB 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">BC 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">CD 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">DE 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">EF 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">FG 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr><tr class="flix-data-table__row"><th class="flix-data-table__th" scope="row">GH 123</th><td class="flix-data-table__td">07:05h</td><td class="flix-data-table__td flix-has-text-right">22.99€</td><td class="flix-data-table__td flix-has-text-right">29</td><td class="flix-data-table__td"><a class="flix-link" href="#">Details</a></td></tr></tbody><tfoot class="flix-data-table__footer"><tr class="flix-data-table__row"><th class="flix-data-table__td flix-has-text-right" scope="row" colSpan="2">Totals:</th><td class="flix-data-table__td flix-has-text-right">1399.93€</td><td class="flix-data-table__td flix-has-text-right">203</td><td class="flix-data-table__td"></td></tr></tfoot></table>
</div>