Tables
Tables can be used to represent tabular data using rows and columns.
Create amazing Typeform-like forms and pages just by writing Markdown!
Overview #
Tables are opt-in, meaning you need to add the base class .table
to a <table>
element, then extend with our optional modifier classes or custom styles. All table styles are not inherited, meaning any nested tables can be styled independent from the parent.
# | First | Last | Age |
---|---|---|---|
1 | Johnathan | Gates | 25 |
2 | Melissa | Waters | 27 |
3 | Jack the Sleeper | ??? |
HTML
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col" class="text-end">Age</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Johnathan</td>
<td>Gates</td>
<td class="text-end">25</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Melissa</td>
<td>Waters</td>
<td class="text-end">27</td>
</tr>
<tr>
<th scope="row">3</th>
<td colspan="2">Jack the Sleeper</td>
<td class="text-end">???</td>
</tr>
</tbody>
</table>
Accented tables #
Different styles are available for applying table accents (via modifier classes). They are generally best applied directly on the <table>
, but some also work on individual rows and cells.
Accented tables Striped rows #
Use .table-striped
to add zebra-striping to any table row within the <tbody>
.
# | First | Last | Age |
---|---|---|---|
1 | Johnathan | Gates | 25 |
2 | Melissa | Waters | 27 |
3 | Richard | Jones | 38 |
HTML
<!-- Striped rows -->
<table class="table table-striped">
...
</table>
Accented tables Striped columns #
Use .table-striped-columns
to add zebra-striping to any table column.
# | First | Last | Age |
---|---|---|---|
1 | Johnathan | Gates | 25 |
2 | Melissa | Waters | 27 |
3 | Richard | Jones | 38 |
HTML
<!-- Striped columns -->
<table class="table table-striped-columns">
...
</table>
Accented tables Hoverable rows #
Add .table-hover
to enable a hover state on table rows within a <tbody>
.
# | First | Last | Age |
---|---|---|---|
1 | Johnathan | Gates | 25 |
2 | Melissa | Waters | 27 |
3 | Richard | Jones | 38 |
HTML
<!-- Hoverable rows -->
<table class="table table-hover">
...
</table>
Accented tables Active tables #
Highlight a table row or cell by adding a .table-active
class.
# | First | Last | Age |
---|---|---|---|
1 | Johnathan | Gates | 25 |
2 | Melissa | Waters | 27 |
3 | Jack the Sleeper | ??? |
HTML
<!-- Active table row and cell -->
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col" class="text-end">Age</th>
</tr>
</thead>
<tbody>
<tr class="table-active">
<th scope="row">1</th>
<td>Johnathan</td>
<td>Gates</td>
<td class="text-end">25</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Melissa</td>
<td>Waters</td>
<td class="text-end">27</td>
</tr>
<tr>
<th scope="row">3</th>
<td class="table-active" colspan="2">Jack the Sleeper</td>
<td class="text-end">???</td>
</tr>
</tbody>
</table>
Variants #
Use the .table-{variant}
contextual classes to apply table variants, where the {variant}
can be primary
, secondary
, success
, danger
, warning
, info
, light
, or dark
. Note that these classes can be used on cells, rows, head, body, foot, or the actual table. Generally speaking, however, it is recommended that they are used sparingly on cells and rows for the maximum visual impact. Also note, all of the above accent styles will work with table variants.
Given below is an example of using the contextual classes on table cells (<td>
or <th>
).
# | Name | Maths | Science | English |
---|---|---|---|---|
1 | Jeff | 84 | 92 | 83 |
2 | Jonah | 100 | 77 | 78 |
3 | Nicole | 84 | 86 | 49 |
4 | Yelena | 91 | 80 | 79 |
5 | Yusuf | 88 | 88 | 67 |
HTML
<!-- Table variants on cells -->
<table class="table table-hover">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Maths</th>
<th scope="col">Science</th>
<th scope="col">English</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Jeff</td>
<td>84</td>
<td class="table-primary">92</td>
<td>83</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jonah</td>
<td class="table-success">100</td>
<td>77</td>
<td>78</td>
</tr>
<tr>
<th scope="row">3</th>
<td>Nicole</td>
<td>84</td>
<td>86</td>
<td class="table-danger">49</td>
</tr>
<tr>
<th scope="row">4</th>
<td>Yelena</td>
<td class="table-primary">91</td>
<td>80</td>
<td>79</td>
</tr>
<tr>
<th scope="row">5</th>
<td>Yusuf</td>
<td>88</td>
<td>88</td>
<td class="table-warning">67</td>
</tr>
</tbody>
</table>
Here's another example of using the contextual classes on table rows.
# | Name | Department | Score |
---|---|---|---|
1 | Tim | Marketing | 8 |
2 | Jenna | Engineering | 9 |
3 | Richard | Sales | 6 |
4 | Kim | Engineering | 4 |
5 | Adam | Sales | 7 |
HTML
<!-- Table variants on rows -->
<table class="table table-hover">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Department</th>
<th scope="col">Score</th>
</tr>
</thead>
<tbody>
<tr class="table-primary">
<th scope="row">1</th>
<td>Tim</td>
<td>Marketing</td>
<td>8</td>
</tr>
<tr class="table-success">
<th scope="row">2</th>
<td>Jenna</td>
<td>Engineering</td>
<td>9</td>
</tr>
<tr>
<th scope="row">3</th>
<td>Richard</td>
<td>Sales</td>
<td>6</td>
</tr>
<tr class="table-danger">
<th scope="row">4</th>
<td>Kim</td>
<td>Engineering</td>
<td>4</td>
</tr>
<tr>
<th scope="row">5</th>
<td>Adam</td>
<td>Sales</td>
<td>7</td>
</tr>
</tbody>
</table>
Accessibility
Using color to add meaning only provides a visual indication, which will not be conveyed to users of assistive technologies like screen readers. Please ensure the meaning is 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.
How do the accented tables and variants work? #
For the accented tables (striped rows, striped columns, hoverable rows, and active tables), we used some techniques to make these effects work for all our table variants:
- We start by setting the background of a table cell with the
--bs-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 an inset box shadow on the table cells with
box-shadow: inset 0 0 0 9999px var(--bs-table-bg-state, var(--bs-table-bg-type, var(--bs-table-accent-bg)))
to layer on top of any specifiedbackground-color
. It uses custom cascade to override thebox-shadow
, regardless the CSS specificity. Because we use a huge spread and no blur, the color will be monotone. Since--bs-table-accent-bg
is set totransparent
by default, we don't have a default box shadow. - When either
.table-striped
,.table-striped-columns
,.table-hover
or.table-active
classes are added, either--bs-table-bg-type
or--bs-table-bg-state
(by default set toinitial
) are set to a semi-transparent color (--bs-table-striped-bg
,--bs-table-active-bg
or--bs-table-hover-bg
) to colorize the background and override default--bs-table-accent-bg
.
Table borders #
Apply or remove borders to tables using the table border classes. Please note, you can also use border utilities on tables along with these classes.
Table borders Bordered tables #
Add .table-bordered
for borders on all sides of the table and cells.
# | First | Last | Age |
---|---|---|---|
1 | Johnathan | Gates | 25 |
2 | Melissa | Waters | 27 |
3 | Richard | Jones | 38 |
HTML
<!-- Bordered table -->
<table class="table table-bordered">
...
</table>
Table borders Tables without borders #
Add .table-borderless
for a table without borders.
# | First | Last | Age |
---|---|---|---|
1 | Johnathan | Gates | 25 |
2 | Melissa | Waters | 27 |
3 | Richard | Jones | 38 |
HTML
<!-- Borderless table -->
<table class="table table-borderless">
...
</table>
Small tables #
Add .table-sm
to make any .table
more compact by reducing all cell padding
.
# | First | Last | Age |
---|---|---|---|
1 | Johnathan | Gates | 25 |
2 | Melissa | Waters | 27 |
3 | Richard | Jones | 38 |
HTML
<!-- Small table -->
<table class="table table-sm">
...
</table>
Table group dividers #
Add a thicker border, darker between table groups—<thead>
, <tbody>
, and <tfoot>
—with .table-group-divider
. Customize the color by changing the border-top-color
property.
# | First | Last | Age |
---|---|---|---|
1 | Johnathan | Gates | 25 |
2 | Melissa | Waters | 27 |
3 | Richard | Jones | 38 |
HTML
<!-- Table group divider -->
<table class="table">
<thead>
...
</thead>
<tbody class="table-group-divider">
...
</tbody>
</table>
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 top by default. Use the vertical align classes to re-align where needed.
Heading | Heading | Heading |
---|---|---|
|
Middle (From table) |
Middle (From table) |
|
Bottom (From row) |
Bottom (From row) |
|
Middle (From table) |
Top (From cell) |
HTML
<!-- Vertical alignment -->
<table class="table table-bordered align-middle">
<thead>
...
</thead>
<tbody>
<tr>
...
</tr>
<tr class="align-bottom">
...
</tr>
<tr>
<td>...</td>
<td>...</td>
<td class="align-top">...</td>
</tr>
</tbody>
</table>
Nesting #
Border styles, active styles, and table variants are not inherited by nested tables.
# | First | Last | Age | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | Johnathan | Gates | 25 | |||||||||
|
||||||||||||
2 | Melissa | Waters | 27 |
HTML
<!-- Nested tables -->
<table class="table table-striped">
<thead>
...
</thead>
<tbody>
...
<tr>
<td colspan="4">
<table class="table mb-0">
...
</table>
</td>
</tr>
...
</tbody>
</table>
Nesting How nesting works #
To prevent any styles from leaking to nested tables, we use the child combinator (>
) selector in our CSS. Since we need to target all the td
and th
tags in the thead
, tbody
, and tfoot
, our selector would look pretty long without it. As such, we use the rather odd looking .table > :not(caption) > * > *
selector to target all td
and th
tags of the .table
, but none of any potential nested tables.
Note that if you add <tr>
tags as direct children of a table, those <tr>
tags will be wrapped in a <tbody>
by default, thus making our selectors work as intended.
Anatomy #
Tables are made up of <thead>
, <tbody>
, and <tfoot>
tags. They can also be labeled using a <caption>
placed inside the <table>
.
Anatomy Table head #
The following example shows a table head marked visually using the .table-secondary
class.
# | First | Last | Age |
---|---|---|---|
1 | Johnathan | Gates | 25 |
2 | Melissa | Waters | 27 |
3 | Richard | Jones | 38 |
HTML
<!-- Table head -->
<table class="table">
<thead class="table-secondary">
...
</thead>
<tbody>
...
</tbody>
</table>
Anatomy Table foot #
The next example shows a table foot, along with the head and body.
# | First | Last | Age |
---|---|---|---|
1 | Johnathan | Gates | 25 |
2 | Melissa | Waters | 27 |
3 | Richard | Jones | 38 |
Footer | Footer | Footer | Footer |
HTML
<!-- Table foot -->
<table class="table">
<thead class="table-secondary">
...
</thead>
<tbody>
...
</tbody>
<tfoot>
...
</tfoot>
</table>
Anatomy 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.
# | First | Last | Age |
---|---|---|---|
1 | Johnathan | Gates | 25 |
2 | Melissa | Waters | 27 |
3 | Richard | Jones | 38 |
HTML
<!-- Table caption -->
<table class="table">
<caption>List of employees</caption>
<thead>
...
</thead>
<tbody>
...
</tbody>
</table>
You can also put the <caption>
on the top of the table with .caption-top
.
# | First | Last | Age |
---|---|---|---|
1 | Johnathan | Gates | 25 |
2 | Melissa | Waters | 27 |
3 | Richard | Jones | 38 |
HTML
<!-- Table caption on top -->
<table class="table caption-top">
<caption class="border-bottom">List of employees</caption>
<thead>
...
</thead>
<tbody>
...
</tbody>
</table>
Responsive tables #
Responsive tables allow tables to be scrolled horizontally with ease. Make any table responsive by wrapping a .table
with the following:
.table-responsive
— across all viewports.table-responsive-{sm|md|lg|xl|xxl}
— breakpoint specific
Please note, you may have to set a width to the containing wrapper.
# | Heading | Heading | Heading | Heading | Heading | Heading | Heading | Heading | Heading |
---|---|---|---|---|---|---|---|---|---|
1 | Item | Item | Item | Item | Item | Item | Item | Item | Item |
2 | Item | Item | Item | Item | Item | Item | Item | Item | Item |
3 | Item | Item | Item | Item | Item | Item | Item | Item | Item |
HTML
<!-- Responsive table -->
<div class="card table-responsive specific-w-300 mw-100 mx-auto rounded-0">
<table class="table">
...
</table>
</div>
Help us grow
Our main goal is to make Halfmoon the go-to framework for building websites, dashboards and tools. If you believe in our mission, consider becoming a sponsor and help us grow.
You can email us directly if you have any queries. We are always happy to answer.
Subscribe for updates
We will notify you when the framework gets a substantial update. No spam ever.
Follow us on Twitter so that you can stay updated that way.