Cabecera fija de tabla y cuerpo desplazable.
Estoy intentando crear una tabla con encabezado fijo y contenido desplazable usando la tabla bootstrap 3. Lamentablemente, las soluciones que he encontrado no funcionan con bootstrap o estropean el estilo.
Aquí hay una tabla de arranque simple, pero por alguna razón que desconozco, la altura del tbody no es 10px.
height: 10px !important; overflow: scroll;
Ejemplo:
<link rel="stylesheet" type="text/css" href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
<table class="table table-striped">
<thead>
<tr>
<th>Make</th>
<th>Model</th>
<th>Color</th>
<th>Year</th>
</tr>
</thead>
<tbody style="height: 10px !important; overflow: scroll; ">
<tr>
<td class="filterable-cell">111 Ford</td>
<td class="filterable-cell">Escort</td>
<td class="filterable-cell">Blue</td>
<td class="filterable-cell">2000</td>
</tr>
<tr>
<td class="filterable-cell">Ford</td>
<td class="filterable-cell">Escort</td>
<td class="filterable-cell">Blue</td>
<td class="filterable-cell">2000</td>
</tr>
<tr>
<td class="filterable-cell">Ford</td>
<td class="filterable-cell">Escort</td>
<td class="filterable-cell">Blue</td>
<td class="filterable-cell">2000</td>
</tr>
<tr>
<td class="filterable-cell">Ford</td>
<td class="filterable-cell">Escort</td>
<td class="filterable-cell">Blue</td>
<td class="filterable-cell">2000</td>
</tr>
</tbody>
</table>
Cabecera de tabla fija: solo CSS
Simplemente position: sticky; top: 0;
tus th
elementos. (Cromo, FF, Borde)
.tableFixHead { overflow: auto; height: 100px; }
.tableFixHead thead th { position: sticky; top: 0; z-index: 1; }
/* Just common table stuff. Really. */
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>
Para columnas TH verticales adhesivas y TH horizontales (interior TBODY
) :
.tableFixHead { overflow: auto; height: 100px; width: 240px; }
.tableFixHead thead th { position: sticky; top: 0; z-index: 1; }
.tableFixHead tbody th { position: sticky; left: 0; }
Mostrar fragmento de código
Solución del problema de fronteras TH
Dado que border
no se puede pintar correctamente en un TH
elemento traducido, para recrear y representar "bordes" utilice la box-shadow
propiedad:
/* Borders (if you need them) */
.tableFixHead,
.tableFixHead td {
box-shadow: inset 1px -1px #000;
}
.tableFixHead th {
box-shadow: inset 1px 1px #000, 0 1px #000;
}
Mostrar fragmento de código
TH pegajoso no funciona
Asegúrese de que los elementos principales del th
elemento " ", al menos hasta table
el elemento (inclusive), no establezcan estilos overflow
relacionados (por ejemplo overflow
, overflow-x
, overflow-y
).
Para obtener más información, consulte stackoverflow.com/ ¿ Por qué la 'posición: pegajosa' no funciona?
Cabecera de tabla fija: usando JavaScript
Para navegadores antiguos , puedes usar un poco de JS y traducir los th
elementos.
// Fix table head example:
function tableFixHead(evt) {
const el = evt.currentTarget,
sT = el.scrollTop;
el.querySelectorAll("thead th").forEach(th =>
th.style.transform = `translateY(${sT}px)`
);
}
document.querySelectorAll(".tableFixHead").forEach(el =>
el.addEventListener("scroll", tableFixHead)
);
.tableFixHead {
overflow-y: auto;
height: 100px;
}
/* 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>
Para un enfoque CSS puro, necesitaría un contenedor overflow-y: auto;
y decidiría cómo ocultar las filas desplazadas/desbordadas:
- Superposición con un encabezado adhesivo no transparente ( ), como en la respuesta
position: sticky; top: 0; z-index: 1;
de @RokoCBuljan . - Alternar la visibilidad de las filas (configurando
tr:after
las propiedades como se indica a continuación).
Tenga en cuenta que el contenedor puede ser externo <div>
, él <table>
mismo o una parte de él (p. ej. <tbody>
). Para los dos últimos, debes configurarlos display: block;
de manera tan efectiva que se traten como div
s.
Vea a continuación una solución modificada de @giulio:
:root {
--height-height: 150px;
/* cell width has to reserve some space for scrolling. Hence the sum < 100% */
--cell-width: 85px;
}
.header-fixed {
width: 200px;
}
/* Treat all as divs */
.header-fixed > thead,
.header-fixed > tbody,
.header-fixed > thead > tr,
.header-fixed > tbody > tr,
.header-fixed > thead > tr > th,
.header-fixed > tbody > tr > td {
display: block;
}
/* Prevent header to wrap */
.header-fixed > thead > tr > th {
white-space: nowrap;
background-color: lightgrey;
}
.header-fixed > tbody > tr:after,
.header-fixed > thead > tr:after {
content: ' ';
display: block;
visibility: hidden;
clear: both;
}
.header-fixed > tbody {
overflow-y: auto;
height: var(--height-height);
}
.header-fixed > tbody > tr > td,
.header-fixed > thead > tr > th {
width: var(--cell-width);
border: thin solid grey;
float: left;
}
<table class="header-fixed">
<thead>
<tr> <th>Header 1</th> <th>Header 2</th> </tr>
</thead>
<tbody>
<tr> <td>cell 11</td> <td>cell 12</td> </tr>
<tr> <td>cell 21</td> <td>cell 22</td> </tr>
<tr> <td>cell 31</td> <td>cell 32</td> </tr>
<tr> <td>cell 41</td> <td>cell 42</td> </tr>
<tr> <td>cell 51</td> <td>cell 52</td> </tr>
<tr> <td>cell 61</td> <td>cell 62</td> </tr>
<tr> <td>cell 71</td> <td>cell 72</td> </tr>
<tr> <td>cell 81</td> <td>cell 82</td> </tr>
<tr> <td>cell 91</td> <td>cell 92</td> </tr>
</tbody>
</table>
Nota: Si tiene >2 columnas, debe modificar la var(--cell-width)
variable en consecuencia.
Aquí está la solución de trabajo:
table {
width: 100%;
}
thead, tbody, tr, td, th { display: block; }
tr:after {
content: ' ';
display: block;
visibility: hidden;
clear: both;
}
thead th {
height: 30px;
/*text-align: left;*/
}
tbody {
height: 120px;
overflow-y: auto;
}
thead {
/* fallback */
}
tbody td, thead th {
width: 19.2%;
float: left;
}
<link href="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet"/>
<table class="table table-striped">
<thead>
<tr>
<th>Make</th>
<th>Model</th>
<th>Color</th>
<th>Year</th>
</tr>
</thead>
<tbody>
<tr>
<td class="filterable-cell">Ford</td>
<td class="filterable-cell">Escort</td>
<td class="filterable-cell">Blue</td>
<td class="filterable-cell">2000</td>
</tr>
<tr>
<td class="filterable-cell">Ford</td>
<td class="filterable-cell">Escort</td>
<td class="filterable-cell">Blue</td>
<td class="filterable-cell">2000</td>
</tr>
<tr>
<td class="filterable-cell">Ford</td>
<td class="filterable-cell">Escort</td>
<td class="filterable-cell">Blue</td>
<td class="filterable-cell">2000</td>
</tr>
<tr>
<td class="filterable-cell">Ford</td>
<td class="filterable-cell">Escort</td>
<td class="filterable-cell">Blue</td>
<td class="filterable-cell">2000</td>
</tr>
</tbody>
</table>
Enlace a jsfiddle
Actualizar
Para una biblioteca más nueva y aún mantenida, pruebe con jquery.floatThead (como lo menciona Bob Jordan en el comentario) .
Antigua respuesta
Esta es una respuesta muy antigua, la biblioteca que se menciona a continuación ya no se mantiene.
¡Estoy usando StickyTableHeaders en GitHub y funciona de maravilla!
Sin embargo, tuve que agregar este CSS para que el encabezado no fuera transparente.
table#stickyHeader thead {
border-top: none;
border-bottom: none;
background-color: #FFF;
}
Con diferencia, la mejor solución que he visto es solo CSS, con buena compatibilidad con varios navegadores y sin problemas de alineación es esta solución de codingrabbithole.
table {
width: 100%;
}
thead, tbody tr {
display: table;
width: 100%;
table-layout: fixed;
}
tbody {
display: block;
overflow-y: auto;
table-layout: fixed;
max-height: 200px;
}