Table styles
Choose striped, hoverable, bordered, borderless, compact, and caption treatments that fit the shape of your dataset.
Table styles
Choose row treatments, borders, caption placement, and density from the shape of the dataset. Combine modifiers sparingly so the data remains the strongest visual signal.
Striped, hoverable data table
Combine stripes with hover and focus-within feedback for operational records. Status remains readable as text, and each row’s action is a real control.
| Customer | Status | Plan | Last active | Action |
|---|---|---|---|---|
| Avery Morgan | Active | Team | 2 min ago | |
| Kai Patel | Invited | Starter | Yesterday | |
| Sam Rivera | Active | Business | 3 days ago |
<div class="bs-table-responsive" role="region" tabindex="0" aria-label="Customer database records">
<table class="bs-table bs-table-striped bs-table-hover">
<caption>Recently active customer accounts</caption>
<thead><tr><th scope="col">Customer</th><th scope="col">Status</th><th scope="col">Plan</th><th scope="col">Last active</th><th class="bs-table-cell-actions" scope="col">Action</th></tr></thead>
<tbody>
<tr><th scope="row">Avery Morgan</th><td><span class="bs-badge bs-badge-primary">Active</span></td><td>Team</td><td>2 min ago</td><td class="bs-table-cell-actions"><button class="bs-btn bs-btn-ghost bs-btn-sm" type="button">View</button></td></tr>
<tr><th scope="row">Kai Patel</th><td><span class="bs-badge">Invited</span></td><td>Starter</td><td>Yesterday</td><td class="bs-table-cell-actions"><button class="bs-btn bs-btn-ghost bs-btn-sm" type="button">View</button></td></tr>
<tr><th scope="row">Sam Rivera</th><td><span class="bs-badge bs-badge-primary">Active</span></td><td>Business</td><td>3 days ago</td><td class="bs-table-cell-actions"><button class="bs-btn bs-btn-ghost bs-btn-sm" type="button">View</button></td></tr>
</tbody>
</table>
</div>Bordered and compact
Use cell borders when readers need to trace values across a dense matrix. Compact spacing keeps repeated numeric data scannable.
| Region | Q1 | Q2 | Q3 | Q4 |
|---|---|---|---|---|
| North | 184 | 201 | 218 | 236 |
| South | 142 | 156 | 164 | 179 |
<div class="bs-table-responsive" role="region" tabindex="0" aria-label="Quarterly revenue matrix">
<table class="bs-table bs-table-bordered bs-table-compact">
<caption>Revenue by region, USD thousands</caption>
<thead><tr><th scope="col">Region</th><th class="bs-table-cell-numeric" scope="col">Q1</th><th class="bs-table-cell-numeric" scope="col">Q2</th><th class="bs-table-cell-numeric" scope="col">Q3</th><th class="bs-table-cell-numeric" scope="col">Q4</th></tr></thead>
<tbody>
<tr><th scope="row">North</th><td class="bs-table-cell-numeric">184</td><td class="bs-table-cell-numeric">201</td><td class="bs-table-cell-numeric">218</td><td class="bs-table-cell-numeric">236</td></tr>
<tr><th scope="row">South</th><td class="bs-table-cell-numeric">142</td><td class="bs-table-cell-numeric">156</td><td class="bs-table-cell-numeric">164</td><td class="bs-table-cell-numeric">179</td></tr>
</tbody>
</table>
</div>Borderless comparison
Remove internal rules when the dataset is short and spacing alone provides enough separation. A bottom caption works well for a source or freshness note.
| Entry | CSS | JavaScript |
|---|---|---|
| Core | 70 kB | 14 kB |
| React adapter | — | 9 kB |
<div class="bs-table-responsive" role="region" tabindex="0" aria-label="Package size comparison">
<table class="bs-table bs-table-borderless bs-table-caption-bottom">
<caption>Minified package sizes from the current release.</caption>
<thead><tr><th scope="col">Entry</th><th class="bs-table-cell-numeric" scope="col">CSS</th><th class="bs-table-cell-numeric" scope="col">JavaScript</th></tr></thead>
<tbody>
<tr><th scope="row">Core</th><td class="bs-table-cell-numeric">70 kB</td><td class="bs-table-cell-numeric">14 kB</td></tr>
<tr><th scope="row">React adapter</th><td class="bs-table-cell-numeric">—</td><td class="bs-table-cell-numeric">9 kB</td></tr>
</tbody>
</table>
</div>Row aids
Stripes and hover feedback help scanning but do not communicate selection, status, or validation. Keep those meanings in text and controls.
Density
Use compact cells for repeated operational values, not as a substitute for removing low-value columns or supporting responsive overflow.
Borders
Use full borders for matrices that require tracing in two directions. Prefer default dividers or borderless treatment for shorter comparisons.
Table style API
Style modifiers compose on .bs-table. Keep wide variants inside .bs-table-responsive and use alignment helpers consistently across each column.
| Class | Purpose |
|---|---|
.bs-table-striped | Adds an alternating surface to even body rows. |
.bs-table-hover | Highlights body rows on pointer hover and when a descendant has keyboard focus. |
.bs-table-bordered | Adds vertical cell borders to the default horizontal row dividers. |
.bs-table-borderless | Removes internal cell borders for short, low-density comparisons. |
.bs-table-compact | Reduces cell padding for dense operational datasets. |
.bs-table-caption-bottom | Moves the native caption below the table for a source or freshness note. |
.bs-table-cell-numeric | Right-aligns numeric columns. |
.bs-table-cell-actions | Right-aligns row actions and keeps them together. |
.bs-table-responsive | Contains a styled table when its columns exceed the available width. |
.bs-table | Required base presentation for every table variant. |