Skip to documentation
BoobstrapDocs
Tables

Table fundamentals

Build semantic tables with captions, scoped headers, footers, responsive overflow, sticky headers, sorting controls, and empty states.

Tables guideCopy-ready referencev0.7.0 current
Tables

Table fundamentals

Build tables from meaningful native structure, contain wide datasets in accessible overflow regions, and expose data states without weakening the row-and-column relationships.

Sticky and sortable columns

Constrain a long result set with the sticky-header wrapper. Sorting remains application behavior: update the rows and move aria-sort to the active column after each sort.

Deployment history
CommitResult
Aug 11, 14:32Productiona81f0d2Passed
Aug 11, 12:08Preview7c29be1Passed
Aug 10, 18:41Production663d420Rolled back
Aug 10, 16:05Preview45fb118Passed
Aug 9, 09:27Production31ad902Passed
HTML · Sticky sortable table
<div class="bs-table-responsive bs-table-sticky-header" role="region" tabindex="0" aria-label="Deployment history" style="--bs-table-max-height: 16rem;">
  <table class="bs-table bs-table-hover">
    <caption>Deployment history</caption>
    <thead><tr><th scope="col" aria-sort="descending"><button class="bs-table-sort" type="button">Deployed</button></th><th scope="col"><button class="bs-table-sort" type="button">Environment</button></th><th scope="col">Commit</th><th scope="col">Result</th></tr></thead>
    <tbody>
      <tr><td>Aug 11, 14:32</td><td>Production</td><td><code class="bs-code-inline">a81f0d2</code></td><td>Passed</td></tr>
      <tr><td>Aug 11, 12:08</td><td>Preview</td><td><code class="bs-code-inline">7c29be1</code></td><td>Passed</td></tr>
      <tr><td>Aug 10, 18:41</td><td>Production</td><td><code class="bs-code-inline">663d420</code></td><td>Rolled back</td></tr>
      <tr><td>Aug 10, 16:05</td><td>Preview</td><td><code class="bs-code-inline">45fb118</code></td><td>Passed</td></tr>
      <tr><td>Aug 9, 09:27</td><td>Production</td><td><code class="bs-code-inline">31ad902</code></td><td>Passed</td></tr>
    </tbody>
  </table>
</div>

Empty dataset

Keep the table structure and column context while data is empty. The message should explain the absence; place any recovery action in or immediately after the cell.

Invoices matching the current filters
InvoiceCustomerDue dateAmount
No invoices match these filters.
HTML · Empty table state
<div class="bs-table-responsive" role="region" tabindex="0" aria-label="Filtered invoices">
  <table class="bs-table">
    <caption>Invoices matching the current filters</caption>
    <thead><tr><th scope="col">Invoice</th><th scope="col">Customer</th><th scope="col">Due date</th><th class="bs-table-cell-numeric" scope="col">Amount</th></tr></thead>
    <tbody><tr><td class="bs-table-empty" colspan="4">No invoices match these filters.</td></tr></tbody>
  </table>
</div>

Overflow

Give scrollable wrappers role="region", tabindex="0", and an accessible name. This lets keyboard users reach columns beyond the viewport.

Sorting

Put sorting on real buttons, move aria-sort to the active header, and update it only after the visible rows have been reordered.

Empty states

Keep the caption and headers in place, then span one explanatory .bs-table-empty cell across the body so users retain column context.

Structure and behavior API

Sorting remains application behavior. Use a real button in the header and keep aria-sort synchronized with the rendered row order.

Table fundamentals classes and their purposes
ClassPurposeUse it on
.bs-tableStyles native captions, headers, body rows, cells, and footers.The table.
.bs-table-responsiveContains horizontal or vertical overflow.A wrapper with a role, keyboard target, and accessible name.
.bs-table-sticky-headerConstrains the scroll region and keeps column headers visible. Override --bs-table-max-height as needed.The responsive wrapper.
.bs-table-cell-numericAligns tabular numbers to the right.Matching numeric header and data cells.
.bs-table-cell-actionsRight-aligns and keeps row actions on one line.Matching action header and data cells.
.bs-table-sortStyles a real sort button and reflects its parent header’s sort state.A button inside a column header.
.bs-table-emptyCreates a centered empty-state cell with generous vertical space.One cell spanning every column.