Tag thead pinned at the top and tbody with scroll bar in table in HTML

Asked

Viewed 4,421 times

2

I want a table with the tag thead fixed at the top and tbody with a scroll vertically, I found some solutions that use only CSS, but use the property display, removing the default behavior from the table and making it the same in block, making it impossible to use self-adjusting fields, creating a misalignment with title and data.

dbgrid
{
    text-align: left;
    width: 100%; 
}
.dbgrid table
{
    width: 100%;
    text-align: left;
    border-collapse: collapse;
    vertical-align: top;
    white-space: nowrap;
    text-overflow: ellipsis;
}
.dbgrid thead
{
    background: #063b53;    
    color: #fff;
    width:100%;
}
.dbgrid tr
{   
    width:100%;
    box-sizing: border-box;
    padding: 3px 10px;
    text-align: left;
    
}
.dbgrid thead tr
{
    color:#fff;
    background:#000;
}
.dbgrid tbody tr
{
    color:#000;
    background:#FFF;
}
/** Testar barra de scroll com height:40px; **/
.dbgrid tbody
{
    width:100%;
    text-align: left;  
    overflow-y: scroll;
    overflow-x: hidden;
    height:40px;
    
  /** ao utilizar display:block funciona, porém perde algumas propriedades da tabela, como alinhar o título da coluna. 
  
  display:block;
  
  **/
    
}
<div class="dbgrid">
    <table>
        <thead>
            <tr>
                <th>Código</th>
                <th>Nome</th>
                <th>Sobrenome</th>
                <th>Endereço</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>01</td>
                <td>João</td>
                <td>Silva</td>
                <td>Avenida Genérica N 12345</td>
            </tr>
            <tr>
                <td>02</td>
                <td>Pedro</td>
                <td>Souza</td>
                <td>Rua Comum N 65478 - Bairro Qualquer</td>
            </tr>
            <tr>
                <td>03</td>
                <td>João</td>
                <td>Paulo</td>
                <td>-</td>
            </tr>
            <tr>
                <td>04</td>
                <td>Maria</td>
                <td>Carvalho</td>
                <td>Avenida Qualquer</td>
            </tr>
        </tbody>
    </table>
</div>

This is the table I have, remove the comment from display:block and then the scroll will work, but the fields will misalign.

Is there a solution? I accept solutions that use pure CSS or Javascript, or some combination of both.

Grateful.

  • I had to do something similar, only the scroll was horizontal, then I did it with two tables and Divs that enclosed them to determine the scroll.

  • I also have the possibility to use a div to encompass everything, but the problem is that the scroll is vertical, and I would like the title of the columns to be maintained, in this case if you used the same solution as yours, the title of the columns would scroll next to the scroll.

  • You make a div for the title and another for tbody, then scroll you apply only in tbody div, like that example, there at the end of the page on the tab cards, just do it backwards

  • It is not possible to use this logic vertically, as you cannot use Ivds in the table that are not within the td or th element, it would act in the same way as setting tbody to block. As I pointed out earlier, the solution is perfect for horizontal use, but vertical does not work.

  • But it is to put div inside the table no, it would be one to simulate thead and another for tbody.

1 answer

2


There are already some solutions to this Renan. Here are some interesting:
Using in conjunction with JS:

        // Change the selector if needed
var $table = $('table.scroll'),
    $bodyCells = $table.find('tbody tr:first').children(),
    colWidth;

// Adjust the width of thead cells when window resizes
$(window).resize(function() {
    // Get the tbody columns width array
    colWidth = $bodyCells.map(function() {
        return $(this).width();
    }).get();
    
    // Set the width of thead columns
    $table.find('thead tr').children().each(function(i, v) {
        $(v).width(colWidth[i]);
    });    
}).resize(); // Trigger resize handler
            table.scroll {
                width: 100%; /* Optional */
                /* border-collapse: collapse; */
                border-spacing: 0;
                border: 2px solid black;
            }

            table.scroll tbody,
            table.scroll thead { display: block; }

            thead tr th { 
                height: 30px;
                line-height: 30px;
                /*text-align: left;*/
            }

            table.scroll tbody {
                height: 100px;
                overflow-y: auto;
                overflow-x: hidden;
            }

            tbody { border-top: 2px solid black; }

            tbody td, thead th {
                width: 20%; /* Optional */
                border-right: 1px solid black;
            }

            tbody td:last-child, thead th:last-child {
                border-right: none;
            }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table class="scroll">
    <thead>
        <tr>
            <th>Head 1</th>
            <th>Head 2</th>
            <th>Head 3</th>
            <th>Head 4</th>
            <th>Head 5</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Content 1</td>
            <td>Content 2</td>
            <td>Content 3</td>
            <td>Content 4</td>
            <td>Content 5</td>
        </tr>
        <tr>
            <td>Content 1</td>
            <td>Lorem ipsum dolor sit amet.</td>
            <td>Content 3</td>
            <td>Content 4</td>
            <td>Content 5</td>
        </tr>
        <tr>
            <td>Content 1</td>
            <td>Content 2</td>
            <td>Content 3</td>
            <td>Content 4</td>
            <td>Content 5</td>
        </tr>
        <tr>
            <td>Content 1</td>
            <td>Content 2</td>
            <td>Content 3</td>
            <td>Content 4</td>
            <td>Content 5</td>
        </tr>
        <tr>
            <td>Content 1</td>
            <td>Content 2</td>
            <td>Content 3</td>
            <td>Content 4</td>
            <td>Content 5</td>
        </tr>
        <tr>
            <td>Content 1</td>
            <td>Content 2</td>
            <td>Content 3</td>
            <td>Content 4</td>
            <td>Content 5</td>
        </tr>
        <tr>
            <td>Content 1</td>
            <td>Content 2</td>
            <td>Content 3</td>
            <td>Content 4</td>
            <td>Content 5</td>
        </tr>
    </tbody>
</table>

Reference: http://jsfiddle.net/hashem/CrSpu/554/

Using pure CSS:

.fixed {
  width:350px;
  table-layout: fixed;
  border-collapse: collapse;
}
.fixed th {
  text-decoration: underline;
}
.fixed th,
.fixed td {
  padding: 5px;
  text-align: left;
  min-width: 200px;
}


.fixed thead {
  background-color: red;
  color: #fdfdfd;
}
.fixed thead tr {
  display: block;
  position: relative;
}
.fixed tbody {
  display: block;
  overflow: auto;
  width: 100%;
  height: 100px;
  overflow-y: scroll;
    overflow-x: hidden;
}
<table class="fixed">
    <thead>
        <tr>
            <td>Name</td>
            <td>phone</td>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>AAAA</td>
            <td>323232</td>
        </tr>
        <tr>
            <td>BBBBB</td>
            <td>323232</td>
        </tr>
        <tr>
            <td>CCCCC</td>
            <td>3435656</td>
        </tr>
      <tr>
            <td>AAAA</td>
            <td>323232</td>
        </tr>
        <tr>
            <td>BBBBB</td>
            <td>323232</td>
        </tr>
        <tr>
            <td>CCCCC</td>
            <td>3435656</td>
        </tr>
    </tbody>
</table>

Reference: http://jsbin.com/vujoyubu/1/edit?html,css,output

Just adapt to your need now.
I hope I’ve helped.

  • The first solution is a good one, the second unfortunately uses fixed width for the columns, I will test the first, thank you Ricardo Moura.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.