0
0
mirror of https://github.com/twbs/bootstrap.git synced 2025-03-15 15:29:22 +01:00

Prevent nested tables style leaks

This commit is contained in:
Martijn Cuppens 2020-03-24 15:00:00 +01:00
parent ffb19e925c
commit d089a683c8
10 changed files with 642 additions and 712 deletions

View File

@ -27,7 +27,7 @@
@import "mixins/lists"; @import "mixins/lists";
@import "mixins/list-group"; @import "mixins/list-group";
@import "mixins/forms"; @import "mixins/forms";
@import "mixins/table-row"; @import "mixins/table-variants";
// Skins // Skins
@import "mixins/background-variant"; @import "mixins/background-variant";

View File

@ -374,6 +374,17 @@ th {
text-align: -webkit-match-parent; // 2 text-align: -webkit-match-parent; // 2
} }
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
// Forms // Forms
// //

View File

@ -3,29 +3,45 @@
// //
.table { .table {
--table-bg: #{$table-bg};
--table-accent-bg: transparent;
--table-striped-color: #{$table-striped-color};
--table-striped-bg: #{$table-striped-bg};
--table-active-color: #{$table-active-color};
--table-active-bg: #{$table-active-bg};
--table-hover-color: #{$table-hover-color};
--table-hover-bg: #{$table-hover-bg};
width: 100%; width: 100%;
margin-bottom: $spacer; margin-bottom: $spacer;
color: $table-color; color: $table-color;
vertical-align: $table-cell-vertical-align; vertical-align: $table-cell-vertical-align;
background-color: $table-bg; // Reset for nesting within parents with `background-color`. border-color: $table-border-color;
th, // Target th & td
td { // We need the child combinator to prevent styles leaking to nested tables which doesn't have a `.table` class.
// We use the universal selectors here to simplify the selector (else we would need 6 different selectors).
// Another advantage is that this generates less code and makes the selector less specific making it easier to override.
// stylelint-disable-next-line selector-max-universal
> :not(caption) > * > * {
padding: $table-cell-padding; padding: $table-cell-padding;
border-bottom: $table-border-width solid $table-border-color; background-color: var(--table-bg);
background-image: linear-gradient(var(--table-accent-bg), var(--table-accent-bg));
border-bottom-width: $table-border-width;
} }
tbody { > tbody {
vertical-align: inherit; vertical-align: inherit;
} }
thead th { > thead {
vertical-align: bottom; vertical-align: bottom;
border-bottom-color: $table-head-border-color;
} }
tbody + tbody { // Highlight border color between thead, tbody and tfoot.
border-top: (2 * $table-border-width) solid $table-border-color; // stylelint-disable-next-line selector-max-universal
> :not(:last-child) > :last-child > * {
border-bottom-color: currentColor;
} }
} }
@ -34,7 +50,9 @@
// Change placement of captions with a class // Change placement of captions with a class
// //
.caption-top { caption-side: top; } .caption-top {
caption-side: top;
}
// //
@ -42,8 +60,8 @@
// //
.table-sm { .table-sm {
th, // stylelint-disable-next-line selector-max-universal
td { > :not(caption) > * > * {
padding: $table-cell-padding-sm; padding: $table-cell-padding-sm;
} }
} }
@ -52,29 +70,28 @@
// Border versions // Border versions
// //
// Add or remove borders all around the table and between all the columns. // Add or remove borders all around the table and between all the columns.
//
// When borders are added on all sides of the cells, the corners can render odd when
// these borders do not have the same color or if they are semi-transparent.
// Therefor we add top and border bottoms to the `tr`s and left and right borders
// to the `td`s or `th`s
.table-bordered { .table-bordered {
border: $table-border-width solid $table-border-color; // stylelint-disable-next-line selector-max-universal
> :not(caption) > * {
border-width: $table-border-width 0;
th, // stylelint-disable-next-line selector-max-universal
td { > * {
border: $table-border-width solid $table-border-color; border-width: 0 $table-border-width;
}
thead {
th,
td {
border-bottom-width: 2 * $table-border-width;
} }
} }
} }
.table-borderless { .table-borderless {
th, // stylelint-disable-next-line selector-max-universal
td, > :not(caption) > * > * {
thead th, border-bottom-width: 0;
tbody + tbody {
border: 0;
} }
} }
@ -83,92 +100,42 @@
// Default zebra-stripe styles (alternating gray and transparent backgrounds) // Default zebra-stripe styles (alternating gray and transparent backgrounds)
.table-striped { .table-striped {
tbody tr:nth-of-type(#{$table-striped-order}) { > tbody > tr:nth-of-type(#{$table-striped-order}) {
background-color: $table-accent-bg; --table-accent-bg: var(--table-striped-bg);
color: var(--table-striped-color);
} }
} }
// Active table
//
// The `.table-active` class can be added to highlight rows or cells
.table-active {
--table-accent-bg: var(--table-active-bg);
color: var(--table-active-color);
}
// Hover effect // Hover effect
// //
// Placed here since it has to come after the potential zebra striping // Placed here since it has to come after the potential zebra striping
.table-hover { .table-hover {
tbody tr { > tbody > tr:hover {
&:hover { --table-accent-bg: var(--table-hover-bg);
color: $table-hover-color; color: var(--table-hover-color);
background-color: $table-hover-bg;
}
} }
} }
// Table backgrounds // Table variants
// //
// Exact selectors below required to override `.table-striped` and prevent // Table variants set the table cell backgrounds, border colors
// inheritance to nested tables. // and the colors of the striped, hovered & active tables
@each $color, $value in $theme-colors { @each $color, $value in $table-variants {
@include table-row-variant($color, color-level($value, $table-bg-level), color-level($value, $table-border-level)); @include table-variant($color, $value);
} }
@include table-row-variant(active, $table-active-bg);
// Dark styles
//
// Same table markup, but inverted color scheme: dark background and light text.
// stylelint-disable-next-line no-duplicate-selectors
.table {
.thead-dark {
th {
color: $table-dark-color;
background-color: $table-dark-bg;
border-color: $table-dark-border-color;
}
}
.thead-light {
th {
color: $table-head-color;
background-color: $table-head-bg;
border-color: $table-border-color;
}
}
}
.table-dark {
color: $table-dark-color;
background-color: $table-dark-bg;
th,
td,
thead th {
border-color: $table-dark-border-color;
}
&.table-bordered {
border: 0;
}
&.table-striped {
tbody tr:nth-of-type(#{$table-striped-order}) {
background-color: $table-dark-accent-bg;
}
}
&.table-hover {
tbody tr {
&:hover {
color: $table-dark-hover-color;
background-color: $table-dark-hover-bg;
}
}
}
}
// Responsive tables // Responsive tables
// //
// Generate series of `.table-responsive-*` classes for configuring the screen // Generate series of `.table-responsive-*` classes for configuring the screen

View File

@ -465,38 +465,48 @@ $mark-bg: #fcf8e3 !default;
// //
// Customizes the `.table` component with basic values, each used across all table variations. // Customizes the `.table` component with basic values, each used across all table variations.
// scss-docs-start table-variables
$table-cell-padding: .5rem !default; $table-cell-padding: .5rem !default;
$table-cell-padding-sm: .25rem !default; $table-cell-padding-sm: .25rem !default;
$table-cell-vertical-align: top !default; $table-cell-vertical-align: top !default;
$table-color: $body-color !default; $table-color: $body-color !default;
$table-bg: null !default; $table-bg: transparent !default;
$table-accent-bg: rgba($black, .05) !default;
$table-hover-color: $table-color !default;
$table-hover-bg: rgba($black, .075) !default;
$table-active-bg: $table-hover-bg !default;
$table-striped-color: $table-color !default;
$table-striped-bg-factor: .05 !default;
$table-striped-bg: rgba($black, $table-striped-bg-factor) !default;
$table-active-color: $table-color !default;
$table-active-bg-factor: .1 !default;
$table-active-bg: rgba($black, $table-active-bg-factor) !default;
$table-hover-color: $table-color !default;
$table-hover-bg-factor: .075 !default;
$table-hover-bg: rgba($black, $table-hover-bg-factor) !default;
$table-border-factor: .1 !default;
$table-border-width: $border-width !default; $table-border-width: $border-width !default;
$table-border-color: $border-color !default; $table-border-color: $border-color !default;
$table-head-bg: $gray-200 !default;
$table-head-color: $gray-700 !default;
$table-head-border-color: $gray-700 !default;
$table-dark-color: $white !default;
$table-dark-bg: $gray-800 !default;
$table-dark-accent-bg: rgba($white, .05) !default;
$table-dark-hover-color: $table-dark-color !default;
$table-dark-hover-bg: rgba($white, .075) !default;
$table-dark-border-color: lighten($table-dark-bg, 7.5%) !default;
$table-striped-order: odd !default; $table-striped-order: odd !default;
$table-caption-color: $text-muted !default; $table-caption-color: $text-muted !default;
$table-bg-level: -9 !default; $table-bg-level: -9 !default;
$table-border-level: -6 !default;
$table-variants: (
"primary": color-level($primary, $table-bg-level),
"secondary": color-level($secondary, $table-bg-level),
"success": color-level($success, $table-bg-level),
"info": color-level($info, $table-bg-level),
"warning": color-level($warning, $table-bg-level),
"danger": color-level($danger, $table-bg-level),
"light": $light,
"dark": $dark,
) !default;
// scss-docs-end table-variables
// Buttons + Forms // Buttons + Forms

View File

@ -1,39 +0,0 @@
// Tables
@mixin table-row-variant($state, $background, $border: null) {
// Exact selectors below required to override `.table-striped` and prevent
// inheritance to nested tables.
.table-#{$state} {
&,
> th,
> td {
background-color: $background;
}
@if $border != null {
th,
td,
thead th,
tbody + tbody {
border-color: $border;
}
}
}
// Hover states for `.table-hover`
// Note: this is not available for cells or rows within `thead` or `tfoot`.
.table-hover {
$hover-background: darken($background, 5%);
.table-#{$state} {
&:hover {
background-color: $hover-background;
> td,
> th {
background-color: $hover-background;
}
}
}
}
}

View File

@ -0,0 +1,21 @@
// scss-docs-start table-variant
@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-bg: #{$background};
--table-striped-bg: #{$striped-bg};
--table-striped-color: #{color-contrast($striped-bg)};
--table-active-bg: #{$active-bg};
--table-active-color: #{color-contrast($active-bg)};
--table-hover-bg: #{$hover-bg};
--table-hover-color: #{color-contrast($hover-bg)};
color: $color;
border-color: mix($color, $background, percentage($table-border-factor));
}
}
// scss-docs-end table-variant

View File

@ -8,328 +8,102 @@ toc: true
## Overview ## Overview
Due to the widespread use of `<table>` elements across third-party widgets like calendars and date pickers, Bootstrap's tables are **opt-in**. Add the base class `.table` to any `<table>`, then extend with our optional modifier classes or custom styles. **All table styles are inherited in Bootstrap**, meaning any nested tables will be styled in the same manner as the parent. Due to the widespread use of `<table>` elements across third-party widgets like calendars and date pickers, Bootstrap's tables are **opt-in**. Add the base class `.table` to any `<table>`, then extend with our optional modifier classes or custom styles. All table styles are not inherited in Bootstrap, meaning any nested tables can be styled independent from the parent.
Using the most basic table markup, here's how `.table`-based tables look in Bootstrap. Using the most basic table markup, here's how `.table`-based tables look in Bootstrap.
{{< example >}} {{< table class="table" simplified="false" >}}
<table class="table">
## Variants
Use contextual classes to color tables, table rows or individual cells.
<div class="bd-example">
<table class="table">
<thead> <thead>
<tr> <tr>
<th scope="col">#</th> <th scope="col">Class</th>
<th scope="col">First</th> <th scope="col">Heading</th>
<th scope="col">Last</th> <th scope="col">Heading</th>
<th scope="col">Handle</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr> <tr>
<th scope="row">1</th> <th scope="row">Default</th>
<td>Mark</td> <td>Cell</td>
<td>Otto</td> <td>Cell</td>
<td>@mdo</td>
</tr> </tr>
<tr> {{< table.inline >}}
<th scope="row">2</th> {{- range (index $.Site.Data "theme-colors") }}
<td>Jacob</td> <tr class="table-{{ .name }}">
<td>Thornton</td> <th scope="row">{{ .name | title }}</th>
<td>@fat</td> <td>Cell</td>
</tr> <td>Cell</td>
<tr>
<th scope="row">3</th>
<td>Larry</td>
<td>the Bird</td>
<td>@twitter</td>
</tr> </tr>
{{- end -}}
{{< /table.inline >}}
</tbody> </tbody>
</table> </table>
{{< /example >}} </div>
## Options {{< highlight html >}}
<!-- On tables -->{{< table.inline >}}
{{- range (index $.Site.Data "theme-colors") }}
<table class="table-{{ .name }}">...</table>
{{- end -}}
{{< /table.inline >}}
### Inverted <!-- On rows -->{{< table.inline >}}
{{- range (index $.Site.Data "theme-colors") }}
<tr class="table-{{ .name }}">...</tr>
{{- end -}}
{{< /table.inline >}}
You can also invert the colors—with light text on dark backgrounds—with `.table-dark`. <!-- On cells (`td` or `th`) -->
<tr>{{< table.inline >}}
{{- range (index $.Site.Data "theme-colors") }}
<td class="table-{{ .name }}">...</td>
{{- end -}}
{{< /table.inline >}}
</tr>
{{< /highlight >}}
{{< example >}} {{< callout info >}}
<table class="table table-dark"> {{< partial "callout-warning-color-assistive-technologies.md" >}}
<thead> {{< /callout >}}
<tr>
<th scope="col">#</th> ## Accented tables
<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>
{{< /example >}}
### Striped rows ### Striped rows
Use `.table-striped` to add zebra-striping to any table row within the `<tbody>`. Use `.table-striped` to add zebra-striping to any table row within the `<tbody>`.
{{< example >}} {{< table class="table table-striped" >}}
<table class="table table-striped">
<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>
{{< /example >}}
{{< example >}} These classes can also be added to table variants:
<table class="table table-striped table-dark">
<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>
{{< /example >}}
### Bordered {{< table class="table table-dark table-striped" >}}
Add `.table-bordered` for borders on all sides of the table and cells. {{< table class="table table-success table-striped" >}}
{{< example >}}
<table class="table table-bordered">
<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>
{{< /example >}}
{{< example >}}
<table class="table table-bordered table-dark">
<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>
{{< /example >}}
### No borders
Add `.table-borderless` for a table without borders.
{{< example >}}
<table class="table table-borderless">
<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>
{{< /example >}}
`.table-borderless` can also be used on dark tables.
{{< example >}}
<table class="table table-borderless table-dark">
<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>
{{< /example >}}
### Hoverable rows ### Hoverable rows
Add `.table-hover` to enable a hover state on table rows within a `<tbody>`. Add `.table-hover` to enable a hover state on table rows within a `<tbody>`.
{{< example >}} {{< table class="table table-hover" >}}
<table class="table table-hover">
<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>
{{< /example >}}
{{< example >}} {{< table class="table table-dark table-hover" >}}
<table class="table table-hover table-dark">
These hoverable rows can also be combined with the striped variant:
{{< table class="table table-striped table-hover" >}}
### Active tables
Highlight a table row or cell by adding a `.table-active` class.
<div class="bd-example">
<table class="table">
<thead> <thead>
<tr> <tr>
<th scope="col">#</th> <th scope="col">#</th>
@ -339,7 +113,7 @@ Add `.table-hover` to enable a hover state on table rows within a `<tbody>`.
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr> <tr class="table-active">
<th scope="row">1</th> <th scope="row">1</th>
<td>Mark</td> <td>Mark</td>
<td>Otto</td> <td>Otto</td>
@ -353,55 +127,135 @@ Add `.table-hover` to enable a hover state on table rows within a `<tbody>`.
</tr> </tr>
<tr> <tr>
<th scope="row">3</th> <th scope="row">3</th>
<td colspan="2">Larry the Bird</td> <td colspan="2" class="table-active">Larry the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
</div>
{{< highlight html >}}
<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> <td>@twitter</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
{{< /example >}} {{< /highlight >}}
<div class="bd-example">
<table class="table table-dark">
<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 class="table-active">
<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" class="table-active">Larry the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
</div>
{{< highlight html >}}
<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>
{{< /highlight >}}
## How do the variants and accented tables work?
For the accented tables ([striped rows](#striped-rows), [hoverable rows](#hoverable-rows) and [active tables](#active-tables)), we used some techniques to make these effects work for all our [table variants](#variants):
- First of all we set the background of a table cell with the `--table-bg` custom property. All table variants then set that custom property to colorize the table cells. This way, we don't get into trouble if semi-transparent colors are used as table backgrounds.
- Then we add a linear background to the table cells with `background-image: linear-gradient(var(--table-accent-bg), var(--table-accent-bg));`. Since `--table-accent-bg` is transparent by default, we have an invisible transparent linear gradient by default.
- When either `.table-striped`, `.table-hover` or `.table-active` classes are added, the `--table-accent-bg` is set to a semitransparent color to colorize the background.
- For each table variant the `--table-accent-bg` color with the most contrast is generated, therefor `.table-primary` has a darkened accent color and `.table-dark` has a lightened accent color.
- The text color and border color are also generated the same way. The colors and border colors are inherited by default.
Behind the scenes it looks like this:
{{< scss-docs name="table-variant" file="scss/mixins/_table-variants.scss" >}}
## Table borders
### Bordered tables
Add `.table-bordered` for borders on all sides of the table and cells.
{{< table class="table table-bordered" >}}
[Border color utilities]({{< docsref "/utilities/borders#border-color" >}}) can be added to change colors:
{{< table class="table table-bordered border-primary" >}}
### Tables without borders
Add `.table-borderless` for a table without borders.
{{< table class="table table-borderless" >}}
{{< table class="table table-dark table-borderless" >}}
### Small tables ### Small tables
Add `.table-sm` to make any `.table` more compact by cutting all cell `padding` in half. Add `.table-sm` to make any `.table` more compact by cutting all cell `padding` in half.
{{< example >}} {{< table class="table table-sm" >}}
<table class="table table-sm">
<thead> {{< table class="table table-dark table-sm" >}}
<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>
{{< /example >}}
## Vertical alignment ## Vertical alignment
Table cells of `<thead>` are always vertical aligned to the bottom. Table cells in `<tbody>` inherit their alignment from `<table>` and are aligned to the the top by default. Table cells of `<thead>` are always vertical aligned to the bottom. Table cells in `<tbody>` inherit their alignment from `<table>` and are aligned to the the top by default. Use the [vertical align]({{< docsref "/utilities/vertical-align" >}}) classes to re-align where needed.
{{< example >}} <div class="bd-example">
<div class="table-responsive"> <div class="table-responsive">
<table class="table align-middle"> <table class="table align-middle">
<thead> <thead>
<tr> <tr>
@ -432,158 +286,130 @@ Table cells of `<thead>` are always vertical aligned to the bottom. Table cells
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </div>
{{< /example >}}
### Variants
Use contextual classes to color table rows or individual cells.
<div class="bd-example">
<table class="table">
<thead>
<tr>
<th scope="col">Class</th>
<th scope="col">Heading</th>
<th scope="col">Heading</th>
</tr>
</thead>
<tbody>
<tr class="table-active">
<th scope="row">Active</th>
<td>Cell</td>
<td>Cell</td>
</tr>
<tr>
<th scope="row">Default</th>
<td>Cell</td>
<td>Cell</td>
</tr>
{{< table.inline >}}
{{- range (index $.Site.Data "theme-colors") }}
<tr class="table-{{ .name }}">
<th scope="row">{{ .name | title }}</th>
<td>Cell</td>
<td>Cell</td>
</tr>
{{- end -}}
{{< /table.inline >}}
</tbody>
</table>
</div> </div>
{{< highlight html >}} {{< highlight html >}}
<!-- On rows --> <table class="table table-sm table-dark">
<tr class="table-active">...</tr> <div class="table-responsive">
{{< table.inline >}} <table class="table align-middle">
{{- range (index $.Site.Data "theme-colors") }} <thead>
<tr class="table-{{ .name }}">...</tr> <tr>
{{- end -}} ...
{{< /table.inline >}} </tr>
</thead>
<!-- On cells (`td` or `th`) --> <tbody>
<tr> <tr>
<td class="table-active">...</td> ...
{{< table.inline >}} </tr>
{{- range (index $.Site.Data "theme-colors") }} <tr class="align-bottom">
<td class="table-{{ .name }}">...</td> ...
{{- end -}} </tr>
{{< /table.inline >}} <tr>
</tr> <td>...</td>
<td>...</td>
<td class="align-top">This cell is aligned to the top.</td>
<td>...</td>
</tr>
</tbody>
</table>
</div>
</table>
{{< /highlight >}} {{< /highlight >}}
Regular table background variants are not available with the dark table, however, you may use [text or background utilities]({{< docsref "/utilities/colors" >}}) to achieve similar styles. ## Nesting
Neither border styles, active styles nor table variants are inherited by nested tables:
<div class="bd-example"> <div class="bd-example">
<table class="table table-dark"> <table class="table table-striped table-bordered">
<thead> <thead>
<tr> <tr>
<th scope="col">#</th> <th scope="col">#</th>
<th scope="col">Heading</th> <th scope="col">First</th>
<th scope="col">Heading</th> <th scope="col">Last</th>
<th scope="col">Handle</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr class="bg-primary"> <tr>
<th scope="row">1</th> <th scope="row">1</th>
<td>Cell</td> <td>Mark</td>
<td>Cell</td> <td>Otto</td>
<td>@mdo</td>
</tr> </tr>
<tr> <tr>
<th scope="row">2</th> <td colspan="4">
<td>Cell</td> <table class="table mb-0">
<td>Cell</td> <thead>
<tr>
<th scope="col">Header</th>
<th scope="col">Header</th>
<th scope="col">Header</th>
</tr> </tr>
<tr class="bg-success"> </thead>
<th scope="row">3</th> <tbody>
<td>Cell</td> <tr>
<td>Cell</td> <th scope="row">A</th>
<td>First</td>
<td>Last</td>
</tr> </tr>
<tr> <tr>
<th scope="row">4</th> <th scope="row">B</th>
<td>Cell</td> <td>First</td>
<td>Cell</td> <td>Last</td>
</tr>
<tr class="bg-info">
<th scope="row">5</th>
<td>Cell</td>
<td>Cell</td>
</tr> </tr>
<tr> <tr>
<th scope="row">6</th> <th scope="row">C</th>
<td>Cell</td> <td>First</td>
<td>Cell</td> <td>Last</td>
</tr>
<tr class="bg-warning">
<th scope="row">7</th>
<td>Cell</td>
<td>Cell</td>
</tr>
<tr>
<th scope="row">8</th>
<td>Cell</td>
<td>Cell</td>
</tr>
<tr class="bg-danger">
<th scope="row">9</th>
<td>Cell</td>
<td>Cell</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</td>
</tr>
<tr>
<th scope="row">3</th>
<td>Larry</td>
<td>the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
</div> </div>
{{< highlight html >}} {{< highlight html >}}
<!-- On rows --> <table class="table table-striped">
<tr class="bg-primary">...</tr> <thead>
<tr class="bg-success">...</tr> ...
<tr class="bg-warning">...</tr> </thead>
<tr class="bg-danger">...</tr> <tbody>
<tr class="bg-info">...</tr> ...
<tr>
<!-- On cells (`td` or `th`) --> <td colspan="4">
<tr> <table class="table mb-0">
<td class="bg-primary">...</td> ...
<td class="bg-success">...</td> </table>
<td class="bg-warning">...</td> </td>
<td class="bg-danger">...</td> </tr>
<td class="bg-info">...</td> ...
</tr> </tbody>
</table>
{{< /highlight >}} {{< /highlight >}}
{{< callout info >}} ## How nesting works
{{< partial "callout-warning-color-assistive-technologies.md" >}}
{{< /callout >}} To prevent **any** style from leaking to nested tables we worked with the child combinator (`>`). Since we needed to target all the `td`s and `th`s in the `thead`, `tbody` and `tfoot`, our selector would look pretty long. Therefor we use the rather odd looking `.table > :not(caption) > * > * ` selector to target all `td`s and `th`s of the `.table` and not a nested table. Note: if you add `<tr>`s as direct children of a table, those `<tr>` will be wrapped in a `<tbody>` by default and therefor making the selector work.
## Anatomy ## Anatomy
### Table head ### Table head
Similar to tables and dark tables, use the modifier classes `.thead-light` or `.thead-dark` to make `<thead>`s appear light or dark gray. Similar to tables and dark tables, use the modifier classes `.table-light` or `.table-dark` to make `<thead>`s appear light or dark gray.
{{< example >}} <div class="bd-example">
<table class="table"> <table class="table">
<thead class="thead-dark"> <thead class="table-light">
<tr> <tr>
<th scope="col">#</th> <th scope="col">#</th>
<th scope="col">First</th> <th scope="col">First</th>
@ -612,9 +438,22 @@ Similar to tables and dark tables, use the modifier classes `.thead-light` or `.
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div>
{{< highlight html >}}
<table class="table"> <table class="table">
<thead class="thead-light"> <thead class="table-light">
...
</thead>
<tbody>
...
</tbody>
</table>
{{< /highlight >}}
<div class="bd-example">
<table class="table">
<thead class="table-dark">
<tr> <tr>
<th scope="col">#</th> <th scope="col">#</th>
<th scope="col">First</th> <th scope="col">First</th>
@ -643,45 +482,99 @@ Similar to tables and dark tables, use the modifier classes `.thead-light` or `.
</tr> </tr>
</tbody> </tbody>
</table> </table>
{{< /example >}} </div>
{{< highlight html >}}
<table class="table">
<thead class="table-dark">
...
</thead>
<tbody>
...
</tbody>
</table>
{{< /highlight >}}
### Table foot
<div class="bd-example">
<table class="table">
<thead class="table-light">
<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>
<tfoot>
<tr>
<td>Footer</td>
<td>Footer</td>
<td>Footer</td>
<td>Footer</td>
</tr>
</tfoot>
</table>
</div>
{{< highlight html >}}
<table class="table">
<thead>
...
</thead>
<tbody>
...
</tbody>
<tfoot>
...
</tfoot>
</table>
{{< /highlight >}}
### Captions ### Captions
A `<caption>` 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. A `<caption>` 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.
{{< example >}} <div class="bd-example">
<table class="table"> <table class="table">
<caption>List of users</caption>
{{< partial "table-content.html" >}}
</table>
</div>
{{< highlight html >}}
<table class="table table-sm">
<caption>List of users</caption> <caption>List of users</caption>
<thead> <thead>
<tr> ...
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead> </thead>
<tbody> <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> </tbody>
</table> </table>
{{< /example >}} {{< /highlight >}}
You can also put the `<caption>` on the top of the table with `.caption-top`. You can also put the `<caption>` on the top of the table with `.caption-top`.
@ -880,3 +773,10 @@ Use `.table-responsive{-sm|-md|-lg|-xl|-xxl}` as needed to create responsive tab
{{- end -}} {{- end -}}
{{< /tables.inline >}} {{< /tables.inline >}}
{{< /highlight >}} {{< /highlight >}}
## Customizing in Sass
- 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-level` variable.
{{< scss-docs name="table-variables" file="scss/_variables.scss" >}}

View File

@ -72,7 +72,10 @@ Changes to Reboot, typography, tables, and more.
- [RFS]({{< docsref "/getting-started/rfs" >}}) enabled for automated font size rescaling. [See #29152](https://github.com/twbs/bootstrap/pull/29152) - [RFS]({{< docsref "/getting-started/rfs" >}}) enabled for automated font size rescaling. [See #29152](https://github.com/twbs/bootstrap/pull/29152)
- Reset default horizontal `padding-left` on `<ul>` and `<ol>` elements from browser default `40px` to `2rem`. - Reset default horizontal `padding-left` on `<ul>` and `<ol>` elements from browser default `40px` to `2rem`.
- Simplified table styles (no more 2px border on `thead > th` elements) and tightened cell padding. - Simplified table styles (no more odd top border) and tightened cell padding.
- Nested tables do not inherit styles anymore.
- `.thead-light` and `.thead-dark` are dropped in favor of the `.table-*` variant classes which can be used for all table elements (`thead`, `tbody`, `tfoot`, `tr`, `th` and `td`).
- The `table-row-variant()` mixin is renamed to `table-variant()` and accepts only 2 parameters: `$color` (colon name) and `$value` (color code). The border color and accent colors are automatically calculated based on the table factor variables.
- Dropped `.pre-scrollable` class. [See #29135](https://github.com/twbs/bootstrap/pull/29135) - Dropped `.pre-scrollable` class. [See #29135](https://github.com/twbs/bootstrap/pull/29135)
- `.text-*` utilities do not add hover and focus states to links anymore. `.link-*` helper classes can be used instead. [See #29267](https://github.com/twbs/bootstrap/pull/29267) - `.text-*` utilities do not add hover and focus states to links anymore. `.link-*` helper classes can be used instead. [See #29267](https://github.com/twbs/bootstrap/pull/29267)
- Drop `.text-justify` class. [See #229793](https://github.com/twbs/bootstrap/pull/29793) - Drop `.text-justify` class. [See #229793](https://github.com/twbs/bootstrap/pull/29793)

View File

@ -0,0 +1,27 @@
<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>

View File

@ -0,0 +1,30 @@
{{- /*
Usage: `table [args]`
`args` are optional and can be one of the following:
class: any class(es) to be added to the `table` - default ""
simplified: show a simplified version in the examples - default `true`
*/ -}}
{{- $simplified := .Get "simplified" | default true -}}
{{- $table_attributes := "" -}}
{{- $table_content := " ...\n" -}}
{{- with .Get "class" -}}
{{- $table_attributes = printf ` class="%s"` . -}}
{{- end -}}
{{- if eq $simplified "false" -}}
{{- $table_content = partialCached "table-content" . -}}
{{- end -}}
{{- $table := printf "<table%s>\n%s</table>" $table_attributes $table_content -}}
<div class="bd-example">
<table{{ with .Get "class" }} class="{{ . }}"{{ end }}>
{{ partialCached "table-content" . }}
</table>
</div>
{{- highlight $table "html" "" -}}