Table
A Table is a structural component used to arrange data in rows and columns to facilitate the comparison, analysis and management of information.
Guidelines
When to use tables
In order to support the scanning and interpretation of information, the content within Tables needs to be well-structured and optimized for readability. For that reason, Tables should be avoided if the space is limited, if the interaction with their information is too complex, or if the data cannot be easily categorized. Additionally, consider alternative presentations for standalone information, or when detailed analysis isn't the primary objective.
When to use:
- When users need a systematic representation of information that allows them to compare and analyze multiple data points across different categories.
- When users need to perform specific actions to manipulate items within a dataset, such as editing, deleting, or organizing.
- When users can benefit from the ability to sort or filter data dynamically in order to extract conclusions.
When not to use:
- When the interaction with the data is too complex (e.g. there are interdependencies between data points).
- When space is constrained. Please find alternative methods to display the information in case the readability of the Table content is compromised.
- When the goal is to create simple, non-data-centric layouts. Opt for lists or other components in case there aren’t multiple data points to compare, and the information doesn’t require manipulation (sorting, filtering).
- When the user's primary goal is to obtain a high-level overview rather than detailed, more granular, analysis of the information. Alternative visualization methods such as summaries, charts, or lists may be more suitable for providing an overview.
- When information is standalone and doesn't require side-by-side comparison, consider using text, lists, or Cards instead.
Specifications
Header (optional)
Tables can feature a header section with elements such as a visible caption or actions that can be applied to Table rows in bulk.Caption
A caption provides a clear and concise description of the contents and the purpose of the Table. It is key for accessibility, and must always be provided for users of assistive technology. The caption can be visually hidden if a visible caption is not needed (e.g. if there is a heading above the Table that serves as a title).Actions (optional)
Actions that can be applied to all the items within a Table should be made available from the header.Selection (optional)
Row selection can be enabled to allow targeting the items that will be affected by Table actions. The checkbox available at the heading row level allows selecting all Table items at once, while individual checkboxes allow the selection of independent rows. A custom indicator of the number of selected rows can be included in the Table’s header for visibility (See custom header text).Headings
Tables can feature column headings (most commonly), row headings, or both. Headings are used to describe the type of information or the category of the data contained by the list of elements they label. Column headings are required.Sorting (optional)
Sorting allows users to organize data in an ascending or descending order according to specific criteria (e.g. alphabetically). It facilitates the analysis of data, identification of patterns, and comparison of values within Tables.Cell
Table cells are individual units of information, organized at the intersection of rows and columns. They can contain any sort of content, from simple text to iconography, images and components in any necessary order or combination.Footer (optional)
Tables can feature an optional footer to organize adjacent Table information or actions (e.g. pagination). The configuration and contents of the Table footer are fully customizable.
Table and column width
Tables will occupy the full width of the area assigned to them in a layout. The available space will be distributed across Table columns evenly, depending on the data they contain.
Tables are optimized for readability by default, but there might be special cases where adjustments might be needed. If so, it is possible to adjust the width of individual columns to distribute space more intentionally:
Column and row headings
Tables can display column headings, row headings, or both.
Column headings represent the category or type of information contained in each Table column. They are essential for the quick identification of the Table’s content.
Row headings are useful when there’s a need to further categorize or label the data presented in individual or sets of rows. In Tables with many items, row headings can serve as navigation aids, allowing users to quickly jump to specific sections or categories within the data structure. Please note that you might or might not include a column heading to give a title to the row headings column.
Cell customization
Table cells can include combinations of any type of content: from text with end or start icons, to images or even components. This level of cell customization allows covering a wide range of presentational and interactive use cases like, for example, the introduction of inline, row actions:
Types
Table with vertical borders
By default, the Table component will only display horizontal borders to separate rows and rely on spacing to create columns. Vertical borders can be added in data-heavy Tables, where the cell content is too clumped and mistakes might be made when interpreting the data.[1]
Common scenarios where the use of vertical borders is recommended include: when presenting data with lengthy textual descriptions or explanations alongside numerical values, in Tables with a long list of narrow columns, or when combining data with different horizontal alignment (see example below).
Table with sorting
Sorting allows reordering all the items included in a Table based on the values of one of its columns. Any number of columns can be sortable, but data can only be sorted by one column at a time.
Table with row selection
Enable row selection when the same action(s) can be applied to all of the items in a Table. We recommend including an indicator of the amount of selected items within the Table’s header.
When selection is enabled, users can pick out rows individually, or use the checkbox included at the heading level to select or deselect all Table items at once:
Interaction states
Heading sorting states
Heading cells that include sorting functionality display a hovered state, an active state when clicked or tapped, and a focused style after having been activated and until any other interaction takes place.
- Default
- Hover
- Active
- Focused
Row selection states
In Tables where selection is available, rows present the following styles:
- Default
- Selected
The heading-level checkbox, which facilitates the simultaneous selection and deselection of all Table items, will present an indeterminate state in case some items remain unselected. Please note that, while Table rows display a selected state, only the checkboxes are interactive (See 2).
Best practices
Table actions
It is possible to use the header to provide actions that can be applied to all Table items. Enabling selection will allow users to target the Table items to be manipulated.
- Use normal or quiet Buttons to represent Table actions.
- Use any of the Button actions (neutral, progressive, and destructive)
- Use primary Buttons to represent Table actions, since they might compete with main page actions. (Exceptions might apply).
- Use icon-only buttons to represent Table actions, since they might complicate understanding. Exceptions do apply, e.g. in cases where space is scarce, or when they are used to trigger related actions in a menu or modal.
Make sure to follow the button and groups of buttons usage recommendations when defining the best way to represent actions, keeping the Table’s external context in mind too.
Inline actions
It is possible to customize Table cells, and include inline actions in them that allow manipulating the data of individual rows. Although exceptions might apply, we only recommend using inline actions in Tables that will display fewer rows (less than 5) by default.
- Use the cell slot to provide inline actions in Tables with fewer items.
- Use inline actions in Tables with more than 5 rows. Instead, use the header slot to provide bulk actions and enable selection.
Table width
Achieving the optimal readability of Table content should be the guiding factor when defining the width of a Table within a composition. Strive to balance information density with legibility, ensuring that Tables occupy just the appropriate amount of space.
Avoid using Tables in narrow spaces. This can cause their content to wrap too tightly, or unnecessarily trigger the Table’s default horizontal scroll. At the same time, refrain from overstretching Tables to make them fit wider layouts: embedding too much white space within cells will make their information harder to parse and compare.
- Use Tables in layouts where they’ll have enough space to display all relevant information clearly and comprehensively.
- Use Tables within limited spaces, where their content might have to adjust to the point of compromising readability.
- Use Tables in wide areas, where they’ll overstretch, complicating the parsing and comparison of information.
Content
Table caption
The caption provides a clear and succinct description of the content and purpose of a Table. It can be visually hidden, or replaced by an external title if a design either requires or allows it. Regardless of its visibility, a caption should always be defined in the Table’s code in order to provide context for users of assistive technology.[2]
Visible or not, make sure the caption conveys the Table's content and context in a concise and accurate way.
To keep captions readable, don’t exceed a line length of 75 characters. You can apply a maximum width to the caption if necessary in order to follow this recommendation.
Heading content
Do not rely on iconography alone to represent categorical information in headings, as it might be hard to understand based on the content of the surrounding cells alone:
Cell content alignment
Except for numbers, text within cells should be aligned left or right, according to the directionality of the user’s interface language.
Numbers that express quantities should always be aligned right, regardless of the directionality of the user’s interface language. This helps readers make easier comparisons of values when scanning down columns. For consistency and ease of understanding, the alignment of headings should always match the alignment of the data.[1]
Keyboard navigation
Key | Function |
---|---|
Tab | It moves the focus to the next interactive element within the Table. |
Shift+Tab | It moves the focus to the previous interactive element within the Table. |
Up arrow, Down arrow | For assistive technology users, these keys move between the column cells. |
Left arrow, Right arrow | For assistive technology users, these keys move between the row cells. |
References
- Web Typography: Designing Tables to be Read, Not Looked At by Richard Rutter
- Inclusive Components: Data Tables, by Heydon Pickering
Demos
Configurable
Athlete | Nation | Rank | Time |
---|---|---|---|
Ken McArthur | South Africa | 1 | 2:36:54.8 |
Christian Gitsham | South Africa | 2 | 2:37:52.0 |
Gaston Strobino | United States | 3 | 2:38:42.4 |
Shizo Kanakuri | Japan | 36 | 54:08:06:05:32:20.3 |
Name | Value |
---|---|
Props | |
caption | |
hideCaption | |
useRowHeaders | |
showVerticalBorders | |
Slots | |
header | |
footer | |
View | |
Reading direction |
With custom-sized columns
The TableColumn type has optional properties for width
and minWidth
so you can customize each column's size. Include the units, e.g. '120px'
or '100%'
.
Wave | Years | Overview | Main figures |
---|---|---|---|
First wave | Late 19th to early 20th century | Focused on women's suffrage and legal rights, addressing inequalities in the public sphere. | Susan B. Anthony, Elizabeth Cady Stanton |
Second wave | 1960s to 1980s | Centered on women's liberation and social equality, addressing issues such as reproductive rights, workplace discrimination, and sexual liberation. | Betty Friedan, Gloria Steinem, Simone de Beauvoir |
Third wave | 1990s to early 2000s | Emphasized diversity and intersectionality, addressing issues of race, class, sexuality, and gender identity. Advocated for inclusivity and challenging stereotypes. | bell hooks, Kimberlé Crenshaw, Judith Butler |
Fourth wave | Early 2010s to present | Characterized by a focus on the empowerment of women through the use of internet tools, and intersectionality. The fourth wave seeks greater gender equality by focusing on gendered norms and the marginalization of women in society. | Tarana Burke, Chimamanda Ngozi Adichie, Roxane Gay |
With custom cell content
By default, the data provided for a cell will be rendered within it as-is. You can customize the contents of a cell by using the item-[ columnId ]
slots. For example, for a column with the id time
, there is a slot called item-time
. This slot comes with 2 bindings:
item
: the cell contentrow
: data for the entire row
Timestamp | Target | Block parameters | Actions |
---|---|---|---|
16:58, 2023-11-30 | Username1 |
| |
15:16, 2023-11-23 | Username2 |
| |
11:13, 2023-11-12 | Username3 |
|
With custom table elements
You can further customize the layout of your Table by using the thead
, tbody
, and tfoot
slots. Using these slots will override the default implementation of that element within the Table component so you can include your own markup. The example below uses the thead
slot to add th
elements with custom colspan
and rowspan
attributes, and the tfoot
slot to add a <tfoot>
with totals below the <tbody>
.
You can use any combination of these slots. Note that in the example below, even though we are including custom thead
markup, we are still passing in the columns
prop so that the Table component can output the data
in the <tbody>
. Always pass in columns
, unless you are using the slots to override both the <thead>
and <tbody>
.
Cell data is aligned to the start of the cell by default. You can use the following CSS classes to change the alignment of cell data:
cdx-table__table__cell--align-center
: Align content to the center of the cellcdx-table__table__cell--align-end
: Align content to the end of the cell (to the right in LTR and to the left in RTL)cdx-table__table__cell--align-number
: Align content to the right of the cell in both reading directionalities. This is recommended for columns that contain numerical values.
Project | No. of wikis | Users | |
---|---|---|---|
Active | All | ||
wikipedias | 342 | 292249 | 113556337 |
wiktionaries | 193 | 5764 | 7275027 |
wikiquotes | 96 | 2042 | 4261041 |
Total: | 631 | 300055 | 125092405 |
With sorting
To enable sorting, pass in the sort
prop via v-model, and make at least one Table column sortable by adding allowSort: true
to its definition.
You can initialize the sort ref to an empty object if there is no initial sort order, or to an initial sort order as in the Table below, where the initial sort order is { user: 'asc' }
.
WARNING
For translatable interfaces, make sure you also use the sortCaption
prop to provide a translated string for this visually-hidden accessibility helper.
Username1 | de.wikipedia | Bahnstromleitung | 06:12, 2023-12-28 | +9 |
Username2 | commons.wikimedia | Xanthium.jpg | 11:12, 2024-01-02 | -70 |
Username3 | de.wikipedia | Berlin | 16:58, 2024-01-04 | +652 |
Username4 | en.wikipedia | Stability Model | 16:25, 2023-12-14 | +42 |
With selection
To enable row selection, set the useRowSelection
prop to true
, and use v-model to bind the selectedRows
prop.
WARNING
For translatable interfaces, make sure you also use the selectAllLabel
and selectRowLabel
props to provide translated strings for these visually-hidden accessibility helpers.
Name | Status | English verb to agent noun | |
---|---|---|---|
"illustrate" -> "illustrator" | Connected | Failed | |
"listen" -> "listener" | Connected | Passed | |
"mentor" -> "mentor" | Connected | Passed | |
"swim" -> "swimmer" | Connected | Failed |
With selection and sort
To use both row selection and sorting, you must add a unique identifier to each row:
- Import the
TableRowIdentifier
constant from Codex - Add a property to each row object keyed on
TableRowIdentifier
with a unique ID, e.g.[ TableRowIdentifier ]: 'Q123'
Status | English verb to agent noun | ||
---|---|---|---|
"illustrate" -> "illustrator" | Connected | Failed | |
"listen" -> "listener" | Connected | Passed | |
"mentor" -> "mentor" | Connected | Passed | |
"swim" -> "swimmer" | Connected | Failed |
Vue usage
Props
Prop name | Description | Type | Default |
---|---|---|---|
caption (required) | Table caption. Required to support users of assistive technology, but can be visually hidden. | string | |
hideCaption | Whether to visually hide the caption. | boolean | false |
columns | Column definitions. | TableColumn[] | () => [] |
data | Table data. An array of objects, with each object representing the data for a table row. Item keys should align with column IDs, as defined in the columns prop. | TableRow[]|TableRowWithIdentifier[] | () => [] |
useRowHeaders | Whether to use <th> for the first cell in each row. | boolean | false |
showVerticalBorders | Whether vertical borders separating columns should be rendered. | boolean | false |
useRowSelection | Whether to enable row selection. | boolean | false |
selectedRows | An array of selected row indices. Must be bound with v-model:selected-rows .If sorting is also enabled, this will be an array of TableRowIdentifiers. | ( number|string )[] | () => [] |
selectAllLabel | Label for the "select all rows" checkbox. This label is visually hidden but needed for assistive technology. | string | 'Select all rows' |
selectRowLabel | Label for the "select row" checkboxes. These labels are visually hidden but needed for assistive technology. | func | ( x: number, y:number ) => |
sort | Definition of sort order. Column(s) can be sorted ascending, descending, or not sorted. To display data unsorted initially, set to an empty object initially. Must be bound with v-model:sort | TableSort | () => ( {} ) |
sortCaption | Text that provides additional info for the <caption> element when the column header has sorting is enabled.This text is visually hidden but needed for assistive technology when sort is enabled. | string | ', column headers with buttons are sortable.' |
Events
Event name | Properties | Description |
---|---|---|
update:selectedRows | selectedRows string[] - The new selected rows. | When the selected row(s) changes. |
update:sort | sort Object - The new sort order. | When the sort order changes emit an event to update the sort order. |
Slots
Name | Description | Bindings |
---|---|---|
header | Header content. Not to be confused with <thead>; use the thead slot to customize that. | |
thead | Custom <thead>. | |
tbody | Custom <tbody>. | |
'item-' + column.id | Table cell content, per column. | item any - Data for the cellrow TableRow, TableRowWithIdentifier - Data for the row |
tfoot | Custom <tfoot>. | |
footer | Footer content. Not to be confused with <tfoot>; use the tfoot slot to add that. |
CSS-only version
Markup structure
The CSS-only Table consists of a <table>
element and its child elements, plus some wrapper elements and CSS classes needed to ensure proper styles and accessibility. See the code sample below for details.
Cell data is aligned to the start of the cell by default. You can use the following CSS classes to change the alignment of cell data:
cdx-table__table__cell--align-center
: Align content to the center of the cellcdx-table__table__cell--align-end
: Align content to the end of the cell (to the right in LTR and to the left in RTL)cdx-table__table__cell--align-number
: Align content to the right of the cell in both reading directionalities. This is recommended for columns that contain numerical values.
Note that all cells in a column, including the <th>
in the <thead>
, should have the same text alignment.
Athlete | Nation | Rank | Time |
---|---|---|---|
Ken McArthur | South Africa | 1 | 2:36:54.8 |
Christian Gitsham | South Africa | 2 | 2:37:52.0 |
Gaston Strobino | United States | 3 | 2:38:42.4 |
Shizo Kanakuri | Japan | 36 | 54:08:06:05:32:20.3 |
Visually hidden caption
To visually hide the header's caption, simply do not add it to the header element (<div class="cdx-table__header">
). If you have no other header content, the entire header element can be removed, as in the example below. Make sure to always include the <caption>
element inside the <table>
, which is visually hidden by default.
Project | No. of wikis | Active users | All users |
---|---|---|---|
wikipedias | 342 | 292249 | 113556337 |
wiktionaries | 193 | 5764 | 7275027 |
wikiquotes | 96 | 2042 | 4261041 |
Total: | 631 | 300055 | 125092405 |
Vertical borders
To display vertical borders that separate the columns, apply the cdx-table__table--borders-vertical
class to table element. This class may not cover all use cases, therefore apply additional border styles to the element as needed.
Project | No. of wikis | Users | |
---|---|---|---|
Active | All | ||
wikipedias | 342 | 292249 | 113556337 |
wiktionaries | 193 | 5764 | 7275027 |
wikiquotes | 96 | 2042 | 4261041 |
Total: | 631 | 300055 | 125092405 |
Row headers
In some cases, header information can be found in the top row and first column. All header cells are marked up as th
elements with the appropriate scope
attribute. The scope attribute helps to describe the relationship between header and data cells. Refer to WAI to learn more about Table header row and header column.
Project | No. of wikis | Users | |
---|---|---|---|
Active | All | ||
wikipedias | 342 | 292249 | 113556337 |
wiktionaries | 193 | 5764 | 7275027 |
wikiquotes | 96 | 2042 | 4261041 |
Total: | 631 | 300055 | 125092405 |
With row selection
Row selection can be done without JavaScript by following these steps:
- Use a
<form>
element as the outermost element with the classcdx-table
- Add a submit button to the header to handle the row selection data
- Omit the "select all" checkbox in the
<thead>
- Give each row's checkbox the same
name
and a uniquevalue
Note that the Table below doesn't actually do anything when you click "Sign up" besides submit the form and reload the page.