Para hacer que el <tbody>
elemento se pueda desplazar, necesitamos cambiar la forma en que se muestra en la página, es decir, usarlo display: block;
para mostrarlo como un elemento de nivel de bloque.
Como cambiamos la display
propiedad de tbody
, también debemos cambiar esa propiedad para el thead
elemento para evitar que se rompa el diseño de la tabla.
Entonces tenemos:
thead, tbody { display: block; }
tbody {
height: 100px; /* Just for the demo */
overflow-y: auto; /* Trigger vertical scroll */
overflow-x: hidden; /* Hide the horizontal scroll */
}
Los navegadores web muestran los elementos thead
y tbody
como grupo de filas ( table-header-group
y table-row-group
) de forma predeterminada.
Una vez que cambiamos eso, los tr
elementos internos no llenan todo el espacio de su contenedor.
Para solucionarlo, debemos calcular el ancho de las tbody
columnas y aplicar el valor correspondiente a las thead
columnas a través de JavaScript.
Columnas de ancho automático
Aquí está la versión jQuery de la lógica anterior:
// 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]);
});
Y aquí está la salida (en Windows 7 Chrome 32) :
DEMO DE TRABAJO .
Tabla de ancho completo, columnas de ancho relativo
Como lo necesitaba el Cartel original, podríamos expandirlo table
al 100% de width
su contenedor, y luego usar un relativo ( Porcentaje ) width
para cada columna de la tabla.
table {
width: 100%; /* Optional */
}
tbody td, thead th {
width: 20%; /* Optional */
}
Dado que la tabla tiene un diseño fluido , deberíamos ajustar el ancho de las thead
columnas cuando el contenedor cambia de tamaño.
Por lo tanto, deberíamos establecer el ancho de las columnas una vez que la ventana cambia de tamaño:
// Adjust the width of thead cells when *window* resizes
$(window).resize(function() {
/* Same as before */
}).resize(); // Trigger the resize handler once the script runs
El resultado sería:
DEMO DE TRABAJO .
Soporte del navegador y alternativas
He probado los dos métodos anteriores en Windows 7 a través de las nuevas versiones de los principales navegadores web (incluido IE10 +) y funcionó.
Sin embargo, no funciona correctamente en IE9 y versiones posteriores.
Eso es porque en un diseño de tabla , todos los elementos deben seguir las mismas propiedades estructurales.
Al usar display: block;
para los elementos <thead>
y <tbody>
, hemos roto la estructura de la tabla.
Diseño de rediseño a través de JavaScript
Un enfoque es rediseñar el diseño de tabla (completo). Usar JavaScript para crear un nuevo diseño sobre la marcha y manejar y / o ajustar los anchos / alturas de las celdas dinámicamente.
Por ejemplo, eche un vistazo a los siguientes ejemplos:
Mesas de anidamiento
Este enfoque utiliza dos tablas anidadas con un div que contiene. La primera table
tiene solo una celda que tiene un div
, y la segunda tabla se coloca dentro de ese div
elemento.
Consulte las tablas de desplazamiento vertical en CSS Play .
Esto funciona en la mayoría de los navegadores web. También podemos hacer la lógica anterior de forma dinámica a través de JavaScript.
Tabla con encabezado fijo en desplazamiento
Dado que el propósito de agregar una barra de desplazamiento vertical al <tbody>
mostrar el encabezado de la tabla en la parte superior de cada fila, podríamos colocar el thead
elemento para que permanezca fixed
en la parte superior de la pantalla.
Aquí hay una demostración de trabajo de este enfoque realizado por Julien .
Tiene un soporte de navegador web prometedor.
Y aquí una implementación CSS pura por Willem Van Bockstal .
La solución CSS pura
Aquí está la vieja respuesta. Por supuesto, agregué un nuevo método y perfeccioné las declaraciones CSS.
Mesa con ancho fijo
En este caso, table
debería tener un valor fijo width
(incluida la suma de los anchos de las columnas y el ancho de la barra de desplazamiento vertical) .
Cada columna debe tener una determinada anchura y la última columna del thead
elemento necesita una mayor anchura que es igual a la de los demás ancho + el ancho de la barra de desplazamiento vertical.
Por lo tanto, el CSS sería:
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 */
}
Aquí está la salida:
DEMO DE TRABAJO .
Mesa con 100% de ancho
En este enfoque, table
tiene un ancho de 100%
y para cada th
y td
, el valor de la width
propiedad debe ser menor que 100% / number of cols
.
Además, tenemos que reducir el ancho de thead
como el valor de la anchura de la barra de desplazamiento vertical.
Para hacer eso, necesitamos usar la calc()
función CSS3 , de la siguiente manera:
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;
}
Aquí está la demostración en línea .
Nota: este enfoque fallará si el contenido de cada columna rompe la línea, es decir, el contenido de cada celda debe ser lo suficientemente corto .
A continuación, hay dos ejemplos simples de solución CSS pura que creé en el momento en que respondí esta pregunta.
Aquí está la jsFiddle Demo v2 .
Versión anterior: jsFiddle Demo v1