Quick answer: Bootstrap 5 tables start with a plain table element plus the base table class. Add table-striped for zebra rows, table-hover for a highlight on hover, table-bordered for cell borders, and table-sm for tighter padding. To colour a whole table use a context class such as table-dark; to colour a single row or cell use table-success and friends. Wrap any table that might overflow in div.table-responsive so it scrolls on small screens.

Part of our Bootstrap series. New to the framework? Start with getting started with Bootstrap 5.

A reusable table

The base table plus a named modifier class covers almost everything. Note the semantic thead and tbody — Bootstrap styles them but does not require them, and screen readers rely on them.

<div class="table-responsive">
  <table class="table table-striped table-hover align-middle">
    <thead>
      <tr>
        <th scope="col">#</th>
        <th scope="col">Name</th>
        <th scope="col">Role</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">1</th>
        <td>Ana</td>
        <td>Editor</td>
      </tr>
      <tr>
        <th scope="row">2</th>
        <td>Ben</td>
        <td>Author</td>
      </tr>
    </tbody>
  </table>
</div>

align-middle vertically centres every cell, which fixes the uneven look you get when one row contains a taller element such as a badge or a button. The table-responsive wrapper is the important one: without it a wide table breaks the page layout on a phone instead of scrolling inside its own box.

The modifier classes

ClassWhat it does
tableBase styling — always required
table-stripedZebra-stripes the odd rows in tbody
table-hoverHighlights the row under the pointer
table-borderedAdds a border on all four sides of every cell
table-borderlessRemoves borders entirely
table-smCuts cell padding for dense data
table-darkInverts the table for dark sections
caption-topMoves the caption above the table

Contextual colours and per-cell states

Two sizes of colour exist. Apply one to the whole table to tint it, or apply one to individual rows and cells to flag values — for example a failing score.

<table class="table">
  <tbody>
    <tr class="table-danger">
      <th scope="row">Build 42</th>
      <td>Failed</td>
    </tr>
    <tr>
      <th scope="row">Build 41</th>
      <td class="table-success">Passed</td>
    </tr>
  </tbody>
</table>
Context classTypical meaning
table-primaryInformational, selected row
table-successPassed, valid, completed
table-warningAttention, nearing a limit
table-dangerFailed, invalid, over budget
table-activeThe row the user is working on

Responsive strategies

There are three practical approaches to narrow screens. The default table-responsive scrolls horizontally, which is fine for data tables the reader scans rather than reads. table-responsive-sm (or -md, -lg) only scrolls below that breakpoint and shows the full table above it. The third option is to restructure the table on mobile into a stacked list using CSS — more work, and only worth it when every row must stay fully readable without scrolling. As a rule, pick horizontal scrolling when the reader compares values down a column, and a stacked layout when each row is a self-contained record that someone reads end to end. Whichever you choose, keep the underlying markup a real table so assistive technology can still announce the headers. For tables that follow a design system’s material styling, the differences are covered in the Materialize responsive tables guide and the Angular Material scrollable table post.

Common mistakes

  • No responsive wrapper. A wide table then stretches the whole page and creates horizontal page scroll.
  • Styling tbody rows with table-dark. Put whole-table inversion on the table element, not on rows.
  • Missing scope attributes. Screen readers use them to relate cells to their headers.
  • Using tables for layout. Bootstrap tables are for tabular data; use the grid for layout.
  • Forgetting align-middle. Rows with a button or badge look misaligned without it.

Tables often sit inside a card, and the actions in their last column are usually Bootstrap buttons or a dropdown of row actions.

Struggling to make a dense data screen readable? Ampersand Academy teaches front-end development one-to-one, using your own project as the curriculum.

Official documentation

For the full class reference, every option and the browser support notes, read Bootstrap 5.3 content reference, which covers table styling. It is the source the examples above are drawn from, and it is the first place to check when a class or attribute name changes in a new release.

Frequently asked questions

How do I make a Bootstrap table responsive?

Wrap the table element in a div with class table-responsive. The table then scrolls horizontally inside its box instead of stretching the page on small screens.

What is the difference between table-striped and table-hover?

table-striped shades alternate rows for readability across a wide table. table-hover highlights the row under the pointer, which helps when rows are clickable. They can be combined.

How do I change the colour of one Bootstrap table row?

Add a context class such as table-success or table-danger to that tr. The same classes work on individual td cells when only one value needs highlighting.

How do I make a Bootstrap table more compact?

Add table-sm to reduce the cell padding. Combine it with table-borderless for a clean, dense list that still uses correct table markup.

How do I vertically centre text in Bootstrap table cells?

Add align-middle to the table element. Every cell in the table is then vertically centred, which keeps rows even when some cells are taller than others.

Last updated on · Written by