Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flexbox type fixed header, scrollable content for table markup

I am using a data table for which i am using the traditional table markup but what i want is my table start from somewhere in the page and i want my table header to be fixed where it starts and table body should scroll by taking the remaining page height
i am showing a small example here

https://codepen.io/avreddy/pen/eyYBdB?editors=1100

.datatable{
  width: 50%;
  border-collapse: collapse;
}
td{
  text-align: center;
  border: 1px solid;
  padding:5px;
}
<body>
  <div class="somecontent">
    <h4>Some Content</h4><h4>Some Content</h4><h4>Some Content</h4>
  </div>
  <table class="datatable">
    <thead>
      <tr>
      <th>col1</th>
      <th>col2</th>
      <th>col3</th>
      </tr>
    </thead>
    <tbody>
      <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr>
      <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr><tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
        </tr>
    </tbody>
  </table>
</body>


I know we can get it from flex-box responsive table but my limitation is i have to use traditional table markup so if tell me if there is any other way than flexbox responsive table
Thank you

like image 537
Aravind Reddy Avatar asked Dec 12 '17 10:12

Aravind Reddy


People also ask

How will you create a table with a fixed header and scrollable body?

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 keep my table header fixed while scrolling in HTML?

To freeze the row/column we can use a simple HTML table and CSS. HTML: In HTML we can define the header row by <th> tag or we can use <td> tag also. Below example is using the <th> tag. We also put the table in DIV element to see the horizontal and vertical scrollbar by setting the overflow property of the DIV element.


1 Answers

Scrollable table + fixed header tricks cannot work with automatic column widths. This is because they change the display property of tbody element which creates a new (anonymous) table having different column widths.

The best solution I could think of is to create a copy of the table (so that both have identical content and therefore identical column widths) and manipulate them independently.

In the following example, I use jQuery to create a copy of table and visibility: collapse to hide the table header and body:

$(function() {
  $("#button-1").one("click", function() {
    $(".datatable").clone().insertAfter(".datatable");
    $(".datatable").eq(0).addClass("tablehead");
    $(".datatable").eq(1).addClass("tablebody");
  });
});
/* full height */
html { height: 100%; }
body { height: 100%; margin: 0; padding: 0; font: medium monospace; }

/* make last item scrollable and occupy available height */
#wrapper { height: 100%; display: flex; flex-direction: column; overflow-y: hidden; }
#wrapper > :last-child { display: block; flex: 1; overflow-y: auto; }

/* make thead and tbody collapse when JavaScript adds the classes */
.datatable.tablehead tbody { visibility: collapse; }
.datatable.tablebody thead { visibility: collapse; }

/* beautify */
.datatable { border-collapse: collapse; }
.datatable th { border: 1px solid; background-color: #CCC; }
.datatable td { border: 1px solid; padding: 5px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<!--
Notes:

1) Using a wrapper div instead of body because third party scripts
often append elements to body element breaking our flex model

2) Width of second column is determined by thead > 1st row > 2nd column
while width of third column is determined by tbody > 1st row > 3rd column

3) If JavaScript fails the result is still usable
-->

<div id="wrapper">
  <div>
    <h4>Some Content</h4>
    <h4>Some Content</h4>
    <p><button type="button" id="button-1">Convert to fixed header</button></p>
  </div>
  <table class="datatable">
    <thead>
      <tr>
        <th>col 1</th>
        <th>col 2 (wide header)</th>
        <th>col 3</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3 (wide content)</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
    </tbody>
  </table>
</div>

Note that visibility: collapse is not implemented properly in all browsers. Alternate solution is to wrap the two tables inside divs: fixed height div for header table, scrollable div for body table. But then you need to set the height of the header.

like image 130
Salman A Avatar answered Oct 25 '22 09:10

Salman A