Octopus relies heavily on tables to display such core product entities as Projects, Tenants, Deployment Targets, Workers, Releases, Variables, and many more. It’s vital to our users that the information presented is easy to digest and act on. Otherwise, setting up and managing their deployments becomes unnecessarily complex.
Tables allow displaying potentially complex data in a structured, easy-to-digest way. They can also scale to large quantities of data (however, we have to consider performance optimizations in those cases to avoid negative impacts on UX).
When to use tables
How we apply tables will vary depending on context, but here are common user goals that tables are best suited for:
- Finding item(s) that meet criteria: Well-structured tables with filtering, ordering, and search enable users to locate what they are looking for quickly.
- Comparing data: tables make it easy to find outliers, analyze trends, and explore relationships between items.
- Taking actions on items: tables simplify management tasks by allowing single and bulk actions on presented items.
Beyond these use cases, tables are ideal for displaying large quantities of data in a structured way, especially in scenarios when each item has more than three characteristics or relationships to other items that need to be portrayed.
Tables vs other ways of presenting data
Tables aren’t the only way to represent data—it’s essential to know when tables are most useful, and when a different mode of data display might be more suitable.
|
Component |
Table |
List |
Card |
|---|---|---|---|
|
Scalability |
Unlimited items |
Unlimited items |
Less than 7 items |
|
Scannability |
✅ Yes |
❌ No |
✅ Yes |
|
Searching |
✅ Yes |
✅ Yes |
❌ No |
|
Single and bulk actions |
✅ Yes |
❌ No |
❌ No |
|
Filtering |
✅ Yes |
❌ No |
❌ No |
|
Controlling display density |
✅ Yes |
✅ Yes |
✅ Yes |
|
Controlling data displayed |
✅ Yes |
❌ No |
❌ No |
Tables vs Lists
Lists don’t support data comparison and manipulation. While it’s possible to display many entries using a list, users will evaluate each entry individually because of the visual representation. When thinking about scalability, reconsider list usage.
Lists are helpful when you want to display an entity with fewer than three additional item characteristics (or associated actions). For example, a list of Spaces with only Space names listed or a list of users with only names and emails listed.
Tables vs Cards
Cards don’t support data comparison and manipulation either. Scalability is also an issue as reading through cards requires a lot of spatial reorientation, increasing cognitive load. Cards work best when displayed in minimal numbers.
Cards are useful in a data visualization context when leveraged to summarize data in dashboards or above tables. They focus users on key takeaways without the need to analyze all of the available data.
Considerations for table design
Content alignment
Always match the table header content alignment to the body alignment. Content alignment differs depending on the contents of the cell:
- Text: left-aligned.
- Numerical: right-aligned.
- Actions: right-aligned.
Content ordering and importance
Arrange the columns in order of importance from left to right. Consider bolder visual treatment for the left-most, identifying column.
Row styling
Appropriate row styling makes the data more readable, as it’s easy to distinguish between entries. Depending on the amount of data and interactions available within the table, consider:
|
Preview |
Styling Type |
Use Case |
|---|---|---|
|
Horizontal lines |
Displaying complex data, often in various formats, with intention to reduce noise. |
|
Grid lines |
Displaying complex, dense data, with intention to clearly separate all cells. |
|
Zebra stripes |
Displaying complex, dense data, when rows are read only and don’t have additional states and interactions that could be easily confused with zebra styling. |
Sorting
Allow sorting columns, so users can easily customize the displayed data. Sorting should be toggled by clicking on a relevant column header (or, at minimum, the sorting icon and the accompanying text label) Use the most relevant type of sorting to the presented data. Most common sorting options include:
- Alphabetical (A - Z, Z - A).
- Size (Largest to smallest, smallest to largest).
- Recency (Newest to oldest, oldest to newest).
Searching
Search functionality makes it easy to find targeted information within large datasets. The search field should be visually connected to the table and placed above it.
When using search in conjunction with filtering, keep the scope of the search to the columns that can’t be filtered. This approach might limit search to a single column, in which case, label the search placeholder with Search {objectName}.
Filtering
Filtering is an excellent addition to searching. It allows users to easily find information, compare it across multiple dimensions, and narrow down substantial data sets.
When using filters in tables, display a summary of selected filters that’s easily accessible and clearly visually connected to the filtered table. Always provide a way to clear the selected filters quickly.
Responsiveness
Tables should be responsive and adapt to fit the available viewport. When there’s too much data represented in a table to display it within a smaller viewport without compromising legibility, use the following approaches:
- Scrolling: add horizontal or vertical scrolls.
- Column customization: allow users to toggle columns on and off to control display.
- Column resizing: allow users to change column width to make content more readable.
Scrolling behavior
Make sure tables are scalable. Information should remain easily understandable when users scroll vertically (many rows) and horizontally (many columns) across tables that won’t fit their viewport. When users start to scroll:
- Vertically: freeze the header, so the data is always presented in context.
- Horizontally: freeze the leftmost column containing identifying information about the viewed items to maintain context.
Another way of controlling horizontal scrolling is column customization.
Column customization
When a table has more than 5 columns, allow users to choose which ones they want to display. That way, they can focus on the most important information for their task. It also potentially removes the need for horizontal scrolling.
Display density
Display density refers to how tall the table rows are. Allowing users to control display density helps them view data in a way that’s most comfortable for them. It also allows them to switch between modes depending on context: a condensed view to see more data at once when using a smaller screen size or a more spacious view when using a bigger screen with less data.
|
Preview |
Density |
Row Height |
|---|---|---|
|
Condensed |
40px |
|
Regular |
48px |
|
Relaxed |
56px |
Table actions
Use progressive disclosure when approaching single and bulk item actions within tables. Displaying buttons by default will clutter already data-rich tables more. Instead, display actions on hover on the row:
- Single item action: display buttons at the end of the row and right-align them.
- Bulk items action: display checkboxes at the beginning of the row and left-align them. Additionally, display the selected item count and choice of actions above the table.
Showing row details
It’s possible that you might need to make more data easily available in table context than would be comfortable to display by default. In those cases, consider the amount of extra information and whether users should be able to manipulate it:
|
Approach |
Amount of information |
Action support |
|---|---|---|
|
Row expansion |
Small |
❌ No |
|
Dialog |
Medium |
✅ Yes |
|
Drawer |
Medium |
✅ Yes |
|
Navigate to item page |
Large |
✅ Yes |
Refer to Dialogs, Drawers & Wizards pattern for guidance in using these components.
Optimizing performance
Data-heavy tables can inevitably introduce visible performance issues when data takes too long to load. To decrease negative user experience:
- Use pagination to display data in batches.
- Optimize API calls to serve data quicker.
Accessibility
Using tables for layout
Tables shouldn’t be used to construct page layouts. Their sole purpose is data presentation.
Semantic markup
Use semantic markup to highlight specific table elements (such as th, td) in conjunction with appropriate ARIA roles. Describe the contents of the table using <caption>, and identify column headers by using scope= "row" and scope= "column".
Sequential and logical order
Organize data in sequential and logical order so it is easily understood. Content embedded within a table should be readable even without any design treatment or styling.
View flexibility
Cater to various needs by offering multiple ways of consuming and interacting with tabular data. Tables should be responsive, customizable, and viewable on smaller and larger resolutions.
Content nesting
Be careful when creating complex, nested structures within table cells. Inappropriate nesting will cause screen readers to lose track of the reading order, creating a confusing user experience. Navigating incorrectly nested tables while using assistive technologies will also be difficult.
Empty cells
Don’t leave cells empty. Where there is no data, use zero, nil, or N/A. If the represented data is numerical, use the numerical zero (0).