jrdev
jrdev

Reputation: 125

Scrollable table with fixed header and expandable rows

Is it possible to have a scrollable HTML table with a fixed header like:

http://jsfiddle.net/T9Bhm/7/

But the rows are also able to expand onclick like this:

http://jsfiddle.net/Pn3m5/

I have been able to replicate each individually, but not both effects in the same table.

I have tried using the following styling methods:

<style>
    * {box-sizing: border-box} 
    table {
        width: 100%;
    }
    table, td {
        border-collapse: collapse;
        border: 1px solid #000;
    }
    thead {
        display: table; 
        width: 100%
    }
    tbody {
        display: block; 
        max-height: 950px; 
        overflow-y: scroll;
    }
    td, th {
        text-align: center;
        border-bottom: none;
        border-left: none;
    }
</style>

On the expandable row table, but it does not yield the desired result. Is this possible (in CSS or JavaScript)?

Upvotes: 0

Views: 1862

Answers (2)

Chase DeAnda
Chase DeAnda

Reputation: 16441

Working JS Fiddle Here

Had to make a custom script and change the html a bit. To get the sticky headers working, I am using a technique where you have two tables. The first table renders the thead and the second table renders the tbody.

For the expandable rows, you will now create a tr with class expandable-row and a sibling tr (the next element after the expandable row) with a class of content that stores your expandable content:

<tr class="expandable-row">
    <td>
      +
    </td>
    <td>Fred</td>
    <td>30</td>
  </tr>
  <tr class="content">
    <td colspan="3">
      <p>Blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah.</p>
    </td>
  </tr>

I tried to preserve the smooth animation for showing/hiding the content, but it wasn't working great. Uncomment the slideToggle line to add it back.

$(function() {
  $(".content").hide();

  $('.expandable-row').click(function(e) {
    $(this).next('.content').toggle();
    //$(this).next('.content').slideToggle();
  });

});
table {
  border: 1px solid gray;
}

.table-header, .table-body tbody {
  display: table;
  table-layout: fixed;
  width: 100%;
}

.table-header tr,
.table-body tr {
  height: 30px;
  border-bottom: 1px solid gray;
}

.table-body {
  height: 150px;
  overflow: auto;
  display: block;
}

tbody .expandable-row:nth-child(odd) {
  background: #f9f9f9;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Click on a row for more info:
<table class="table-header">
  <thead>
    <tr>
      <th></th>
      <th>Name</th>
      <th>Age</th>
    </tr>
  </thead>
</table>
<table class="table-body">
  <tr class="expandable-row">
    <td>
      +
    </td>
    <td>Fred</td>
    <td>30</td>
  </tr>
  <tr class="content">
    <td colspan="3">
      <p>Blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah.</p>
    </td>
  </tr>
  <tr class="expandable-row">
    <td>
      +
    </td>
    <td>Fred</td>
    <td>30</td>
  </tr>
  <tr class="content">
    <td colspan="3">
      <p>Blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah.</p>
    </td>
  </tr><tr class="expandable-row">
    <td>
      +
    </td>
    <td>Fred</td>
    <td>30</td>
  </tr>
  <tr class="content">
    <td colspan="3">
      <p>Blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah.</p>
    </td>
  </tr><tr class="expandable-row">
    <td>
      +
    </td>
    <td>Fred</td>
    <td>30</td>
  </tr>
  <tr class="content">
    <td colspan="3">
      <p>Blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah.</p>
    </td>
  </tr><tr class="expandable-row">
    <td>
      +
    </td>
    <td>Fred</td>
    <td>30</td>
  </tr>
  <tr class="content">
    <td colspan="3">
      <p>Blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah.</p>
    </td>
  </tr><tr class="expandable-row">
    <td>
      +
    </td>
    <td>Fred</td>
    <td>30</td>
  </tr>
  <tr class="content">
    <td colspan="3">
      <p>Blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah.</p>
    </td>
  </tr><tr class="expandable-row">
    <td>
      +
    </td>
    <td>Fred</td>
    <td>30</td>
  </tr>
  <tr class="content">
    <td colspan="3">
      <p>Blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah.</p>
    </td>
  </tr><tr class="expandable-row">
    <td>
      +
    </td>
    <td>Fred</td>
    <td>30</td>
  </tr>
  <tr class="content">
    <td colspan="3">
      <p>Blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah.</p>
    </td>
  </tr>
</table>

Upvotes: 1

Rob Moll
Rob Moll

Reputation: 3473

I have accomplished this in the past by using a series of divs to act as the table column headers positioned above the scrollable table. Using javascript I changed the width of the top (header) div's to match the width of the td in the table below it using an event handler.

The trick was to set the styling of the divs to display: inline-grid;

Upvotes: 0

Related Questions