|

Tables

Documentation and examples for opt-in styling of tables (given their prevalent use in JavaScript plugins) with UX4G.

Overview #

UX4G's tables are opt-in due to the widespread use of <table> components across third-party widgets like calendars and date pickers. Any <table> can be extended with optional modifier classes or unique styles after adding the base class.table. Since none of the table styles in UX4G are inherited, any nested tables can have their own styling independent of the parent table.

Here's how, using the most fundamental table markup.UX4G's table-based tables appear.

RESULT
# First Last Handle
1 Mark Otto @mdo
2 Jacob Thornton @fat
3 Larry the Bird @twitter

Variants #

Color-coding to add meaning just gives a visual cue, which users of assistive technologies like screen readers won't be able to understand. Make sure the information the colour designates is either evident from the content itself (such as the visible text) or is included in another way, such as by hiding additional text using the .visually-hidden class.

Class Heading Heading
Default Cell Cell
Primary Cell Cell
Secondary Cell Cell
Success Cell Cell
Danger Cell Cell
Warning Cell Cell
Info Cell Cell
Light Cell Cell
Dark Cell Cell
<!-- On tables -->
<table class="table-primary">...</table>
<table class="table-secondary">...</table>
<table class="table-success">...</table>
<table class="table-danger">...</table>
<table class="table-warning">...</table>
<table class="table-info">...</table>
<table class="table-light">...</table>
<table class="table-dark">...</table>

<!-- On rows -->
<tr class="table-primary">...</tr>
<tr class="table-secondary">...</tr>
<tr class="table-success">...</tr>
<tr class="table-danger">...</tr>
<tr class="table-warning">...</tr>
<tr class="table-info">...</tr>
<tr class="table-light">...</tr>
<tr class="table-dark">...</tr>

<!-- On cells (`td` or `th`) -->
<tr>
<td class="table-primary">...</td>
<td class="table-secondary">...</td>
<td class="table-success">...</td>
<td class="table-danger">...</td>
<td class="table-warning">...</td>
<td class="table-info">...</td>
<td class="table-light">...</td>
<td class="table-dark">...</td>
</tr>

CONVEYING MEANING TO ASSISTIVE TECHNOLOGIES

Using color to add meaning only provides a visual indication, which will not be conveyed to users of assistive technologies – such as screen readers. Ensure that information denoted by the color is either obvious from the content itself (e.g. the visible text), or is included through alternative means, such as additional text hidden with the .visually-hidden class.

Accented tables #

Striped rows #

Use .table-striped to add zebra-striping to any table row within the .

# First Last Handle
1 Mark Otto @mdo
2 Jacob Thornton @fat
3 Larry the Bird @twitter

Striped columns #

Use .table-striped-columns to add zebra-striping to any table column.

RESULT
# First Last Handle
1 Mark Otto @mdo
2 Jacob Thornton @fat
3 Larry the Bird @twitter

These classes can also be added to table variants:

RESULT
# First Last Handle
1 Mark Otto @mdo
2 Jacob Thornton @fat
3 Larry the Bird @twitter
RESULT
# First Last Handle
1 Mark Otto @mdo
2 Jacob Thornton @fat
3 Larry the Bird @twitter
RESULT
# First Last Handle
1 Mark Otto @mdo
2 Jacob Thornton @fat
3 Larry the Bird @twitter
RESULT
# First Last Handle
1 Mark Otto @mdo
2 Jacob Thornton @fat
3 Larry the Bird @twitter

Hoverable rows #

Add .table-hover to enable a hover state on table rows within a tbody.

RESULT
# First Last Handle
1 Mark Otto @mdo
2 Jacob Thornton @fat
3 Larry the Bird @twitter
RESULT
# First Last Handle
1 Mark Otto @mdo
2 Jacob Thornton @fat
3 Larry the Bird @twitter

These hoverable rows can also be combined with the striped rows variant:

RESULT
# First Last Handle
1 Mark Otto @mdo
2 Jacob Thornton @fat
3 Larry the Bird @twitter

Active tables #

Highlight a table row or cell by adding a .table-active class.

# First Last Handle
1 Mark Otto @mdo
2 Jacob Thornton @fat
3 Larry the Bird @twitter
<table class="table">
  <thead>
    ...
  </thead>
  <tbody>
    <tr class="table-active">
      ...
    </tr>
    <tr>
      ...
    </tr>
    <tr>
      <th scope="row">3</th>
      <td colspan="2" class="table-active">Larry the Bird</td>
      <td>@twitter</td>
    </tr>
  </tbody>
</table>
# First Last Handle
1 Mark Otto @mdo
2 Jacob Thornton @fat
3 Larry the Bird @twitter
<table class="table table-dark">
<thead>
...
</thead>
<tbody>
<tr class="table-active">
...
</tr>
<tr>
...
</tr>
<tr>
<th scope="row">3</th>
<td colspan="2" class="table-active">Larry the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>

How do the variants and accented tables work? #

There are several methods to ensure that these effects appeared on all of the table variations for the accented tables (striped rows, striped columns, hoverable rows, and active tables):

  • Starting off, use the custom property --bs-table-bg to change a table cell's background colour. The custom attribute is then set in all table variations to colourize the table cells. In this approach, if semi-transparent colours are chosen for table backdrops, avoid any issues.
  • Then, to layer on top of any supplied background-color, place an inset box shadow on the table cells with the following syntax: box-shadow: inset 0 0 0 9999px var (--bs-table-accent-bg); The colour will be monotone because there is a utilisation of wide spread and didn't apply any blur. It doesn't have a default box-shadow because --bs-table-accent-bg is unset by default.
  • The --bs-table-accent-bg property is used to colourize the background when the .table-striped, .table-striped-columns, .table-hover, or .table-active classes are added.
  • We create a --bs-table-accent-bg colour for each table version based on the colour that has the highest contrast. For instance, .table-primary has a darker accent colour than .table-dark, which has a lighter accent colour.
  • The same algorithm is used to produce both text and border colours, and by default, those colours are inherited.
@mixin table-variant($state, $background) {
  .table-#{$state} {
    $color: color-contrast(opaque($body-bg, $background));
    $hover-bg: mix($color, $background, percentage($table-hover-bg-factor));
    $striped-bg: mix($color, $background, percentage($table-striped-bg-factor));
    $active-bg: mix($color, $background, percentage($table-active-bg-factor));
    $table-border-color: mix($color, $background, percentage($table-border-factor));

    --#{$prefix}table-color: #{$color};
    --#{$prefix}table-bg: #{$background};
    --#{$prefix}table-border-color: #{$table-border-color};
    --#{$prefix}table-striped-bg: #{$striped-bg};
    --#{$prefix}table-striped-color: #{color-contrast($striped-bg)};
    --#{$prefix}table-active-bg: #{$active-bg};
    --#{$prefix}table-active-color: #{color-contrast($active-bg)};
    --#{$prefix}table-hover-bg: #{$hover-bg};
    --#{$prefix}table-hover-color: #{color-contrast($hover-bg)};

    color: var(--#{$prefix}table-color);
    border-color: var(--#{$prefix}table-border-color);
  }
}

Table borders #

Bordered tables #

Add .table-bordered for borders on all sides of the table and cells.

RESULT
# First Last Handle
1 Mark Otto @mdo
2 Jacob Thornton @fat
3 Larry the Bird @twitter

Border color utilities can be added to change colors:

RESULT
# First Last Handle
1 Mark Otto @mdo
2 Jacob Thornton @fat
3 Larry the Bird @twitter

Tables without borders #

Add .table-borderless for a table without borders.

RESULT
# First Last Handle
1 Mark Otto @mdo
2 Jacob Thornton @fat
3 Larry the Bird @twitter
RESULT
# First Last Handle
1 Mark Otto @mdo
2 Jacob Thornton @fat
3 Larry the Bird @twitter

Small tables #

Add .table-sm to make any .table more compact by cutting all cell padding in half.

<table class="table table-sm ">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td colspan="2">Larry the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
Result
# First Last Handle
1 Mark Otto @mdo
2 Jacob Thornton @fat
3 Larry the Bird @twitter
<table class="table table-dark table-sm ">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td colspan="2">Larry the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
Result
# First Last Handle
1 Mark Otto @mdo
2 Jacob Thornton @fat
3 Larry the Bird @twitter

Table group dividers #

Add a thicker border, darker between table groups—, , and —with .table-group-divider. Customize the color by changing the border-top-color (which we don't currently provide a utility class for at this time).

<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody class="table-group-divider">
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td colspan="2">Larry the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
Result
# First Last Handle
1 Mark Otto @mdo
2 Jacob Thornton @fat
3 Larry the Bird @twitter

Vertical alignment #

Table cells are always positioned at the bottom and vertically aligned. Table cells in and by default have top alignment, which they inherit from. To realign when necessary, use the vertical align classes.

Heading 1 Heading 2 Heading 3 Heading 4
This cell inherits vertical-align: middle; from the table This cell inherits vertical-align: middle; from the table This cell inherits vertical-align: middle; from the table This here is some placeholder text, intended to take up quite a bit of vertical space, to demonstrate how the vertical alignment works in the preceding cells.
This cell inherits vertical-align: bottom; from the table row This cell inherits vertical-align: bottom; from the table row This cell inherits vertical-align: bottom; from the table row This here is some placeholder text, intended to take up quite a bit of vertical space, to demonstrate how the vertical alignment works in the preceding cells.
This cell inherits vertical-align: middle; from the table This cell inherits vertical-align: middle; from the table This cell is aligned to the top. This here is some placeholder text, intended to take up quite a bit of vertical space, to demonstrate how the vertical alignment works in the preceding cells.
<div class="table-responsive">
<table class="table align-middle">
<thead>
<tr>
...
</tr>
</thead>
<tbody>
<tr>
...
</tr>
<tr class="align-bottom">
...
</tr>
<tr>
<td>...</td>
<td>...</td>
<td class="align-top">This cell is aligned to the top.</td>
<td>...</td>
</tr>
</tbody>
</table>
</div>

Nesting #

Border styles, active styles, and table variants are not inherited by nested tables.

# First Last Handle
1 Mark Otto @mdo
Header Header Header
A First Last
B First Last
C First Last
3 Larry the Bird @twitter
<table class="table table-striped">
<thead>
...
</thead>
<tbody>
...
<tr>
<td colspan="4">
<table class="table mb-0">
...
</table>
</td>
</tr>
...
</tbody>
</table>

How nesting works #

We employ the child combinator (>) selector in our CSS to stop styles from leaking to nested tables. In order to target every td and th in the thead, tbody, and tfoot, we need this selector, which would otherwise appear quite long. As a result, we employ the peculiar-looking.All tds and ths of the.table are targeted by the table >:not(caption) > * > * selector, but none of the possible nested tables are.

Remember that our selectors will function as planned if you add tr>s as direct children of a table since those <tr> will automatically be wrapped in a <tbody>.

Anatomy #

Table head #

Similar to tables and dark tables, use the modifier classes .table-light or .table-dark to make s appear light or dark gray.

<table class="table">
<thead class="table-light">
...
</thead>
<tbody>
...
</tbody>
</table>
# First Last Handle
1 Mark Otto @mdo
2 Jacob Thornton @fat
3 Larry the Bird @twitter
<table class="table">
<thead class="table-dark">
...
</thead>
<tbody>
...
</tbody>
</table>
# First Last Handle
1 Mark Otto @mdo
2 Jacob Thornton @fat
3 Larry the Bird @twitter

Table foot #

<table class="table">
<thead>
...
</thead>
<tbody>
...
</tbody>
<tfoot>
...
</tfoot>
</table>
# First Last Handle
1 Mark Otto @mdo
2 Jacob Thornton @fat
3 Larry the Bird @twitter
Footer Footer Footer Footer

Captions #

A functions like a heading for a table. It helps users with screen readers to find a table and understand what it's about and decide if they want to read it.

Partail Table Content
List of users
<table class="table table-sm">
<caption>List of users</caption>
<thead>
...
</thead>
<tbody>
...
</tbody>
</table>

You can also put the on the top of the table with .caption-top.

<table class="table caption-top">
<caption>List of users</caption>
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td>Larry</td>
<td>the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
Result
List of users
# First Last Handle
1 Mark Otto @mdo
2 Jacob Thornton @fat
3 Larry the Bird @twitter

Responsive tables #

Tables that are responsive can easily be scrolled horizontally. Wrapping a .table in .table-responsive will make any table responsive across all viewports. Alternately, you may specify a maximum breakpoint by using the .table-responsive {-sm|-md|-lg|-xl|-xxl} keyword.

CAUTION

Vertical clipping/truncation #

Overflow-y: hidden, which clips off material that extends past the bottom or top margins of the table, is a technique used in responsive tables. This can specifically clip off third-party widgets like dropdown menus.

Always responsive #

Across every breakpoint, use .table-responsive for horizontally scrolling tables.

# Heading Heading Heading Heading Heading Heading Heading Heading Heading
1 Cell Cell Cell Cell Cell Cell Cell Cell Cell
2 Cell Cell Cell Cell Cell Cell Cell Cell Cell
3 Cell Cell Cell Cell Cell Cell Cell Cell Cell
<div class="table-responsive">
<table class="table">
...
</table>
</div>

Breakpoint specific #

To generate responsive tables up to a specific breakpoint, use .table-responsive{-sm|-md|-lg|-xl|-xxl}. The table will act appropriately after that breakpoint and won't scroll horizontally.

<div class="table-responsive">
  <table class="table">
    ...
  </table>
</div>

<div class="table-responsive-sm">
  <table class="table">
    ...
  </table>
</div>

<div class="table-responsive-md">
  <table class="table">
    ...
  </table>
</div>

<div class="table-responsive-lg">
  <table class="table">
    ...
  </table>
</div>

<div class="table-responsive-xl">
  <table class="table">
    ...
  </table>
</div>

<div class="table-responsive-xxl">
  <table class="table">
    ...
  </table>
</div>
Result
# Heading Heading Heading Heading Heading Heading Heading Heading
1 Cell Cell Cell Cell Cell Cell Cell Cell
2 Cell Cell Cell Cell Cell Cell Cell Cell
3 Cell Cell Cell Cell Cell Cell Cell Cell
# Heading Heading Heading Heading Heading Heading Heading Heading
1 Cell Cell Cell Cell Cell Cell Cell Cell
2 Cell Cell Cell Cell Cell Cell Cell Cell
3 Cell Cell Cell Cell Cell Cell Cell Cell
# Heading Heading Heading Heading Heading Heading Heading Heading
1 Cell Cell Cell Cell Cell Cell Cell Cell
2 Cell Cell Cell Cell Cell Cell Cell Cell
3 Cell Cell Cell Cell Cell Cell Cell Cell
# Heading Heading Heading Heading Heading Heading Heading Heading
1 Cell Cell Cell Cell Cell Cell Cell Cell
2 Cell Cell Cell Cell Cell Cell Cell Cell
3 Cell Cell Cell Cell Cell Cell Cell Cell
# Heading Heading Heading Heading Heading Heading Heading Heading
1 Cell Cell Cell Cell Cell Cell Cell Cell
2 Cell Cell Cell Cell Cell Cell Cell Cell
3 Cell Cell Cell Cell Cell Cell Cell Cell
# Heading Heading Heading Heading Heading Heading Heading Heading
1 Cell Cell Cell Cell Cell Cell Cell Cell
2 Cell Cell Cell Cell Cell Cell Cell Cell
3 Cell Cell Cell Cell Cell Cell Cell Cell

Customizing #

  • The factor variables ($table-striped-bg-factor, $table-active-bg-factor & $table-hover-bg-factor) are used to determine the contrast in table variants.
  • Apart from the light & dark table variants, theme colors are lightened by the $table-bg-scale variable.