Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fixed Table Header with Scrolling Page Body

Initially scrolling, then fixed table header with scrolling page body.

I would like to put a table somewhere in the middle of my web page that has the following behavior:

  1. Acts like a "normal" html table for the most part... until you scroll past the table's headers
  2. When you scroll past the table's headers, the table headers stays fixed at or near the top of that page, while the rest of the table keeps scrolling with the rest of the page body. This is not the same as a scrolling <tbody> with fixed <thead>.
  3. Bonus points if the table headers disappear if you scroll past the last row of the table.
  4. Bonus points if the table rows disappear as they scroll higher than the headers. (I only need this feature when/if I were to try to place the fixed table header in a different location than at the very top of the page)

It should look something similar to the example given in this fiddle:
http://jsfiddle.net/yeAhU/260/
Except header contents would scroll to the top of the page before becoming fixed and the table contents should not show above the headers as it scrolls.

I have tried slightly tweaking most of the posted answers for "fixed table header scrolling body" questions online but I am not able to get the type of behavior I am looking for from those examples.

I would like the solution to be CSS-based if possible but I am open to other solutions like JS.

I would like the solution to be compatible with both Chrome & Firefox.


QUESTION

Is it possible to do this, and is it possible to do it in just CSS? How?

like image 654
agent provocateur Avatar asked May 16 '16 23:05

agent provocateur


People also ask

How do you make a table header fixed and body scrollable?

We can create such a table with either of the two approaches. By setting the position property to “sticky” and specifying “0” as a value of the top property for the <th> element. By setting the display to “block” for both <thead> and <tbody> element so that we can apply the height and overflow properties to <tbody>.

How do I make my table header fixed while scrolling?

By setting postion: sticky and top: 0, we can create a fixed header on a scroll in HTML tables.

How do I make my table body scrollable?

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; . Anyhow, to set a scrollbar, a display reset is needed to get rid of the table-layout (which will never show scrollbar).


2 Answers

In CSS you could use position:sticky; but since Firefox doesn't mix those two so well yet, you still need to use thead and tbody to break the table-layout to use sticky. ... reset the table-layout on tbody and set table-layout to fixed to help hold columns visually together from thead/tbody ... example :

http://jsfiddle.net/yeAhU/261/ i believe it meets points :1,2,3 (what is 4 actually ? )

http://caniuse.com/#search=sticky

chrome removed it a while ago next link might be helpfull

https://www.sitepoint.com/css-position-sticky-introduction-polyfills/

tbody, thead tr {
  display: table;
  width: 100%;
  table-layout: fixed;
}
td {
  border:1px solid;
}
* {box-sizing:border-box; border-collapse:collapse;}
Additional stuff
<br> Additional stuff
<br> Additional stuff
<br> Additional stuff
<br>

<table width="400" border="0" style="display:block;">
  <thead style="display:block;position: sticky;top:20px;background-color: grey;">
    <tr>
      <td width="200">
        Name
      </td>
      <td width="200">
        Age
      </td>
    </tr>
  </thead>
  <tbody>
  <tr>
    <td width="200">
      &nbsp;
    </td>
    <td width="200">
      &nbsp;
    </td>
  </tr>
  <tr>
    <td>
      John
    </td>
    <td>
      28
    </td>
  </tr>
  <tr>
    <td>
      Jacob
    </td>
    <td>
      22
    </td>
  </tr>
  <tr>
    <td>
      Nicole
    </td>
    <td>
      12
    </td>
  </tr>
  <tr>
    <td>
      Marie
    </td>
    <td>
      15
    </td>
  </tr>
  <tr>
    <td>
      Fabian
    </td>
    <td>
      18
    </td>
  </tr>
  <tr>
    <td>
      Caspar
    </td>
    <td>
      23
    </td>
  </tr>
  <tr>
    <td>
      Elder
    </td>
    <td>
      12
    </td>
  </tr>
  <tr>
    <td>
      Frank
    </td>
    <td>
      17
    </td>
  </tr>
  <tr>
    <td>
      Ling
    </td>
    <td>
      45
    </td>
  </tr>
  <tr>
    <td>
      Pong
    </td>
    <td>
      68
    </td>
  </tr>
  <tr>
    <td>
      Jason
    </td>
    <td>
      67
    </td>
  </tr>
  <tr>
    <td>
      Tony
    </td>
    <td>
      23
    </td>
  </tr>
  <tr>
    <td>
      Britney
    </td>
    <td>
      21
    </td>
  </tr>
  <tr>
    <td>
      Cusac
    </td>
    <td>
      91
    </td>
  </tr>
  <tr>
    <td>
      John
    </td>
    <td>
      28
    </td>
  </tr>
  <tr>
    <td>
      Jacob
    </td>
    <td>
      22
    </td>
  </tr>
  <tr>
    <td>
      Nicole
    </td>
    <td>
      12
    </td>
  </tr>
  <tr>
    <td>
      Marie
    </td>
    <td>
      15
    </td>
  </tr>
  <tr>
    <td>
      Fabian
    </td>
    <td>
      18
    </td>
  </tr>
  <tr>
    <td>
      Caspar
    </td>
    <td>
      23
    </td>
  </tr>
  <tr>
    <td>
      Elder
    </td>
    <td>
      12
    </td>
  </tr>
  <tr>
    <td>
      Frank
    </td>
    <td>
      17
    </td>
  </tr>
  <tr>
    <td>
      Ling
    </td>
    <td>
      45
    </td>
  </tr>
  <tr>
    <td>
      Pong
    </td>
    <td>
      68
    </td>
  </tr>
  <tr>
    <td>
      Jason
    </td>
    <td>
      67
    </td>
  </tr>
  <tr>
    <td>
      Tony
    </td>
    <td>
      23
    </td>
  </tr>
  <tr>
    <td>
      Britney
    </td>
    <td>
      21
    </td>
  </tr>
  <tr>
    <td>
      Cusac
    </td>
    <td>
      91
    </td>
  </tr>
  <tr>
    <td>
      John
    </td>
    <td>
      28
    </td>
  </tr>
  <tr>
    <td>
      Jacob
    </td>
    <td>
      22
    </td>
  </tr>
  <tr>
    <td>
      Nicole
    </td>
    <td>
      12
    </td>
  </tr>
  <tr>
    <td>
      Marie
    </td>
    <td>
      15
    </td>
  </tr>
  <tr>
    <td>
      Fabian
    </td>
    <td>
      18
    </td>
  </tr>
  <tr>
    <td>
      Caspar
    </td>
    <td>
      23
    </td>
  </tr>
  <tr>
    <td>
      Elder
    </td>
    <td>
      12
    </td>
  </tr>
  <tr>
    <td>
      Frank
    </td>
    <td>
      17
    </td>
  </tr>
  <tr>
    <td>
      Ling
    </td>
    <td>
      45
    </td>
  </tr>
  <tr>
    <td>
      Pong
    </td>
    <td>
      68
    </td>
  </tr>
  <tr>
    <td>
      Jason
    </td>
    <td>
      67
    </td>
  </tr>
  <tr>
    <td>
      Tony
    </td>
    <td>
      23
    </td>
  </tr>
  <tr>
    <td>
      Britney
    </td>
    <td>
      21
    </td>
  </tr>
  <tr>
    <td>
      Cusac
    </td>
    <td>
      91
    </td>
  </tr>
  <tr>
    <td>
      John
    </td>
    <td>
      28
    </td>
  </tr>
  <tr>
    <td>
      Jacob
    </td>
    <td>
      22
    </td>
  </tr>
  <tr>
    <td>
      Nicole
    </td>
    <td>
      12
    </td>
  </tr>
  <tr>
    <td>
      Marie
    </td>
    <td>
      15
    </td>
  </tr>
  <tr>
    <td>
      Fabian
    </td>
    <td>
      18
    </td>
  </tr>
  <tr>
    <td>
      Caspar
    </td>
    <td>
      23
    </td>
  </tr>
  <tr>
    <td>
      Elder
    </td>
    <td>
      12
    </td>
  </tr>
  <tr>
    <td>
      Frank
    </td>
    <td>
      17
    </td>
  </tr>
  <tr>
    <td>
      Ling
    </td>
    <td>
      45
    </td>
  </tr>
  <tr>
    <td>
      Pong
    </td>
    <td>
      68
    </td>
  </tr>
  <tr>
    <td>
      Jason
    </td>
    <td>
      67
    </td>
  </tr>
  <tr>
    <td>
      Tony
    </td>
    <td>
      23
    </td>
  </tr>
  <tr>
    <td>
      Britney
    </td>
    <td>
      21
    </td>
  </tr>
  <tr>
    <td>
      Cusac
    </td>
    <td>
      91
    </td>
  </tr></tbody>
</table>

Additional stuff
<br> Additional stuff
<br> Additional stuff
<br> Additional stuff
<br>Additional stuff
<br> Additional stuff
<br> Additional stuff
<br> Additional stuff
<br>Additional stuff
<br> Additional stuff
<br> Additional stuff
<br> Additional stuff
<br>Additional stuff
<br> Additional stuff
<br> Additional stuff
<br> Additional stuff
<br>Additional stuff
<br> Additional stuff
<br> Additional stuff
<br> Additional stuff
<br>Additional stuff
<br> Additional stuff
<br> Additional stuff
<br> Additional stuff
<br>Additional stuff
<br> Additional stuff
<br> Additional stuff
<br> Additional stuff
<br>
like image 158
G-Cyrillus Avatar answered Sep 27 '22 21:09

G-Cyrillus


Here is your solution.. fiddle by Jonas Schubert Erlandsson

<section class="">
  <div class="container">
    <table>
      <thead>
        <tr class="header">
          <th>
            Table attribute name
            <div>Table attribute name</div>
          </th>
          <th>
            Value
            <div>Value</div>
          </th>
          <th>
            Description
            <div>Description</div>
          </th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>align</td>
          <td>left, center, right</td>
          <td>Not supported in HTML5. Deprecated in HTML 4.01. Specifies the alignment of a table according to surrounding text</td>
        </tr>
        <tr>
          <td>bgcolor</td>
          <td>rgb(x,x,x), #xxxxxx, colorname</td>
          <td>Not supported in HTML5. Deprecated in HTML 4.01. Specifies the background color for a table</td>
        </tr>
        <tr>
          <td>border</td>
          <td>1,""</td>
          <td>Specifies whether the table cells should have borders or not</td>
        </tr>
        <tr>
          <td>cellpadding</td>
          <td>pixels</td>
          <td>Not supported in HTML5. Specifies the space between the cell wall and the cell content</td>
        </tr>
        <tr>
          <td>cellspacing</td>
          <td>pixels</td>
          <td>Not supported in HTML5. Specifies the space between cells</td>
        </tr>
        <tr>
          <td>frame</td>
          <td>void, above, below, hsides, lhs, rhs, vsides, box, border</td>
          <td>Not supported in HTML5. Specifies which parts of the outside borders that should be visible</td>
        </tr>
        <tr>
          <td>rules</td>
          <td>none, groups, rows, cols, all</td>
          <td>Not supported in HTML5. Specifies which parts of the inside borders that should be visible</td>
        </tr>
        <tr>
          <td>summary</td>
          <td>text</td>
          <td>Not supported in HTML5. Specifies a summary of the content of a table</td>
        </tr>
        <tr>
          <td>width</td>
          <td>pixels, %</td>
          <td>Not supported in HTML5. Specifies the width of a table</td>
        </tr>
      </tbody>
    </table>
  </div>
</section>

and the css

html, body{
  margin:0;
  padding:0;
  height:100%;
}
section {
  position: relative;
  border: 1px solid #000;
  padding-top: 37px;
  background: #500;
}
section.positioned {
  position: absolute;
  top:100px;
  left:100px;
  width:800px;
  box-shadow: 0 0 15px #333;
}
.container {
  overflow-y: auto;
  height: 200px;
}
table {
  border-spacing: 0;
  width:100%;
}
td + td {
  border-left:1px solid #eee;
}
td, th {
  border-bottom:1px solid #eee;
  background: #ddd;
  color: #000;
  padding: 10px 25px;
}
th {
  height: 0;
  line-height: 0;
  padding-top: 0;
  padding-bottom: 0;
  color: transparent;
  border: none;
  white-space: nowrap;
}
th div{
  position: absolute;
  background: transparent;
  color: #fff;
  padding: 9px 25px;
  top: 0;
  margin-left: -25px;
  line-height: normal;
  border-left: 1px solid #800;
}
th:first-child div{
  border: none;
}
like image 43
Tirthraj Rao Avatar answered Sep 27 '22 21:09

Tirthraj Rao