Scrollbars on Bootstrap tables can be customized to give your table a unique look and feel. Usually it only takes several lines of CSS and a clever selector. In this tutorial we will create 5 customizations for a scrollable Bootstrap table:
- Enable Vertical Scrolling
- Enable Horizontal Scrolling
- Set a Fixed (Sticky) Header
- Set a Fixed (Sticky) First Column
- Style the X and Y Scrollbars with Width and Color
Here is what we will create in this demo:

Notice the blue scroll thumb color on the grey track. The width is also custom and the first column is sticky.
Bootstrap Table X Scroll (Responsive Horizontal Scroll)
Bootstrap has a cleverly created a class to make horizontal scrolling easy. Horizontal scrolling is also known as scrolling on the X axis, and it is the scroll direction that lets content be responsive to small screen sizes.
The class is aptly named table-responsive
. Interestingly, the Bootstrap docs instruct us to wrap the table element in a div and apply table-responsive
to the div. Here’s the code:
<div className="table-responsive">
<table className="table table-striped table-bordered"/>
</div>
I tested the effect of applying this class directly to the table
element. It did not work even though it applied the same styling properties to the table as it did to the wrapping div. My goal was to avoid an unnecessary div.
Here is a screenshot of dev tools where we can see what styling properties are applied by the table-responsive
class:

In my screenshot I’ve already included code for adding scrollbar styling.
Bootstrap Table Y Scroll (Vertical Scroll)
Bootstrap does not have a class for adding vertical scrolling to a table. However, the two ingredients for vertical scrolling are:
- a parent element with a fixed height or max height
- a child element with a larger height than the parent
In this tutorial I will use the wrapping div that has class table-responsive
and add a height to it:
.table-responsive {
max-height: 400px;
}
My table has a greater height than 400px. For this demo, I gave the table six rows of data at 5rem each (80px each), for a height of 480px.
If you look at the screenshot from the last section, you can see that the table is scrollable along the X axis.
Bootstrap Table Fixed Header
Bootstrap does not have a class that can create a sticky header for us. Instead, we have to add some CSS to the appropriate element.
I made a selector that targets the thead
and makes it sticky. I believe it is better to target the thead
element instead of the row element inside of it, because we want to keep both those elements together visually.
Here’s the code:
thead {
position: sticky;
top: -1px;
background-color: white;
}
I targeted the thead
directly instead of using a class just to keep my code simpler.
There are two parts to creating the sticky header: position
and top
to get the header sticking, and background-color
to make the header opaque. We have to have a top
value so that the header knows when to stick. I set the value to -1px because when it was 0, sometimes a bit of the underlying siblings would peek through above the header.
Here’s an example of the header sticking:

An important note is that the sticky header and sticky first column don’t work well together for the very first cell. You probably should pick one or the other, or perhaps conditionally add them based on scroll position.
Bootstrap Table Fixed First Column
We can also make the first Bootstrap column sticky with some clever CSS. Bootstrap does not have a class that will make the column sticky for us.
In order to make the first ‘column’ sticky, we need to add a class to the first td
element of each row. I also made the selector more specific by targeting .table .sticky-column
so that its background color property would override some default Bootstrap table styling.
Here’s the code:
//CSS
.table .sticky-column {
position: sticky;
left: 0;
background-color: white;
border-right: 2px solid black
}
//HTML or JSX
<td className="sticky-column">Software Engineer 1</td>
Notice that the fundamentals are the same as for the sticky header. However, I added a border-right to make the sticky column stand out more. Be aware that the border scrolls away and this is expected behavior.
Remember that the sticky header and sticky column do not play well together. I recommend choosing one or the other.
We can also make a sticky first column in MUI’s table.
Bootstrap Table Scrollbar Styling
The scrollbars rendered with vertical and horizontal table scrolling can be styled! We can target some webkit selectors on Chrome and Safari browsers and add width and color to the scrollbars.
Here’s the code:
.table-responsive {
&::-webkit-scrollbar {
width: 1.5rem;
height: 1.5rem;
};
&::-webkit-scrollbar-track {
background-color: $secondary;
};
&::-webkit-scrollbar-thumb {
background-color: $primary;
border-radius: 2px;
};
}
I target the table-responsive
class because this is responsible for providing the scrollbars. Inside of it I use the &
and SCSS syntax to create nested selectors that target the following:
-webkit-scrollbar
to set a width on the vertical scrollbar and a height on the horizontal scrollbar-webkit-scrollbar-track
to set a color on the scrollbar “track”. This is the bar the thumb slides inside of-webkit-scrollbar-thumb
to set the thumb color and make it an oval shape
It can be hard to see the rounding of the scroll thumb from border radius. Here is an example with border-radius: 12px
:

We can style scrollbars on tables from many libraries with webkit.
Resources
The Bootstrap table column width can be customized with a few CSS styles, and so can the table row height and padding.
Here is the full code for this demo:
//HTML or JSX code
import "./CustomTableScroll.scss";
export default function CustomTableScroll() {
return (
<div className="table-responsive">
<table className="table table-striped table-bordered">
<thead>
<tr>
<th scope="col" className="sticky-column">Job</th>
<th scope="col">Pay</th>
<th scope="col">Vacation Time</th>
<th scope="col">Extra Column 1</th>
<th scope="col">Extra Column 2</th>
<th scope="col">Extra Column 3</th>
</tr>
</thead>
<tbody>
<tr>
<td className="sticky-column">Software Engineer 1</td>
<td>$70,000</td>
<td>2 Weeks</td>
<td>More Info</td>
<td>More Info</td>
<td>More Info</td>
</tr>
<tr>
<td className="sticky-column">Software Engineer 2</td>
<td>$85,000</td>
<td>3 Weeks</td>
<td>More Info</td>
<td>More Info</td>
<td>More Info</td>
</tr>
<tr>
<td className="sticky-column">Software Engineer 3</td>
<td>$100,000</td>
<td>4 Weeks</td>
<td>More Info</td>
<td>More Info</td>
<td>More Info</td>
</tr>
<tr>
<td className="sticky-column">Senior Software Engineer</td>
<td>$120,000</td>
<td>4 Weeks</td>
<td>More Info</td>
<td>More Info</td>
<td>More Info</td>
</tr>
<tr>
<td className="sticky-column">Expert Software Engineer</td>
<td>$140,000</td>
<td>4 Weeks</td>
<td>More Info</td>
<td>More Info</td>
<td>More Info</td>
</tr>
<tr>
<td className="sticky-column">Awesome Software Engineer</td>
<td>Millions</td>
<td>Loads</td>
<td>More Info</td>
<td>More Info</td>
<td>More Info</td>
</tr>
</tbody>
</table >
</div>
);
}
//SCSS code
@import "bootstrap/scss/bootstrap";
.table-responsive {
max-height: 400px;
&::-webkit-scrollbar {
width: 1.5rem;
height: 1.5rem;
};
&::-webkit-scrollbar-track {
background-color: $secondary;
};
&::-webkit-scrollbar-thumb {
background-color: $primary;
border-radius: 2px;
};
}
tr {
height: 5rem;
}
// thead {
// position: sticky;
// top: -1px;
// background-color: white;
// }
.table .sticky-column {
position: sticky;
left: 0;
background-color: white;
border-right: 2px solid black
}
Just add higher z-index to the table header and all should work well ..