If you want tbody
to show a scrollbar, set its display: block;
.
Set display: table;
for the tr
so that it keeps the behavior of a table.
To evenly spread the cells, use table-layout: fixed;
.
DEMO
CSS:
table, tr td {
border: 1px solid red
}
tbody {
display: block;
height: 50px;
overflow: auto;
}
thead, tbody tr {
display: table;
width: 100%;
table-layout: fixed;/* even columns width , fix width of table too*/
}
thead {
width: calc( 100% - 1em )/* scrollbar is average 1em/16px width, remove it from thead width */
}
table {
width: 400px;
}
If tbody
doesn’t show a scroll, because content is less than height
or max-height
, set the scroll any time with: overflow-y: scroll;
. DEMO 2
<editS/updateS>
2019 – 04/2021
- Important note: this approach to making a table scrollable has drawbacks in some cases. (See comments below.) some of the duplicate answers in this thread deserves the same warning by the way
WARNING: this solution disconnects the thead and tbody cell grids; which means that in most practical cases, you will not have the cell alignment you expect from tables. Notice this solution uses a hack to keep them sort-of aligned: thead { width: calc( 100% – 1em ) }
-
Anyhow, to set a scrollbar, a display reset is needed to get rid of the table-layout (which will never show scrollbar).
-
Turning the
<table>
into a grid viadisplay:grid
/contents
will also leave a gap in between header and scrollable part, to mind about. (idem if built from divs) -
overflow:overlay;
has not yet shown up in Firefox ( keep watching it) -
position:sticky
will require a parent container which can be the scrolling one. make sure yourthead
can be sticky if you have a few rows androwspan/colspan
headers in it (it does not with chrome).
So far, there is no perfect solution yet via CSS only. there is a few average ways to choose along so it fits your own table (table-layout:fixed; is .. fixing table and column’s width, but javascript could probably be used to reset those values => exit pure CSS)