如何在 html 表中显示滚动条

我正在写一个网页,我需要一个 html 表,以维持一个设置的大小。我需要表格顶部的标题始终保持在那里,但是我也需要表格的主体滚动,不管向表格添加了多少行。

我希望它看起来像这个 URL 中的方法2: http://www.cssplay.co.uk/menu/tablescroll.html

我尝试过这样做,但没有出现滚动条:

tbody {
height: 80em;
overflow: scroll;
}
<table border=1 id="qandatbl" align="center">
<tr>
<th class="col1">Question No</th>
<th class="col2">Option Type</th>
<th class="col1">Duration</th>
</tr>


<tbody>
<tr>
<td class='qid'></td>
<td class="options"></td>
<td class="duration"></td>
</tr>
</tbody>
</table>

516445 次浏览

You have to insert your <table> into a <div> that it has fixed size, and in <div> style you have to set overflow: scroll.

Update:

The original answer was written 10 years ago. These days there are lots of good UI components for table views and showing in proper ways. So my suggestion is to go for one of these free or paid components to make sure you already support lots of edge cases which is already implemented in these components.

Something like this?

http://jsfiddle.net/TweNm/

The idea is to wrap the <table> in a non-statically positioned <div> which has an overflow:auto CSS property. Then position the elements in the <thead> absolutely.

#table-wrapper {
position:relative;
}
#table-scroll {
height:150px;
overflow:auto;
margin-top:20px;
}
#table-wrapper table {
width:100%;


}
#table-wrapper table * {
background:yellow;
color:black;
}
#table-wrapper table thead th .text {
position:absolute;
top:-20px;
z-index:2;
height:20px;
width:35%;
border:1px solid red;
}
<div id="table-wrapper">
<div id="table-scroll">
<table>
<thead>
<tr>
<th><span class="text">A</span></th>
<th><span class="text">B</span></th>
<th><span class="text">C</span></th>
</tr>
</thead>
<tbody>
<tr> <td>1, 0</td> <td>2, 0</td> <td>3, 0</td> </tr>
<tr> <td>1, 1</td> <td>2, 1</td> <td>3, 1</td> </tr>
<tr> <td>1, 2</td> <td>2, 2</td> <td>3, 2</td> </tr>
<tr> <td>1, 3</td> <td>2, 3</td> <td>3, 3</td> </tr>
<tr> <td>1, 4</td> <td>2, 4</td> <td>3, 4</td> </tr>
<tr> <td>1, 5</td> <td>2, 5</td> <td>3, 5</td> </tr>
<tr> <td>1, 6</td> <td>2, 6</td> <td>3, 6</td> </tr>
<tr> <td>1, 7</td> <td>2, 7</td> <td>3, 7</td> </tr>
<tr> <td>1, 8</td> <td>2, 8</td> <td>3, 8</td> </tr>
<tr> <td>1, 9</td> <td>2, 9</td> <td>3, 9</td> </tr>
<tr> <td>1, 10</td> <td>2, 10</td> <td>3, 10</td> </tr>
<!-- etc... -->
<tr> <td>1, 99</td> <td>2, 99</td> <td>3, 99</td> </tr>
</tbody>
</table>
</div>
</div>

The accepted answer provided a good starting point, but if you resize the frame, change the column widths, or even change the table data, the headers will get messed up in various ways. Every other example I've seen has similar issues, or imposes some serious restrictions on the table's layout.

I think I've finally got all these problems solved, though. It took a lot of CSS, but the final product is about as reliable and easy to use as a normal table.

Here's an example that has all the required features to replicate the table referenced by the OP: jsFiddle

The colors and borders would have to be changed to make it identical to the reference. Information on how to make those kinds of changes is provided in the CSS comments.

Here's the code:

/*the following html and body rule sets are required only if using a % width or height*/
/*html {
width: 100%;
height: 100%;
}*/
body {
box-sizing: border-box;
width: 100%;
height: 100%;
margin: 0;
padding: 0 20px 0 20px;
text-align: center;
background: white;
}
.scrollingtable {
box-sizing: border-box;
display: inline-block;
vertical-align: middle;
overflow: hidden;
width: auto; /*if you want a fixed width, set it here, else set to auto*/
min-width: 0/*100%*/; /*if you want a % width, set it here, else set to 0*/
height: 188px/*100%*/; /*set table height here; can be fixed value or %*/
min-height: 0/*104px*/; /*if using % height, make this large enough to fit scrollbar arrows + caption + thead*/
font-family: Verdana, Tahoma, sans-serif;
font-size: 15px;
line-height: 20px;
padding: 20px 0 20px 0; /*need enough padding to make room for caption*/
text-align: left;
}
.scrollingtable * {box-sizing: border-box;}
.scrollingtable > div {
position: relative;
border-top: 1px solid black;
height: 100%;
padding-top: 20px; /*this determines column header height*/
}
.scrollingtable > div:before {
top: 0;
background: cornflowerblue; /*header row background color*/
}
.scrollingtable > div:before,
.scrollingtable > div > div:after {
content: "";
position: absolute;
z-index: -1;
width: 100%;
height: 100%;
left: 0;
}
.scrollingtable > div > div {
min-height: 0/*43px*/; /*if using % height, make this large enough to fit scrollbar arrows*/
max-height: 100%;
overflow: scroll/*auto*/; /*set to auto if using fixed or % width; else scroll*/
overflow-x: hidden;
border: 1px solid black; /*border around table body*/
}
.scrollingtable > div > div:after {background: white;} /*match page background color*/
.scrollingtable > div > div > table {
width: 100%;
border-spacing: 0;
margin-top: -20px; /*inverse of column header height*/
/*margin-right: 17px;*/ /*uncomment if using % width*/
}
.scrollingtable > div > div > table > caption {
position: absolute;
top: -20px; /*inverse of caption height*/
margin-top: -1px; /*inverse of border-width*/
width: 100%;
font-weight: bold;
text-align: center;
}
.scrollingtable > div > div > table > * > tr > * {padding: 0;}
.scrollingtable > div > div > table > thead {
vertical-align: bottom;
white-space: nowrap;
text-align: center;
}
.scrollingtable > div > div > table > thead > tr > * > div {
display: inline-block;
padding: 0 6px 0 6px; /*header cell padding*/
}
.scrollingtable > div > div > table > thead > tr > :first-child:before {
content: "";
position: absolute;
top: 0;
left: 0;
height: 20px; /*match column header height*/
border-left: 1px solid black; /*leftmost header border*/
}
.scrollingtable > div > div > table > thead > tr > * > div[label]:before,
.scrollingtable > div > div > table > thead > tr > * > div > div:first-child,
.scrollingtable > div > div > table > thead > tr > * + :before {
position: absolute;
top: 0;
white-space: pre-wrap;
color: white; /*header row font color*/
}
.scrollingtable > div > div > table > thead > tr > * > div[label]:before,
.scrollingtable > div > div > table > thead > tr > * > div[label]:after {content: attr(label);}
.scrollingtable > div > div > table > thead > tr > * + :before {
content: "";
display: block;
min-height: 20px; /*match column header height*/
padding-top: 1px;
border-left: 1px solid black; /*borders between header cells*/
}
.scrollingtable .scrollbarhead {float: right;}
.scrollingtable .scrollbarhead:before {
position: absolute;
width: 100px;
top: -1px; /*inverse border-width*/
background: white; /*match page background color*/
}
.scrollingtable > div > div > table > tbody > tr:after {
content: "";
display: table-cell;
position: relative;
padding: 0;
border-top: 1px solid black;
top: -1px; /*inverse of border width*/
}
.scrollingtable > div > div > table > tbody {vertical-align: top;}
.scrollingtable > div > div > table > tbody > tr {background: white;}
.scrollingtable > div > div > table > tbody > tr > * {
border-bottom: 1px solid black;
padding: 0 6px 0 6px;
height: 20px; /*match column header height*/
}
.scrollingtable > div > div > table > tbody:last-of-type > tr:last-child > * {border-bottom: none;}
.scrollingtable > div > div > table > tbody > tr:nth-child(even) {background: gainsboro;} /*alternate row color*/
.scrollingtable > div > div > table > tbody > tr > * + * {border-left: 1px solid black;} /*borders between body cells*/
<div class="scrollingtable">
<div>
<div>
<table>
<caption>Top Caption</caption>
<thead>
<tr>
<th><div label="Column 1"></div></th>
<th><div label="Column 2"></div></th>
<th><div label="Column 3"></div></th>
<th>
<!--more versatile way of doing column label; requires 2 identical copies of label-->
<div><div>Column 4</div><div>Column 4</div></div>
</th>
<th class="scrollbarhead"/> <!--ALWAYS ADD THIS EXTRA CELL AT END OF HEADER ROW-->
</tr>
</thead>
<tbody>
<tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
<tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
<tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
<tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
<tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
<tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
<tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
<tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
<tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
<tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
<tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
<tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
</tbody>
</table>
</div>
Faux bottom caption
</div>
</div>


<!--[if lte IE 9]><style>.scrollingtable > div > div > table {margin-right: 17px;}</style><![endif]-->

Worth noting, that depending on your purpose (mine was the autofill results of a searchbar) you may want the height to be changeable, and for the scrollbar to only exist if the height exceeds that.

If you want that, replace height: x; with max-height: x;, and overflow:scroll with overflow:auto.

Additionally, you can use overflow-x and overflow-y if you want, and obviously the same thing works horizontally with width : x;

I resolved this problem by separating my content into two tables.

One table is the header row.

The seconds is also <table> tag, but wrapped by <div> with static height and overflow scroll.

If you get to the point where all the mentioned solutions don't work (as it got for me), do this:

  • Create two tables. One for the header and another for the body
  • Give the two tables different parent containers/divs
  • Style the second table's div to allow vertical scroll of its contents.

Like this, in your HTML

<div class="table-header-class">
<table>
<thead>
<tr>
<th>Ava</th>
<th>Alexis</th>
<th>Mcclure</th>
</tr>
</thead>
</table>
</div>
<div class="table-content-class">
<table>
<tbody>
<tr>
<td>I am the boss</td>
<td>No, da-da is not the boss!</td>
<td>Alexis, I am the boss, right?</td>
</tr>
</tbody>
</table>
</div>

Then style the second table's parent to allow vertical scroll, in your CSS

    .table-content-class {
overflow-y: scroll;    // use auto; or scroll; to allow vertical scrolling;
overflow-x: hidden;    // disable horizontal scroll
}

just add on table

style="overflow-x:auto;"

<table border=1 id="qandatbl" align="center" style="overflow-x:auto;">
<tr>
<th class="col1">Question No</th>
<th class="col2">Option Type</th>
<th class="col1">Duration</th>
</tr>


<tbody>
<tr>
<td class='qid'></td>
<td class="options"></td>
<td class="duration"></td>
</tr>
</tbody>
</table>

style="overflow-x:auto;"`

Very easy, just wrap the table in a div that has overflow-y:scroll; and overflow-x:scroll properties, and make the div have a width and length smaller than the table. IT WILL WORK!!!

The CSS: div{ overflow-y:scroll; overflow-x:scroll; width:20px; height:30px; } table{ width:50px; height:50px; }

You can make the table and the DIV around the table be any size you want, just make sure that the DIV is smaller than the table. You MUST contain the table inside of the DIV.

Not sure why no one mentioned to just use the built-in sticky header style for elements. Worked great for me.

.tableContainerDiv {
overflow: auto;
max-height: 80em;
}
th {
position: sticky;
top: 0;
background: white;
}

Put a min-width on the in @media if you need to make responsive (or similar).

see Table headers position:sticky or Position Sticky and Table Headers