2026-10-30 · Q&A guide

Bootstrap Scrollable Table with Fixed Header: Quick CSS Fix

Create a Bootstrap table that scrolls vertically while keeping the header fixed, using minimal CSS and no JavaScript.

Problem & Common Pitfalls

When a table contains many rows, the header often scrolls away, making column headings hard to read. A naive approach of setting overflow on the <tbody> breaks column alignment because each row becomes a block element. The result is a messy layout where columns shift or wrap unexpectedly.

Pure CSS Fix for Fixed Header

Wrap the table in a container, give the <thead> a fixed height, and make the <tbody> scrollable. Use table-layout:fixed to keep column widths stable and display:block on thead and tbody. The following CSS achieves a clean, column‑aligned scrollable body:

.scroll-table {
  width: 100%;
  table-layout: fixed;
}
.scroll-table thead {
  display: block;
  width: 100%;
}
.scroll-table tbody {
  display: block;
  height: 250px;
  overflow-y: auto;
}
.scroll-table th, .scroll-table td {
  width: 16.66%; /* 6 columns */
  text-align: left;
}
.scroll-table thead tr, .scroll-table tbody tr {
  display: flex;
}
.scroll-table thead th, .scroll-table tbody td {
  flex: 1;
}

Responsive Wrapper Trick

Bootstrap’s .table-responsive class adds horizontal scrolling on small screens. Combine it with the above CSS to keep the header fixed while the body scrolls vertically:

<div class="table-responsive">
  <table class="table table-hover scroll-table">
    <thead>…</thead>
    <tbody>…</tbody>
  </table>
</div>

Alternative with Flexbox

If you prefer not to use display:block on table elements, wrap rows in a flex container. This method keeps the semantic <table> structure and works well with Bootstrap’s grid utilities:

.flex-table {
  display: flex;
  flex-direction: column;
  width: 100%;
}
.flex-table thead {
  flex: 0 0 auto;
}
.flex-table tbody {
  flex: 1 1 auto;
  overflow-y: auto;
  height: 250px;
}
.flex-table tr {
  display: flex;
}
.flex-table th, .flex-table td {
  flex: 1;
  min-width: 0;
}

Performance & Accessibility Tips

Avoid heavy JavaScript for scrolling; pure CSS is faster and more accessible. Ensure the table has a <caption> for screen readers, use scope="col" on <th> elements, and keep the header row short to reduce vertical space. Test the layout in Chrome, Firefox, and Safari to confirm consistent column widths.

Takeaway: Use table-layout:fixed with display:block on thead and tbody, or a flexbox wrapper, to create a clean scrollable Bootstrap table with a fixed header.

People also ask

Can I use this technique with Bootstrap 5?

Yes. The same CSS applies; just replace .table-hover with the appropriate Bootstrap 5 classes.

Does this affect pagination?

No. The scrollable body is independent of pagination logic; you can still paginate server‑side or client‑side.

Will this work with dynamic column widths?

If columns vary, use width: auto and table-layout:auto, but you must recalc widths on resize or use JavaScript to sync header and body cells.

Inspired by a public discussion on Stack Overflow. This article is an original explanation for learners.

← All posts