Solución:
Para poder hacer <tbody>
elemento desplazable, necesitamos cambiar la forma en que se muestra en la página, es decir, usando display: block;
para mostrar eso como un elemento de nivel de bloque.
Desde que cambiamos el display
propiedad de tbody
, deberíamos cambiar esa propiedad por thead
elemento también para evitar que se rompa el diseño de la mesa.
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 thead
y tbody
elementos como grupo de filas (table-header-group
y table-row-group
) por defecto.
Una vez que cambiamos eso, el interior tr
los elementos no llenan todo el espacio de su contenedor.
Para arreglar eso, tenemos que calcular el ancho de tbody
columnas y aplique el valor correspondiente a la 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 necesitaba el póster original, podríamos expandir el table
al 100% de width
de su contenedor, y luego usando un relativo (Porcentaje) width
para cada columna de la tabla.
table {
width: 100%; /* Optional */
}
tbody td, thead th {
width: 20%; /* Optional */
}
Dado que la mesa tiene una (especie de) diseño fluido, debemos ajustar el ancho de thead
columnas cuando el contenedor cambia de tamaño.
Por lo tanto, deberíamos establecer el ancho de las columnas una vez que se cambia el tamaño de la ventana:
// Adjust the width of thead cells when *window* resizes
$(window).resize(function() {
/* Same as before */
}).resize(); // Trigger the resize handler once the script runs
La salida sería:
DEMO DE TRABAJO.
Compatibilidad con navegadores y alternativas
Probé 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 anteriores.
Eso es porque en un diseño de tabla, todos los elementos deben seguir las mismas propiedades estructurales.
Mediante el uso display: block;
Para el <thead>
y <tbody>
elementos, hemos roto la estructura de la tabla.
Rediseño del diseño a través de JavaScript
Un enfoque consiste en rediseñar el diseño (completo) de la tabla. Usar JavaScript para crear un nuevo diseño sobre la marcha y manejar y / o ajustar los anchos / alturas de las celdas de forma dinámica.
Por ejemplo, eche un vistazo a los siguientes ejemplos:
- jQuery .floatThead () complemento (un complemento de encabezado de tabla flotante / bloqueado / adhesivo)
- jQuery Mesa desplazable enchufar. (código fuente en github)
- jQuery .FixedHeaderTable () complemento (código fuente en github)
- Tablas de datos desplazamiento vertical ejemplo.
Mesas nido
Este enfoque utiliza dos tablas anidadas con un div contenedor. El primero table
tiene solo una celda que tiene un div
, y la segunda tabla se coloca dentro de esa div
elemento.
Consulte las tablas de desplazamiento vertical en Juego CSS.
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 scroll
Dado que el propósito de agregar una barra de desplazamiento vertical a la <tbody>
está mostrando la mesa encabezamiento en la parte superior de cada fila, podríamos posición los thead
elemento para quedarse fixed
en la parte superior de la pantalla.
Aquí hay un Demo de trabajo de este enfoque realizado por Julien.
Tiene un soporte de navegador web prometedor.
Y aqui un CSS puro implementación por Willem Van Bockstal.
La solución Pure CSS
Aquí está la vieja respuesta. Por supuesto, agregué un nuevo método y refiné las declaraciones CSS.
Mesa con ancho fijo
En este caso, el table
debería tener un fijo width
(incluida la suma de los anchos de las columnas y el ancho de la barra de desplazamiento vertical).
Cada columna debe tener un especifico ancho y el última columna de thead
elemento necesita un mayor ancho que es igual a los demás ancho + el ancho de barra de desplazamiento vertical.
Por 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á el resultado:
DEMO DE TRABAJO.
Mesa con 100% de ancho
En este enfoque, el table
tiene un ancho de 100%
y para cada th
y td
, El valor de width
la propiedad debe ser menor que 100% / number of cols
.
Además, necesitamos reducir la ancho de thead
como valor del ancho de barra de desplazamiento vertical.
Para hacer eso, necesitamos usar CSS3 calc()
función, 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á el 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 sencillos de solución CSS pura que creé en el momento en que respondí esta pregunta.
Aquí está el jsFiddle Demo v2.
Versión antigua: jsFiddle Demo v1
En la siguiente solución, la mesa ocupa el 100% del contenedor principal, no se requieren tamaños absolutos. Es CSS puro, se utiliza un diseño flexible.
Así es como se ve:
Posibles desventajas:
- la barra de desplazamiento vertical siempre está visible, independientemente de si es necesaria;
- el diseño de la tabla es fijo: las columnas no cambian de tamaño de acuerdo con el ancho del contenido (aún puede establecer el ancho de columna que desee explícitamente);
- hay un tamaño absoluto: el ancho de la barra de desplazamiento, que es de aproximadamente 0,9 em para los navegadores que pude comprobar.
HTML (abreviado):
<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, con algunas decoraciones omitidas para mayor claridad:
.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 en jsfiddle
Mismo código en MENOS para que pueda mezclarlo en:
.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%;
}
}
}
En los navegadores modernos, simplemente puede usar css:
th {
position: sticky;
top: 0;
z-index: 2;
}