Tabela HTML com 100% de largura, com rolagem vertical dentro do corpo

423

Como definir <table>100% de largura e colocar apenas dentro da <tbody>rolagem vertical para alguma altura?

rolagem vertical dentro do corpo

table {
    width: 100%;
    display:block;
}
thead {
    display: inline-block;
    width: 100%;
    height: 20px;
}
tbody {
    height: 200px;
    display: inline-block;
    width: 100%;
    overflow: auto;
}
  
<table>
  <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>
  </tbody>
</table>

Quero evitar adicionar algumas div adicionais, tudo o que quero é uma tabela simples como essa e quando estou tentando alterar a exibição table-layout, positione muito mais na tabela CSS não funcionam bem com largura de 100% apenas com largura fixa em px.

Marko S
fonte
Não tenho muita certeza do que você deseja alcançar. olhar para este: jsfiddle.net/CrSpu e diga como você quer que ele se comporte
x4rf41
2
Eu sei, mas olhar .. th e td não são mostrados a largura total .. postimg.org/image/mgd630y61
Marko S
Relacionados: stackoverflow.com/questions/1019938/...
Christophe Roussy

Respostas:

675

Para tornar o <tbody>elemento rolável, precisamos alterar a maneira como ele é exibido na página, ou seja, usá-lo display: block;para exibi-lo como um elemento no nível do bloco.

Como alteramos a displaypropriedade de tbody, também devemos alterar essa propriedade para o theadelemento para impedir a quebra do layout da tabela.

Então nós temos:

thead, tbody { display: block; }

tbody {
    height: 100px;       /* Just for the demo          */
    overflow-y: auto;    /* Trigger vertical scroll    */
    overflow-x: hidden;  /* Hide the horizontal scroll */
}

Navegadores da Web exibem os elementos theade tbodycomo grupo de linhas ( table-header-groupe table-row-group) por padrão.

Depois que mudamos isso, os trelementos internos não preenchem todo o espaço do contêiner.

Para consertar isso, precisamos calcular a largura das tbodycolunas e aplicar o valor correspondente aothead colunas via JavaScript.

Colunas de largura automática

Aqui está a versão jQuery da lógica acima:

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

// 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]);
});    

E aqui está a saída (no Windows 7 Chrome 32) :

rolagem vertical dentro do corpo

DEMO DE TRABALHO .

Tabela de largura total, colunas de largura relativa

Conforme o Pôster original fosse necessário, poderíamos expandir tablepara 100% de widthseu contêiner e, em seguida, usar um relativo ( Porcentagem ) widthpara cada coluna da tabela.

table {
    width: 100%; /* Optional */
}

tbody td, thead th {
    width: 20%;  /* Optional */
}

Como a tabela possui um layout de (tipo de) fluido , devemos ajustar a largura das theadcolunas quando o contêiner é redimensionado.

Portanto, devemos definir as larguras das colunas assim que a janela for redimensionada:

// Adjust the width of thead cells when *window* resizes
$(window).resize(function() {
    /* Same as before */ 
}).resize(); // Trigger the resize handler once the script runs

A saída seria:

Mesa fluida com rolagem vertical dentro do corpo

DEMO DE TRABALHO .


Suporte ao navegador e alternativas

Testei os dois métodos acima no Windows 7 por meio das novas versões dos principais navegadores da Web (incluindo o IE10 +) e funcionou.

No entanto, ele não funciona corretamente no IE9 e abaixo.

Isso ocorre porque, em um layout de tabela , todos os elementos devem seguir as mesmas propriedades estruturais.

Usando display: block;os elementos <thead>e <tbody>, quebramos a estrutura da tabela.

Redesenhar o layout via JavaScript

Uma abordagem é redesenhar o layout da tabela (inteira). Use o JavaScript para criar um novo layout rapidamente e manipule e / ou ajuste as larguras / alturas das células dinamicamente.

Por exemplo, dê uma olhada nos seguintes exemplos:

Mesas de aninhamento

Essa abordagem usa duas tabelas aninhadas com uma div contendo. A primeira tablepossui apenas uma célula que possui a dive a segunda tabela é colocada dentro desse divelemento.

Verifique as tabelas de rolagem vertical no CSS Play .

Isso funciona na maioria dos navegadores da web. Também podemos fazer a lógica acima dinamicamente via JavaScript.

Tabela com cabeçalho fixo na rolagem

Como o objetivo de adicionar uma barra de rolagem vertical ao <tbody>é exibir o cabeçalho da tabela na parte superior de cada linha, poderíamos posicionar o theadelemento para permanecer fixedna parte superior da tela.

Aqui está uma demonstração de trabalho dessa abordagem, realizada por Julien .
Possui um suporte promissor ao navegador da web.

E aqui uma implementação CSS pura por Willem Van Bockstal .


A solução CSS pura

Aqui está a resposta antiga. É claro que adicionei um novo método e refinei as declarações CSS.

Mesa com Largura Fixa

Nesse caso, tabledeve ter um valor fixo width (incluindo a soma das larguras das colunas e a largura da barra de rolagem vertical) .

Cada coluna deve ter uma largura específica e a última coluna do theadelemento precisa de uma largura maior, igual à largura das outras + à largura da barra de rolagem vertical.

Portanto, o CSS seria:

table {
    width: 716px; /* 140px * 5 column + 16px scrollbar width */
    border-spacing: 0;
}

tbody, thead tr { display: block; }

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

tbody td, thead th {
    width: 140px;
}

thead th:last-child {
    width: 156px; /* 140px + 16px scrollbar width */
}

Aqui está a saída:

Mesa com Largura Fixa

DEMO DE TRABALHO .

Mesa com 100% de largura

Nesta abordagem, o tabletem uma largura de 100%e para cada um , the tdo valor da widthpropriedade deve ser menor que 100% / number of cols.

Além disso, precisamos reduzir a largura de theadcomo valor da largura da barra de rolagem vertical.

Para fazer isso, precisamos usar a calc()função CSS3 , da seguinte maneira:

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

thead, tbody, tr, th, td { display: block; }

thead tr {
    /* fallback */
    width: 97%;
    /* minus scroll bar width */
    width: -webkit-calc(100% - 16px);
    width:    -moz-calc(100% - 16px);
    width:         calc(100% - 16px);
}

tr:after {  /* clearing float */
    content: ' ';
    display: block;
    visibility: hidden;
    clear: both;
}

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

tbody td, thead th {
    width: 19%;  /* 19% is less than (100% / 5 cols) = 20% */
    float: left;
}

Aqui está a demonstração online .

Nota: Essa abordagem falhará se o conteúdo de cada coluna quebrar a linha, ou seja, o conteúdo de cada célula deve ser curto o suficiente .


A seguir, há dois exemplos simples de solução CSS pura que eu criei no momento em que respondi a essa pergunta.

Aqui está a demonstração do jsFiddle v2 .

Versão antiga: jsFiddle Demo v1

Hashem Qolami
fonte
17
Com display: blockvocê perde propriedades de tabela como largura da coluna compartilhada entre thead e tbody. Sei que você corrigiu isso definindo, width: 19.2%mas, caso não conheçamos a largura de cada coluna com antecedência, isso não funcionará.
Samb
10
Esse código parece assumir que as células do corpo sempre serão maiores que as células do cabeçalho.
Adam Donahue
2
Não está funcionando quando height: 100%(quando você deseja que a tabela se expanda para a parte inferior da página).
AlikElzin-Kilaka
2
Isso também funciona de maneira fantástica com as ng-repeattabelas AngularJS . Não sei por que existem todas as bibliotecas com cabeçalhos de tabela fixos e o que não acontece quando há essa solução.
chakeda
2
Você pode melhorar isso um pouco mais com a box-sizingpropriedade, para que bordas de duas espessuras diferentes não atinjam o alinhamento da coluna.
Ricca
89

Na solução a seguir, a tabela ocupa 100% do contêiner pai, sem necessidade de tamanhos absolutos. É CSS puro, o layout flexível é usado.

Aqui está como fica: insira a descrição da imagem aqui

Possíveis desvantagens:

  • a barra de rolagem vertical está sempre visível, independentemente de ser necessária;
  • o layout da tabela é fixo - as colunas não são redimensionadas de acordo com a largura do conteúdo (você ainda pode definir qualquer largura de coluna que desejar explicitamente);
  • existe um tamanho absoluto - a largura da barra de rolagem, que é de cerca de 0,9 m para os navegadores que eu pude verificar.

HTML (reduzido):

<div class="table-container">
    <table>
        <thead>
            <tr>
                <th>head1</th>
                <th>head2</th>
                <th>head3</th>
                <th>head4</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>content1</td>
                <td>content2</td>
                <td>content3</td>
                <td>content4</td>
            </tr>
            <tr>
                <td>content1</td>
                <td>content2</td>
                <td>content3</td>
                <td>content4</td>
            </tr>
            ...
        </tbody>
    </table>
</div>

CSS, com algumas decorações omitidas para maior clareza:

.table-container {
    height: 10em;
}
table {
    display: flex;
    flex-flow: column;
    height: 100%;
    width: 100%;
}
table thead {
    /* head takes the height it requires, 
    and it's not scaled when table is resized */
    flex: 0 0 auto;
    width: calc(100% - 0.9em);
}
table tbody {
    /* body takes all the remaining available space */
    flex: 1 1 auto;
    display: block;
    overflow-y: scroll;
}
table tbody tr {
    width: 100%;
}
table thead, table tbody tr {
    display: table;
    table-layout: fixed;
}

código completo no jsfiddle

O mesmo código em LESS para que você possa misturá-lo:

.table-scrollable() {
  @scrollbar-width: 0.9em;
  display: flex;
  flex-flow: column;

  thead,
  tbody tr {
    display: table;
    table-layout: fixed;
  }

  thead {
    flex: 0 0 auto;
    width: ~"calc(100% - @{scrollbar-width})";
  }

  tbody {
    display: block;
    flex: 1 1 auto;
    overflow-y: scroll;

    tr {
      width: 100%;
    }
  }
}
tsayen
fonte
2
Obrigado pela solução! Houve uma ligeira bug .... você definir a largura para thead duas vezes, e eu achei que subtraindo 1.05em das linhas de largura um pouco melhor: jsfiddle.net/xuvsncr2/170
TigerBear
1
e o número do personagem? ele mexe-se ao adicionar mais caracteres ou palavras no interior das células de linha
Limon
Eu acho que definir alguma política de embrulho adequado em tddeve ajudar
tsayen
Alguma solução como essa, mas descartando a necessidade da largura de 100%?
Alexandre Pereira Nunes
2
@tsayen Como você impede que se amasse e se sobreponha ao redimensionar a janela?
clearshot66
31

Nos navegadores modernos, você pode simplesmente usar o css:

th {
  position: sticky;
  top: 0;
  z-index: 2;
}
Gauss
fonte
8
Este encantamento está incompleto ... Gostaria de postar um exemplo, ou pelo menos elaborado?
Liam
funcionando bem, mas só se aplica a th. Se definirmos a posição adesiva no cabeçote, ele não funcionará.
Vishal
A banda fixa deve ser adicionada ao W3C!
sonichy 22/02/19
2
Esta resposta funciona quando você quebra o seu <table>com o <div>qual possui overflow-y: auto;e alguns max-height. Por exemplo:<div style="overflow-y: auto; max-height: 400px;"><table>...</table></div>
Minwork 10/09/19
A partir de 2020, essa será a resposta selecionada (junto à atualização do @Minwork)
Christophe Vidal
18

Estou usando display:blockpara theade tbody. Por esse motivo, a largura das theadcolunas é diferente da largura das tbodycolunas.

table {
    margin:0 auto; 
    border-collapse:collapse;
}
thead {
    background:#CCCCCC;
    display:block
}
tbody {
    height:10em;overflow-y:scroll;
    display:block
}

Para corrigir isso, uso jQuerycódigo pequeno , mas isso pode ser feito JavaScriptapenas.

var colNumber=3 //number of table columns    

for (var i=0; i<colNumber; i++) {
  var thWidth=$("#myTable").find("th:eq("+i+")").width();
  var tdWidth=$("#myTable").find("td:eq("+i+")").width();      
  if (thWidth<tdWidth)                    
      $("#myTable").find("th:eq("+i+")").width(tdWidth);
  else
      $("#myTable").find("td:eq("+i+")").width(thWidth);           
}  

Aqui está minha demonstração de trabalho: http://jsfiddle.net/gavroche/N7LEF/

Não funciona no IE 8

gavroche
fonte
Esta é a melhor / mais simples solução que encontrei que permite larguras de coluna não fixas (por exemplo, controle .NET DataGrid). Para "produção", a colNumbervariável pode ser substituída por código que itera pelas células reais encontradas e observe que ela não funciona corretamente se houver algum colspans (também pode ser aprimorado no código, se necessário, mas improvável no tipo de tabela que provavelmente deseja esse recurso de rolagem).
JonBrave
Isso funciona (de certa forma), mas não funciona quando o tamanho da janela é menor que a tabela (pois ignora a largura da barra de rolagem).
Gone Coding
Sim o cabeçalho e células não igualar-se se você largura da tabela está confinado a uma largura definida
Craig
melhor resposta aqui, mais simples também
Charles Okwuagwu
18

Somente CSS

para Chrome, Firefox, Edge (e outros navegadores sempre verdes )

Simplesmente position: sticky; top: 0;seus thelementos:

/* Fix table head */
.tableFixHead    { overflow-y: auto; height: 100px; }
.tableFixHead th { position: sticky; top: 0; }

/* Just common table stuff. */
table  { border-collapse: collapse; width: 100%; }
th, td { padding: 8px 16px; }
th     { background:#eee; }
<div class="tableFixHead">
  <table>
    <thead>
      <tr><th>TH 1</th><th>TH 2</th></tr>
    </thead>
    <tbody>
      <tr><td>A1</td><td>A2</td></tr>
      <tr><td>B1</td><td>B2</td></tr>
      <tr><td>C1</td><td>C2</td></tr>
      <tr><td>D1</td><td>D2</td></tr>
      <tr><td>E1</td><td>E2</td></tr>
    </tbody>
  </table>
</div>

PS: se você precisar de bordas para elementos TH, th {box-shadow: 1px 1px 0 #000; border-top: 0;}isso ajudará (já que as bordas padrão não são pintadas corretamente na rolagem).

Para uma variante do anterior que usa apenas um pouco de JS para acomodar o IE11, consulte esta resposta https://stackoverflow.com/a/47923622/383904

Roko C. Buljan
fonte
Se você tiver bordas para os elementos, o uso de "border-collapse: collapse" colará a borda no corpo, em vez de no cabeçalho. Para evitar esse problema, você deve usar "border-collapse: separado". Veja stackoverflow.com/a/53559396
mrod 25/03
@mrod ao usar separatevocê está adicionando óleo ao fogo. jsfiddle.net/RokoCB/o0zL4xyw e veja uma solução AQUI: adicione bordas ao TH fixo - eu sou bem-vindo para sugestões OFC se eu perdi alguma coisa.
Roko C. Buljan 25/03
11

Crie duas tabelas uma após a outra, coloque a segunda tabela em uma div de altura fixa e defina a propriedade overflow como auto. Mantenha também todos os td dentro da segunda mesa vazios.

<div>
    <table>
        <thead>
            <tr>
                <th>Head 1</th>
                <th>Head 2</th>
                <th>Head 3</th>
                <th>Head 4</th>
                <th>Head 5</th>
            </tr>
        </thead>
    </table>
</div>

<div style="max-height:500px;overflow:auto;">
    <table>
        <thead>
            <tr>
                <th></th>
                <th></th>
                <th></th>
                <th></th>
                <th></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>
        </tbody>
    </table>    
</div>
Sushil Kumar
fonte
8
Nesse caso, as colunas da segunda tabela não podem seguir a largura da primeira tabela.
kat1330
2
Não é bom! Você perde a sincronização de largura para colunas em duas tabelas.
Zafar
1
para completar esta solução, precisamos adicionar @Hashem Qolami roteiro ( descrito acima ) para colunas de cabeçalho synchrinize largura
Elhay Avichzer
6

Eu finalmente entendi direito com CSS puro, seguindo estas instruções:

http://tjvantoll.com/2012/11/10/creating-cross-browser-scrollable-tbody/

O primeiro passo é definir o <tbody>bloco display: para que um excesso e uma altura possam ser aplicados. A partir daí, as linhas <thead>precisam ser definidas para a posição: relativa e exibição: bloco, para que elas fiquem no topo da rolagem agora <tbody>.

tbody, thead { display: block; overflow-y: auto; }

Como o <thead>está relativamente posicionado, cada célula da tabela precisa de uma largura explícita

td:nth-child(1), th:nth-child(1) { width: 100px; }
td:nth-child(2), th:nth-child(2) { width: 100px; }
td:nth-child(3), th:nth-child(3) { width: 100px; }

Mas infelizmente isso não é suficiente. Quando uma barra de rolagem está presente, os navegadores alocam espaço para ela, portanto, <tbody>acaba tendo menos espaço disponível que o <thead>. Observe o leve desalinhamento que isso cria ...

A única solução alternativa que eu pude encontrar foi definir uma largura mínima em todas as colunas, exceto a última.

td:nth-child(1), th:nth-child(1) { min-width: 100px; }
td:nth-child(2), th:nth-child(2) { min-width: 100px; }
td:nth-child(3), th:nth-child(3) { width: 100px; }

Exemplo de código inteiro abaixo:

CSS:

.fixed_headers {
  width: 750px;
  table-layout: fixed;
  border-collapse: collapse;
}
.fixed_headers th {
  text-decoration: underline;
}
.fixed_headers th,
.fixed_headers td {
  padding: 5px;
  text-align: left;
}
.fixed_headers td:nth-child(1),
.fixed_headers th:nth-child(1) {
  min-width: 200px;
}
.fixed_headers td:nth-child(2),
.fixed_headers th:nth-child(2) {
  min-width: 200px;
}
.fixed_headers td:nth-child(3),
.fixed_headers th:nth-child(3) {
  width: 350px;
}
.fixed_headers thead {
  background-color: #333333;
  color: #fdfdfd;
}
.fixed_headers thead tr {
  display: block;
  position: relative;
}
.fixed_headers tbody {
  display: block;
  overflow: auto;
  width: 100%;
  height: 300px;
}
.fixed_headers tbody tr:nth-child(even) {
  background-color: #dddddd;
}
.old_ie_wrapper {
  height: 300px;
  width: 750px;
  overflow-x: hidden;
  overflow-y: auto;
}
.old_ie_wrapper tbody {
  height: auto;
}

Html:

<!-- IE < 10 does not like giving a tbody a height.  The workaround here applies the scrolling to a wrapped <div>. -->
<!--[if lte IE 9]>
<div class="old_ie_wrapper">
<!--<![endif]-->

<table class="fixed_headers">
  <thead>
    <tr>
      <th>Name</th>
      <th>Color</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Apple</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Pear</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
    <tr>
      <td>Grape</td>
      <td>Purple / Green</td>
      <td>These are purple and green.</td>
    </tr>
    <tr>
      <td>Orange</td>
      <td>Orange</td>
      <td>These are orange.</td>
    </tr>
    <tr>
      <td>Banana</td>
      <td>Yellow</td>
      <td>These are yellow.</td>
    </tr>
    <tr>
      <td>Kiwi</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
    <tr>
      <td>Plum</td>
      <td>Purple</td>
      <td>These are Purple</td>
    </tr>
    <tr>
      <td>Watermelon</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Tomato</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Cherry</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Cantelope</td>
      <td>Orange</td>
      <td>These are orange inside.</td>
    </tr>
    <tr>
      <td>Honeydew</td>
      <td>Green</td>
      <td>These are green inside.</td>
    </tr>
    <tr>
      <td>Papaya</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
    <tr>
      <td>Raspberry</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Blueberry</td>
      <td>Blue</td>
      <td>These are blue.</td>
    </tr>
    <tr>
      <td>Mango</td>
      <td>Orange</td>
      <td>These are orange.</td>
    </tr>
    <tr>
      <td>Passion Fruit</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
  </tbody>
</table>

<!--[if lte IE 9]>
</div>
<!--<![endif]-->

EDIT: Solução alternativa para largura da tabela 100% (acima, na verdade, é para largura fixa e não respondeu à pergunta):

HTML:

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Color</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Apple</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Pear</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
    <tr>
      <td>Grape</td>
      <td>Purple / Green</td>
      <td>These are purple and green.</td>
    </tr>
    <tr>
      <td>Orange</td>
      <td>Orange</td>
      <td>These are orange.</td>
    </tr>
    <tr>
      <td>Banana</td>
      <td>Yellow</td>
      <td>These are yellow.</td>
    </tr>
    <tr>
      <td>Kiwi</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
  </tbody>
</table>

CSS:

table {
  width: 100%;
  text-align: left;
  min-width: 610px;
}
tr {
  height: 30px;
  padding-top: 10px
}
tbody { 
  height: 150px; 
  overflow-y: auto;
  overflow-x: hidden;
}
th,td,tr,thead,tbody { display: block; }
td,th { float: left; }
td:nth-child(1),
th:nth-child(1) {
  width: 20%;
}
td:nth-child(2),
th:nth-child(2) {
  width: 20%;
  float: left;
}
td:nth-child(3),
th:nth-child(3) {
  width: 59%;
  float: left;
}
/* some colors */
thead {
  background-color: #333333;
  color: #fdfdfd;
}
table tbody tr:nth-child(even) {
  background-color: #dddddd;
}

Demonstração: http://codepen.io/anon/pen/bNJeLO

Mikael Lepistö
fonte
1
A pergunta queria especificamente uma tabela de largura de 100%, que é a única coisa que o exemplo que você referenciou não faz.
Gone Coding
@TrueBlueAussie Boa captura: D Solução alternativa adicionada para 100% de largura.
Mikael Lepistö 03/04
você não considera a longitude do conteúdo da linha da célula
Limon
2

Solução alternativa de Css para forçar colunas a serem exibidas corretamente com um tbody 'block'

Essa solução ainda exige que as thlarguras sejam calculadas e definidas pelo jQuery

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

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

table.scroll tr {
    display: flex;
}

table.scroll tr > td {
    flex-grow: 1;
    flex-basis: 0;
}

E o Jquery / Javascript

var $table = $('#the_table_element'),
    $bodyCells = $table.find('tbody tr:first').children(),
    colWidth;

$table.addClass('scroll');

// 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
Emmanuel
fonte
@ Craig em 2019, é totalmente bom não me importar com o IE.
Automagisch
2

tente abaixo abordagem, muito simples e fácil de implementar

Abaixo está o link jsfiddle

http://jsfiddle.net/v2t2k8ke/2/

HTML:

<table border='1' id='tbl_cnt'>
<thead><tr></tr></thead><tbody></tbody>

CSS:

 #tbl_cnt{
 border-collapse: collapse; width: 100%;word-break:break-all;
 }
 #tbl_cnt thead, #tbl_cnt tbody{
 display: block;
 }
 #tbl_cnt thead tr{
 background-color: #8C8787; text-align: center;width:100%;display:block;
 }
 #tbl_cnt tbody {
 height: 100px;overflow-y: auto;overflow-x: hidden;
 }

Jquery:

 var data = [
    {
    "status":"moving","vehno":"tr544","loc":"bng","dri":"ttt"
    }, {
    "status":"stop","vehno":"tr54","loc":"che", "dri":"ttt"
    },{    "status":"idle","vehno":"yy5499999999999994","loc":"bng","dri":"ttt"
    },{
    "status":"moving","vehno":"tr544","loc":"bng", "dri":"ttt"
    }, {
    "status":"stop","vehno":"tr54","loc":"che","dri":"ttt"
    },{
    "status":"idle","vehno":"yy544","loc":"bng","dri":"ttt"
    }
    ];
   var sth = '';
   $.each(data[0], function (key, value) {
     sth += '<td>' + key + '</td>';
   });
   var stb = '';        
   $.each(data, function (key, value) {
       stb += '<tr>';
       $.each(value, function (key, value) {
       stb += '<td>' + value + '</td>';
       });
       stb += '</tr>';
    });
      $('#tbl_cnt thead tr').append(sth);
      $('#tbl_cnt tbody').append(stb);
      setTimeout(function () {
      var col_cnt=0 
      $.each(data[0], function (key, value) {col_cnt++;});    
      $('#tbl_cnt thead tr').css('width', ($("#tbl_cnt tbody") [0].scrollWidth)+ 'px');
      $('#tbl_cnt thead tr td,#tbl_cnt tbody tr td').css('width',  ($('#tbl_cnt thead tr ').width()/Number(col_cnt)) + 'px');}, 100)
Nandha
fonte
2
Esta solução não lida com a janela sendo mais estreita que a largura da tabela. Deve ativar a rolagem horizontal quando isso acontecer. Além disso, os títulos não estão alinhados exatamente com as células de dados (Chrome).
Gone Coding
Hoje não funciona
MrHIDEn 11/06
2

Adicionando uma largura fixa a td, depois de fazer o bloco de exibição tbody & thead funcionar perfeitamente, também podemos usar o plugin slimscroll para deixar a barra de rolagem bonita.

insira a descrição da imagem aqui

<!DOCTYPE html>
<html>

<head>
    <title> Scrollable table </title>
    <style>
        body {
            font-family: sans-serif;
            font-size: 0.9em;
        }
        table {
            border-collapse: collapse;
            border-bottom: 1px solid #ddd;
        }
        thead {
            background-color: #333;
            color: #fff;
        }
        thead,tbody {
            display: block;
        }
        th,td {
            padding: 8px 10px;
            border: 1px solid #ddd;
            width: 117px;
            box-sizing: border-box;
        }
        tbody {
            height: 160px;
            overflow-y: scroll
        }
    </style>
</head>

<body>

    <table class="example-table">
        <thead>
            <tr>
                <th> Header 1 </th>
                <th> Header 2 </th>
                <th> Header 3 </th>
                <th> Header 4 </th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td> Row 1- Col 1 </td>
                <td> Row 1- Col 2 </td>
                <td> Row 1- Col 3 </td>
                <td> Row 1- Col 4 </td>
            </tr>
            <tr>
                <td> Row 2- Col 1 </td>
                <td> Row 2- Col 2 </td>
                <td> Row 2- Col 3 </td>
                <td> Row 2- Col 4 </td>
            </tr>
            <tr>
                <td> Row 3- Col 1 </td>
                <td> Row 3- Col 2 </td>
                <td> Row 3- Col 3 </td>
                <td> Row 3- Col 4 </td>
            </tr>
            <tr>
                <td> Row 4- Col 1 </td>
                <td> Row 4- Col 2 </td>
                <td> Row 4- Col 3 </td>
                <td> Row 4- Col 4 </td>
            </tr>
            <tr>
                <td> Row 5- Col 1 </td>
                <td> Row 5- Col 2 </td>
                <td> Row 5- Col 3 </td>
                <td> Row 5- Col 4 </td>
            </tr>
            <tr>
                <td> Row 6- Col 1 </td>
                <td> Row 6- Col 2 </td>
                <td> Row 6- Col 3 </td>
                <td> Row 6- Col 4 </td>
            </tr>
            <tr>
                <td> Row 7- Col 1 </td>
                <td> Row 7- Col 2 </td>
                <td> Row 7- Col 3 </td>
                <td> Row 7- Col 4 </td>
            </tr>
            <tr>
                <td> Row 8- Col 1 </td>
                <td> Row 8- Col 2 </td>
                <td> Row 8- Col 3 </td>
                <td> Row 8- Col 4 </td>
            </tr>
            <tr>
                <td> Row 9- Col 1 </td>
                <td> Row 9- Col 2 </td>
                <td> Row 9- Col 3 </td>
                <td> Row 9- Col 4 </td>
            </tr>
            <tr>
                <td> Row 10- Col 1 </td>
                <td> Row 10- Col 2 </td>
                <td> Row 10- Col 3 </td>
                <td> Row 10- Col 4 </td>
            </tr>
            <tr>
                <td> Row 11- Col 1 </td>
                <td> Row 11- Col 2 </td>
                <td> Row 11- Col 3 </td>
                <td> Row 11- Col 4 </td>
            </tr>
            <tr>
                <td> Row 12- Col 1 </td>
                <td> Row 12- Col 2 </td>
                <td> Row 12- Col 3 </td>
                <td> Row 12- Col 4 </td>
            </tr>
            <tr>
                <td> Row 13- Col 1 </td>
                <td> Row 13- Col 2 </td>
                <td> Row 13- Col 3 </td>
                <td> Row 13- Col 4 </td>
            </tr>
            <tr>
                <td> Row 14- Col 1 </td>
                <td> Row 14- Col 2 </td>
                <td> Row 14- Col 3 </td>
                <td> Row 14- Col 4 </td>
            </tr>
            <tr>
                <td> Row 15- Col 1 </td>
                <td> Row 15- Col 2 </td>
                <td> Row 15- Col 3 </td>
                <td> Row 15- Col 4 </td>
            </tr>
            <tr>
                <td> Row 16- Col 1 </td>
                <td> Row 16- Col 2 </td>
                <td> Row 16- Col 3 </td>
                <td> Row 16- Col 4 </td>
            </tr>
        </tbody>
    </table>


    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jQuery-slimScroll/1.3.8/jquery.slimscroll.min.js"></script>
    <script>
        $('.example-table tbody').slimscroll({
            height: '160px',
            alwaysVisible: true,
            color: '#333'
        })
    </script>
</body>

</html>

codegeek
fonte
1

Este é o código que funciona para mim para criar um cabeçalho em uma tabela com um corpo rolável:

table ,tr td{
    border:1px solid red
}
tbody {
    display:block;
    height:50px;
    overflow:auto;
}
thead, tbody tr {
    display:table;
    width:100%;
    table-layout:fixed;/* even columns width , fix width of table too*/
}
thead {
    width: calc( 100% - 1em )/* scrollbar is average 1em/16px width, remove it from thead width */
}
table {
    width:400px;
}
Max Alexander Hanna
fonte
1

Para usar "overflow: scroll", você deve definir "display: block" no cabeçote e no corpo. E isso atrapalha as larguras das colunas entre eles. Mas você pode clonar a linha do cabeçalho com Javascript e colá-la no corpo como uma linha oculta para manter as larguras exatas das colunas.

$('.myTable thead > tr').clone().appendTo('.myTable tbody').addClass('hidden-to-set-col-widths');

http://jsfiddle.net/Julesezaar/mup0c5hk/

<table class="myTable">
    <thead>
        <tr>
            <td>Problem</td>
            <td>Solution</td>
            <td>blah</td>
            <td>derp</td>
        </tr>
    </thead>
    <tbody></tbody>
</table>
<p>
  Some text to here
</p>

O css:

table {
  background-color: #aaa;
  width: 100%;
}

thead,
tbody {
  display: block; // Necessary to use overflow: scroll
}

tbody {
  background-color: #ddd;
  height: 150px;
  overflow-y: scroll;
}

tbody tr.hidden-to-set-col-widths,
tbody tr.hidden-to-set-col-widths td {
  visibility: hidden;
  height: 0;
  line-height: 0;
  padding-top: 0;
  padding-bottom: 0;
}

td {
  padding: 3px 10px;
}
Julesezaar
fonte
0

Experimente este jsfiddle . Isso está usando jQuery e é feito com a resposta de Hashem Qolami. Primeiro, faça uma tabela regular e depois role-a.

const makeScrollableTable = function (tableSelector, tbodyHeight) {
  let $table = $(tableSelector);
  let $bodyCells = $table.find('tbody tr:first').children();
  let $headCells = $table.find('thead tr:first').children();
  let headColWidth = 0;
  let bodyColWidth = 0;

  headColWidth = $headCells.map(function () {
    return $(this).outerWidth();
  }).get();
  bodyColWidth = $bodyCells.map(function () {
    return $(this).outerWidth();
  }).get();

  $table.find('thead tr').children().each(function (i, v) {
    $(v).css("width", headColWidth[i]+"px");
    $(v).css("min-width", headColWidth[i]+"px");
    $(v).css("max-width", headColWidth[i]+"px");
  });
  $table.find('tbody tr').children().each(function (i, v) {
    $(v).css("width", bodyColWidth[i]+"px");
    $(v).css("min-width", bodyColWidth[i]+"px");
    $(v).css("max-width", bodyColWidth[i]+"px");
  });

  $table.find('thead').css("display", "block");
  $table.find('tbody').css("display", "block");

  $table.find('tbody').css("height", tbodyHeight+"px");
  $table.find('tbody').css("overflow-y", "auto");
  $table.find('tbody').css("overflow-x", "hidden");

};
lechat
fonte