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 display
propriedade de tbody
, também devemos alterar essa propriedade para o thead
elemento 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 thead
e tbody
como grupo de linhas ( table-header-group
e table-row-group
) por padrão.
Depois que mudamos isso, os tr
elementos internos não preenchem todo o espaço do contêiner.
Para consertar isso, precisamos calcular a largura das tbody
colunas 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) :
DEMO DE TRABALHO .
Tabela de largura total, colunas de largura relativa
Conforme o Pôster original fosse necessário, poderíamos expandir table
para 100% de width
seu contêiner e, em seguida, usar um relativo ( Porcentagem ) width
para 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 thead
colunas 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:
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 table
possui apenas uma célula que possui a div
e a segunda tabela é colocada dentro desse div
elemento.
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 thead
elemento para permanecer fixed
na 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, table
deve 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 thead
elemento 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:
DEMO DE TRABALHO .
Mesa com 100% de largura
Nesta abordagem, o table
tem uma largura de 100%
e para cada um , th
e td
o valor da width
propriedade deve ser menor que 100% / number of cols
.
Além disso, precisamos reduzir a largura de thead
como 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