HTML table with fixed header and footer and scrollable body without fixed widths

html table with fixed header and scrollable body jsfiddle
bootstrap table with fixed header and scrollable body
bootstrap responsive table with fixed header and scrollable body
html table with fixed header and scrollable body bootstrap
scroll table body with fixed header css
table with fixed header and sidebar
css fixed header scrolling body
fixed header and footer with scrolling content bootstrap

I want to to create a table with fixed thead and tfoot and a scrollable tbody!

I've tried several approaches, both CSS only and CSS + Javascript, but they are all weak and unreliable and I can easily break them by changing the markup in the demo.

What I want is a way to have the table to behave like a table, this means that the browser will automatically adjust columns based on the content (both at page load that in case of window resize) and that in these scenarios:

  1. if the content of the column's header (thead > tr > th) is larger than the content of the column's body (tbody > tr > td) and larger than the content of the column's footer (tfoot > tr > td) the column should resize based on the size of the column's header

  2. if the content of the column's body (tbody > tr > td) is larger than the content of the column's header (thead > tr > th) and larger than the content of the column's footer (tfoot > tr > td) the column should resize based on the size of the column's body

  3. if the content of the column's footer (tfoot > tr > td) is larger than the content of the column's header (thead > tr > th) and larger than the content of the column's body (tbody > tr > td) the column should resize based on the size of the column's footer

The table below should clarify the scenarios:

<table>
  <thead>
    <tr>
      <th>Header one *leads the width* (case 1)</th>
      <th>Header two</th>
      <th>Header three</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Column one</td>
      <td>Column two *leads the width* (case 2)</td>
      <td>Column three</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <td>Footer one</td>
      <td>Footer two</td>
      <td>Footer three *leads the width* (case 3)</td>
    </tr>
  </tfoot>
</table>

I want a clean (as possible) and reliable solution that will work for the different scenarios, possibly CSS only but also JavaScript is OK (vanilla and clean JavaScript, not jQuery plugins). I don't care about old browser support (it would be great to have it or at least to reach a solution which can degrade gracefully on old browser but it's optional)... I can even accept to use divs instead of table nodes if the final solution works as expected... so in 2016, with modern browser and CSS is this possible somehow?!

EDIT:

The body should scroll vertically and the table may have any number of columns

UPDATE:

I came up with this solution: https://codepen.io/daveoncode/pen/LNomBE but I'm still not 100% satisfied. The main issue is that I can't set different backgrounds for header and footer cells.

UPDATE 2:

it works now!

you can achieve what you want by using a wrapper to your table (div) and make the tr from thead and tfoot a position:absolute

body {
  margin: 0
}

div {
  max-height: 500px;
  overflow-y: auto;
}

table {
  width: 100%
}

thead tr,
tfoot tr {
  position: absolute;
  left: 0;
  right: 15px;
  /* to not cover the scrollbar*/
  background: red
}

thead th,
tfoot td {
  display: inline-block;
}

thead tr {
  top: 0
}

tfoot tr {
  top: 500px/* same value has max-height from div */
}

th,
td {
  width: calc((100%/3) - 5px);
  font-size: 12px;
  text-align: center
}


/*give some space between thead and tfoot*/

tbody tr:first-of-type td {
  padding-top: 35px;
}

tbody tr:last-of-type td {
  padding-bottom: 35px;
}
<div>
  <table>
    <thead>
      <tr>
        <th>Header one *leads the width* (case 1)</th>
        <th>Header two</th>
        <th>Header three</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
      <tr>
        <td>Column one</td>
        <td>Column two *leads the width* (case 2)</td>
        <td>Column three</td>
      </tr>
    </tbody>
    <tfoot>
      <tr>
        <td>Footer one</td>
        <td>Footer two</td>
        <td>Footer three *leads the width* (case 3)</td>
      </tr>
    </tfoot>
  </table>
</div>

Flexible HTML Table with Fixed Header and Footer , Fixed/static/sticky thead and tfoot at the top & bottom of the table, respectively! without any fixed/pre-determined widths, whether that be in px or % . <body> < table> <thead> <tr> <th scope="col">Header 1</th> <th But with my request of a perfectly fixed header & footer with internally scrollable table  It is possible to have a table with a scrolling body and fixed header with only HTML and CSS. The solution is to use three tables. An outer table consists of two rows. The top row contains a table for the heading and the bottom row contains a <div> containing the table for the scrollable body.

HTML table with fixed header and footer and scrollable body without fixed widths using css only. This is simple logic we can use table header put position : sticky method below the example:

table th { position:sticky; top:0; }

Thanks ! :)

HTML/CSS Tricks, Flexible HTML Table with Fixed Header and Footer around a Scrollable Body table headers and footers are fully fluid both in width and height and have no  This simple tricks to solve the problem of making table body scroll-able with fixed table headers. This makes the data table easier to use. Fixed table header when user scroll provides the context

I finally implemented a working solution!

The relevant CSS is the following:

.wrapper {
  width: 90%;
  position: relative;
  border: 1px solid #000;
  background: #efefef;
  overflow: hidden;
  border-radius: 7px;
}

.container {
  overflow-y: auto;
  height: 200px;
  border-top: 41px solid transparent;
  border-bottom: 41px solid transparent;
}

table {
  border-spacing: 0;
  border-collapse: collapse;
  width: 100%;
}

td + td {
  border-left: 1px solid #fff;
}

td, th {
  border-bottom: 1px solid #fff;
  background: #efefef;
  padding: 10px;
}

thead tr th,
tfoot tr td {
  height: 0;
  line-height: 0;
  margin: 0;
  padding-top: 0;
  padding-bottom: 0;
  color: transparent;
  border: none;
  white-space: nowrap;
}

thead tr th div,
tfoot tr td div {
  position: absolute;
  color: #fff;
  height: 20px;
  padding: 10px;
  margin-left: -10px;
  line-height: normal;
  width: 100%;
  z-index: 2;
  text-align: left;
  font-weight: bold;
}

thead tr th div {
  border-left: 1px solid #000;
  border-bottom: 1px solid #000;
}

tfoot tr td div {
  border-top: 1px solid #000;
}

tfoot tr td div.c1,
thead tr th div.c1 {
  background: violet;
}

tfoot tr td div.c2,
thead tr th div.c2 {
  background: green;
}

tfoot tr td div.c3,
thead tr th div.c3 {
  background: yellow;
}

thead tr th div {
  top: 0;
}

tfoot tr td div {
  bottom: 0;
}

thead tr th:first-child div,
tfoot tr td:first-child div {
  border-left: none;
}

And this is the markup:

<div class="wrapper">
  <div class="container">
    <table>
      <thead>
        <tr>
          <th>
            Header one *leads the width* (case 1)
            <div class="c1">
              Header one *leads the width* (case 1)
            </div>
          </th>
          <th>
            Header two
            <div class="c2">
              Header two
            </div>
          </th>
          <th>
            Header three
            <div class="c3">
              Header three
            </div>
          </th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>Column one</td>
          <td>Column two *leads the width* (case 2)</td>
          <td>Column three [first]</td>
        </tr>
        <tr>
          <td>Column one</td>
          <td>Column two *leads the width* (case 2)</td>
          <td>Column three</td>
        </tr>
        <tr>
          <td>Column one</td>
          <td>Column two *leads the width* (case 2)</td>
          <td>Column three</td>
        </tr>
        <tr>
          <td>Column one</td>
          <td>Column two *leads the width* (case 2)</td>
          <td>Column three</td>
        </tr>
        <tr>
          <td>Column one</td>
          <td>Column two *leads the width* (case 2)</td>
          <td>Column three</td>
        </tr>
        <tr>
          <td>Column one</td>
          <td>Column two *leads the width* (case 2)</td>
          <td>Column three</td>
        </tr>
        <tr>
          <td>Column one</td>
          <td>Column two *leads the width* (case 2)</td>
          <td>Column three</td>
        </tr>
        <tr>
          <td>Column one</td>
          <td>Column two *leads the width* (case 2)</td>
          <td>Column three</td>
        </tr>
        <tr>
          <td>Column one</td>
          <td>Column two *leads the width* (case 2)</td>
          <td>Column three</td>
        </tr>
        <tr>
          <td>Column one</td>
          <td>Column two *leads the width* (case 2)</td>
          <td>Column three</td>
        </tr>
        <tr>
          <td>Column one</td>
          <td>Column two *leads the width* (case 2)</td>
          <td>Column three</td>
        </tr>
        <tr>
          <td>Column one</td>
          <td>Column two *leads the width* (case 2)</td>
          <td>Column three</td>
        </tr>
        <tr>
          <td>Column one</td>
          <td>Column two *leads the width* (case 2)</td>
          <td>Column three</td>
        </tr>
        <tr>
          <td>Column one</td>
          <td>Column two *leads the width* (case 2)</td>
          <td>Column three</td>
        </tr>
        <tr>
          <td>Column one</td>
          <td>Column two *leads the width* (case 2)</td>
          <td>Column three</td>
        </tr>
        <tr>
          <td>Column one</td>
          <td>Column two *leads the width* (case 2)</td>
          <td>Column three</td>
        </tr>
        <tr>
          <td>Column one</td>
          <td>Column two *leads the width* (case 2)</td>
          <td>Column three</td>
        </tr>
        <tr>
          <td>Column one</td>
          <td>Column two *leads the width* (case 2)</td>
          <td>Column three</td>
        </tr>
        <tr>
          <td>Column one</td>
          <td>Column two *leads the width* (case 2)</td>
          <td>Column three</td>
        </tr>
        <tr>
          <td>Column one</td>
          <td>Column two *leads the width* (case 2)</td>
          <td>Column three [LATEST]</td>
        </tr>
      </tbody>
      <tfoot>
        <tr>
          <td>
            Footer one
            <div class="c1">
              Footer one
            </div>
          </td>
          <td>
            Footer two
            <div class="c2">Footer two</div>
          </td>
          <td>
            Footer three *leads the width* (case 3)
            <div class="c3">Footer three *leads the width* (case 3)</div>
          </td>
        </tr>
      </tfoot>
    </table>
  </div>
</div>

It works on Chrome, Firefox, Safari and IE11 (I don't know how it behaves on older browsers). See it on codepen: https://codepen.io/daveoncode/pen/LNomBE

Table with fixed header, footer and left column using position:sticky, This simple tricks to solve the problem of making table body scroll-able with fixed table headers. This makes the data table easier to use. Fixed  Possible Duplicate: HTML table with fixed headers? Looking for a solution to create a table with a scrollable body, and a static/fixed header. Searching around seems to produce MANY flaky pie

$.ajax({
          url: "upload.php",
          type: "POST",
          data: fd,
          processData: false,  // tell jQuery not to process the data
          contentType: false   // tell jQuery not to set contentType
        }).done(function( data ) {
            console.log("PHP Output:");
            console.log( data );
        });
        return false;
    }

CSS Table Scrollbar with Fixed Header and Footer, in the HTML editor is what goes within the <body> tags in a basic HTML5 template. Browsers that don't support position:sticky will just get a normal table so no harm done. <div id="table-scroll" class="table-scroll">. 4 <td>Cell content<br> Table with fluid height and width fixed header, footer and first column using  Here is my solution for a fixed table header with scrollable body and aligning columns. The requirements I wanted to achieve were: Fix <thead> while <;tbody&gt; can scroll while

Pure CSS Scrollable Table with Fixed Header, An HTML table is divided into three sections: header (THead), body (TBody) and footer (TFoot). CSS Table Scrollbar with Fixed Header and Footer is no longer able to calculate the width of these columns accurately. Make Fixed Header with CSS. I have written all the CS in the style.css but here Ii will mention some important class which helps us to make this job done successfully. First thing, We make overflow-y:scroll and overflow-x: hidden for the HTML element. Set the 100% height for the body so we don’t need to define the fixed height. You can know

A Scrollable Table With a Fixed Header, 1. use an ovefflow-y:scroll/auto for the tbody html table element; structure that uses the DIV for the header and the TABLE for the table body has a clear markup and looks not natural if the height of the table will be less than the predefined height (no scroll bar). 3. all column must have fixed width, except of the last one . You can easily define this separation in HTML with the <tbody> and the <thead> elements. Now the header and the body of the table are still connected to each other, they will still have the same width (and same scroll properties). Now to let them not 'work' as a table anymore you can set the display: block.

fixed header and scrollable body in table in html angular, Shows you how to create a scrollable table with a fixed header using HTML and a bit of The width of the outer <div> must be larger than the width if the inner table to table) then we need to adjust the header dimension to the body dimension I have implemented complete scrollable table with fixed header and footer  All you need to do is scroll the webpage to see the table rows without knowing the corresponding table headers. To avoid this poor user interface, I’m going to share Bootstrap Table Fixed Header using simple CSS that will make the table header sticky . You no need to scroll up and see the table headers. This small hack will help the users to

Comments
  • Can u use datatables??
  • you want to achieve the vertical or horizontal scrolling?
  • Vertical scrolling
  • What about this answer?
  • I liked this one: codepen.io/w3core/pen/KzNjeo
  • Your example does not work, see here: codepen.io/daveoncode/pen/VaOWgO?editors=1100#anon-login moreover you are assigning width to tds (33%), but the approach should works always (even for table with 4, 10, 50 columns)
  • I'm able to scroll just the tbody through the div and if you have more than 3 columns, just do the math, 100/3 =33.3%, so for 4 columns change to 25%, 100/4=25%
  • the scrolling part is easy, the problem is the column alignment and in your example is not working... moreover, by using a table, the browser is usually smart enough to adjust column size based on content, this means I can have a column of 60% and two of 20%, is not a simple math division ;)
  • if you want to even columns then it is simple math ;), but what you looking for is something like the width:auto
  • Breaks if you make the window narrower than the table content. Although, this can be handled in most cases with a min-width.
  • Also only supports text-align:left for the header. The div's in the header use 100% width of the entire table instead of the th cell.
  • Neat and easy CSS solution, that's only missing the horizontal scrolling. Horizontal scrolling of header & footer might be possible to achieve using javascript.
  • Well, @daveoncode you should ask if it would work on older mozillas and alike because overflow-y was invented by IE and will be compatible way back to IE's of 1997 or of the first Standards complian browser on the market.
  • Only works if table is smaller than page-width. Otherwise, when you x-scroll the content the 'fake' headers created (which are fixed) do not move with the content.