Components

Bootstrap Table: Striped, Responsive and Sortable Tables

By the bootstrap.build team · 5 min read · Published

Bootstrap tables are regular HTML tables with one class, .table, that adds clean spacing, horizontal dividers, and a readable default look. Modifier classes add stripes, hover highlighting, borders, compact rows, colored rows, and horizontal scrolling on small screens. This guide covers each option, then the common jobs: aligning cells, stopping text from wrapping, sticky headers, tables that work on phones, and adding sorting and search. Everything is for Bootstrap 5.3.

A basic table

<table class="table">
  <caption>Invoices, November 2026</caption>
  <thead>
    <tr>
      <th scope="col">Invoice</th>
      <th scope="col">Customer</th>
      <th scope="col">Status</th>
      <th scope="col" class="text-end">Amount</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>#1042</td>
      <td>Acme Inc.</td>
      <td>Paid</td>
      <td class="text-end">$1,200.00</td>
    </tr>
    <tr>
      <td>#1043</td>
      <td>Globex</td>
      <td>Overdue</td>
      <td class="text-end">$860.00</td>
    </tr>
  </tbody>
</table>

Use real table markup: <thead> for the header row, <th scope="col"> for column headings, and <th scope="row"> for a row heading in the first column. Screen readers use these to announce which heading a cell belongs to. <caption> names the table; Bootstrap puts it below the table, or above it with caption-top on the table.

Right-align columns of numbers with text-end, so the digits line up.

Table styles

Class What it does
table-striped Shades every other row
table-striped-columns Shades every other column
table-hover Highlights the row under the pointer
table-bordered Borders on every cell
table-borderless No borders at all
table-sm Halves the cell padding for compact tables
table-group-divider A thicker line between groups, on a <tbody> or <tfoot>

Combine them freely:

<table class="table table-striped table-hover table-sm">...</table>

Colored tables, rows, and cells

Add a color class to the table, a row, or a single cell:

<table class="table table-dark">...</table>

<tr class="table-success">...</tr>
<tr class="table-danger">...</tr>
<td class="table-warning">Pending</td>

The colors are table-primary, table-secondary, table-success, table-danger, table-warning, table-info, table-light, and table-dark. table-active highlights a row or cell as selected. In dark mode, plain tables switch colors on their own, so you rarely need table-dark.

Colored rows don’t reach screen readers, so put the status in text too, as a word or a badge.

Responsive tables

A wide table overflows a phone screen. Wrap it in .table-responsive to let it scroll sideways:

<div class="table-responsive">
  <table class="table">...</table>
</div>

To scroll only below a breakpoint, use table-responsive-sm, -md, -lg, -xl, or -xxl. For example, table-responsive-md scrolls on screens narrower than 768px and behaves normally above that.

Scrolling works, but for tables people need to read on phones, also consider:

  • Hiding less important columns on small screens with d-none d-md-table-cell on those <th> and <td> cells.
  • Turning rows into cards on phones, with a separate card list shown below the breakpoint and the table hidden there.

Vertical alignment and wrapping

Cells line up at the top by default. Align a whole table, a row, or a cell with the vertical-align utilities:

<table class="table align-middle">...</table>
<tr class="align-bottom">...</tr>

To keep a cell on one line, add text-nowrap. To cut off long text with an ellipsis, give the cell a maximum width and add text-truncate:

<td class="text-truncate" style="max-width: 220px;">A very long product description that would otherwise wrap</td>

Column widths

Tables size columns to their content. To fix widths, set them on the heading cells with the sizing utilities or inline styles:

<th scope="col" class="w-50">Description</th>
<th scope="col" style="width: 120px;">Date</th>

For widths that never change with content, add style="table-layout: fixed" to the table.

A table with actions

<table class="table table-hover align-middle">
  <thead>
    <tr><th scope="col">Name</th><th scope="col">Role</th><th scope="col"><span class="visually-hidden">Actions</span></th></tr>
  </thead>
  <tbody>
    <tr>
      <td>
        <div class="d-flex align-items-center gap-2">
          <img src="ana.jpg" class="rounded-circle" width="32" height="32" alt="">
          <span>Ana Lopez</span>
        </div>
      </td>
      <td><span class="badge text-bg-primary">Admin</span></td>
      <td class="text-end">
        <button class="btn btn-sm btn-outline-secondary" type="button">Edit</button>
      </td>
    </tr>
  </tbody>
</table>

The empty-looking actions heading has visually hidden text so screen readers still name the column. Row buttons are covered in the buttons guide, and action menus in the dropdown guide.

Sticky table header

Keep the header visible while a long table scrolls inside a box:

<div class="table-responsive" style="max-height: 400px;">
  <table class="table">
    <thead class="sticky-top bg-body">...</thead>
    <tbody>...</tbody>
  </table>
</div>

sticky-top pins the header, and bg-body gives it a background so rows don’t show through it.

Sorting, search, and pagination

Bootstrap styles tables but doesn’t sort or filter them. Options:

  • Server-side: render sorted, filtered pages on the server, with links in the headings (?sort=amount) and Bootstrap pagination below. Best for large data sets.
  • A small script: for a few hundred rows, sorting in the browser is a short function.
  • A library: Tabulator, AG Grid, and Grid.js add sorting, filtering, paging, and editing. The older “Bootstrap Table” and DataTables plugins also have Bootstrap 5 styles.

A minimal client-side sort:

document.querySelectorAll('th[data-sort]').forEach(th => {
  th.style.cursor = 'pointer'
  th.addEventListener('click', () => {
    const tbody = th.closest('table').querySelector('tbody')
    const index = [...th.parentNode.children].indexOf(th)
    const asc = th.dataset.dir !== 'asc'
    th.dataset.dir = asc ? 'asc' : 'desc'
    const rows = [...tbody.rows].sort((a, b) =>
      a.cells[index].innerText.localeCompare(b.cells[index].innerText, undefined, { numeric: true }) * (asc ? 1 : -1))
    tbody.append(...rows)
  })
})

Add data-sort to any <th> that should sort its column. For screen readers, also set aria-sort="ascending" or "descending" on the sorted heading.

Style tables

Tables use CSS variables:

.table {
  --bs-table-striped-bg: #f5f7ff;
  --bs-table-hover-bg: #eef2ff;
  --bs-table-border-color: #e4e8f5;
}
.table > :not(caption) > * > * { padding: .75rem 1rem; }

In Sass, $table-cell-padding-y and $table-cell-padding-x (both .5rem), $table-striped-bg-factor, $table-hover-bg-factor, and $table-border-color set the defaults. See Bootstrap Sass variables explained.

For a table of recent orders inside a full admin dashboard, see the Bootstrap admin template guide.

FAQ

How do I make a table in Bootstrap 5?

Add the table class to a normal HTML <table> with <thead>, <th scope="col"> headings, and <tbody>. Add table-striped, table-hover, table-bordered, or table-sm for other styles.

How do I make a Bootstrap table responsive?

Wrap the table in <div class="table-responsive"> so it scrolls sideways on small screens. Use table-responsive-md or another breakpoint to scroll only below that width.

How do I add stripes to a Bootstrap table?

Add table-striped to the <table> to shade every other row, or table-striped-columns to shade every other column. Change the shade with the --bs-table-striped-bg CSS variable.

How do I vertically center content in a Bootstrap table?

Add align-middle to the table, a row, or a cell. It applies vertical-align: middle, which lines up text, images, and buttons in the middle of each row.

How do I add sorting to a Bootstrap table?

Bootstrap doesn’t sort tables itself. Sort on the server with links in the column headings, add a short script that reorders the rows when a heading is clicked, or use a library such as Tabulator, Grid.js, or DataTables with its Bootstrap 5 styling.

Try it in the builder

Make these changes visually with a live preview, then export clean Bootstrap Sass or CSS.

Open the Builder