html - tbody - Tabla desplazable CSS-Only con encabezados fijos
inmovilizar filas y columnas tabla html jquery (12)
Como hace poco necesitaba esto, compartiré una solución que usa 3 tablas, pero no requiere JavaScript.
La Tabla 1 (principal) contiene dos filas. La primera fila contiene la tabla 2 (secundaria 1) para los encabezados de las columnas. La segunda fila contiene la tabla 3 (secundaria 2) para el contenido de desplazamiento.
Debe tenerse en cuenta que childTbl
debe ser 25px
más corto que parentTbl
para que el desplazamiento aparezca correctamente.
This es la fuente, de donde obtuve la idea. Lo hice compatible con HTML5 sin las etiquetas obsoletas y el CSS en línea.
.parentTbl table {
border-spacing: 0;
border-collapse: collapse;
border: 0;
width: 690px;
}
.childTbl table {
border-spacing: 0;
border-collapse: collapse;
border: 1px solid #d7d7d7;
width: 665px;
}
.childTbl th,
.childTbl td {
border: 1px solid #d7d7d7;
}
.scrollData {
width: 690;
height: 150px;
overflow-x: hidden;
}
<div class="parentTbl">
<table>
<tr>
<td>
<div class="childTbl">
<table class="childTbl">
<tr>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
<th>Header 4</th>
<th>Header 5</th>
<th>Header 6</th>
</tr>
</table>
</div>
</td>
</tr>
<tr>
<td>
<div class="scrollData childTbl">
<table>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
</table>
</div>
</td>
</tr>
</table>
</div>
Esto es confiable en diferentes navegadores, la desventaja sería tener que codificar el ancho de la tabla.
Tengo una solución mediante la cual puedo crear tablas desplazables con encabezado / pie de página fijo usando jQuery y CSS menores, pero estoy buscando una manera de hacer de esto una solución CSS única que sea compatible con varios navegadores.
Para que quede claro, lo que intento hacer es usar solo una etiqueta de table
(y sus thead
válidas, colgroup
, col
, thead
, tbody
, tfoot
, tr
, th
, td
), pero adopte un conjunto de reglas CSS que cumplir con las siguientes condiciones:
- Debe mantener la alineación de columnas entre las filas de encabezado / pie de página / contenido
- Debe permitir que el encabezado / pie de página permanezca fijo mientras el contenido se desplaza verticalmente
- No debe requerir ningún jQuery u otro JavaScript para proporcionar la funcionalidad
- Solo debe usar las etiquetas proporcionadas anteriormente
Este ejemplo de código: http://jsfiddle.net/TroyAlford/SNKfd/ muestra mi enfoque actual. La mayoría de los JS solo completan la tabla con valores aleatorios, pero la última parte es lo que impulsa la capacidad de desplazamiento izquierda / derecha.
$tbody.bind(''scroll'', function(ev) {
var $css = { ''left'': -ev.target.scrollLeft };
$thead.css($css);
$tfoot.css($css);
});
NOTA: El ejemplo proporcionado no se procesa correctamente en IE, y requiere jQuery para proporcionar el desplazamiento horizontal. No me importa el desplazamiento horizontal de todos modos, así que está bien si una solución no lo hace.
Estuve tratando de resolver esto recientemente, y se me ocurrió una buena solución que funciona perfectamente en mi navegador (Chrome 51) y admite anchos de columna dinámicos . Debo mencionar que después de derivar mi respuesta de forma independiente también encontré una técnica similar descrita en otro lugar en la web ...
El truco es usar dos tablas idénticas colocadas una encima de la otra. La tabla inferior es visible y la tabla superior es invisible para el encabezado. La tabla superior también tiene pointer-events: none
establecido en el tbody, por lo que las interacciones del mouse llegan a la tabla de abajo. De esta manera, la mesa inferior se desplaza debajo del encabezado de la mesa superior.
Para que todo se pueda diseñar y cambiar el tamaño correctamente (cuando el usuario ajusta el ancho de la pantalla, por ejemplo), ambas tablas deben tener el mismo comportamiento en la barra de desplazamiento. Sin embargo, la barra de desplazamiento de la tabla superior se ignora gracias a los pointer-events: none
y se puede hacer invisible con:
<style>
.hiddenScrollbar::-webkit-scrollbar {
background-color: transparent;
}
</style>
Aquí está el código completo:
<html>
<head>
<style>
td {
border: 1px solid black;
white-space: nowrap;
}
th {
background-color: gray;
border: 1px solid black;
white-space: nowrap;
}
.hiddenScrollbar::-webkit-scrollbar {
background-color: transparent;
}
</style>
</head>
<body>
Table test. Use mouse wheel to scroll or scroll to the right to see vertical scroll bar. You can also remove the outermost div if you don''t want a horizontal scroll bar.
<br/>
<div style="display: inline-block; height: 10em; width: 15em; overflow-x: scroll; overflow-y: hidden">
<div style="position: relative;">
<div style="display: inline-block; position: absolute; left: 0px; top: 0px; height: 10em; overflow-y: scroll">
<table style="border-collapse: collapse;">
<thead>
<tr>
<th>Column 1</th>
<th>Another Column</th>
</tr>
</thead>
<tbody>
<tr>
<td>Data 1</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 2</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 3</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 4</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 5</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 6</td>
<td>12340921375021342354235 very long...</td>
</tr>
<tr>
<td>Data 7</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 8</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 9</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 10</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 11</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 12</td>
<td>123409213750213</td>
</tr>
</tbody>
</table>
</div>
<div class="hiddenScrollbar" style="display: inline-block; pointer-events: none; position: relative; left: 0px; top: 0px; height: 10em; overflow-y: scroll">
<table style="border-collapse: collapse;">
<thead style="pointer-events: auto">
<tr>
<th>Column 1</th>
<th>Another Column</th>
</tr>
</thead>
<tbody style="visibility: hidden">
<tr>
<tr>
<td>Data 1</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 2</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 3</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 4</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 5</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 6</td>
<td>12340921375021342354235 very long...</td>
</tr>
<tr>
<td>Data 7</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 8</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 9</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 10</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 11</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 12</td>
<td>123409213750213</td>
</tr>
</tr>
</tbody>
</table>
</div>
</div>
</div><br/>
Stuff after table.
</body>
</html>
Advertencias: se requiere más trabajo para probar que esto funciona en otros navegadores. También fui más bien liberal al mezclar estilos de hojas de estilo y línea. Sin embargo, creo que el concepto general es la mejor manera de hacerlo, ya que si el navegador objetivo lo admite. Los únicos problemas de funcionalidad / visualización son que si desea una barra de desplazamiento horizontal, la barra de desplazamiento vertical puede desplazarse fuera de la vista (como se muestra en el fragmento). Sin embargo, aún puede desplazarse con la rueda del mouse. Además, no puede tener un fondo transparente en el encabezado (de lo contrario, la tabla de abajo se mostraría). Finalmente necesita una forma de generar dos tablas idénticas. Personalmente, estoy utilizando react.js y es fácil hacerlo con reaccionar, pero php u otra generación del servidor o javascript también funcionarán.
Hasta donde yo sé, no hay una forma estándar de lograr esto solo con CSS, aunque creo que debería haberlo. Los navegadores Mozilla solían soportar encabezados fijos con un cuerpo desplazable, pero lo han eliminado en los últimos años.
Después de investigar un poco, incluso encontrar esta publicación, un amigo acaba de desarrollar esta solución para mí; usa Javascript pero no bibliotecas enlatadas, y el único requisito para el marcado HTML es que la tabla tenga un nombre de identificación. Luego, en window.onload, para llamar a una función de Javascript para cada tabla, proporcionando el id, alto y ancho. Si Javascript está desactivado en el navegador, toda la tabla se muestra de acuerdo con su marcado original. Si Javascript está habilitado, la tabla se ajusta al alto y ancho especificados, y tbody se desplaza, y si thead y tfoot existen, se fijan en la parte superior e inferior.
Inspirado por la respuesta de @Purag, aquí hay otra solución de flexbox:
/* basic settings */
table { display: flex; flex-direction: column; width: 200px; }
tr { display: flex; }
th:nth-child(1), td:nth-child(1) { flex-basis: 35%; }
th:nth-child(2), td:nth-child(2) { flex-basis: 65%; }
thead, tbody { overflow-y: scroll; }
tbody { height: 100px; }
/* color settings*/
table, th, td { border: 1px solid black; }
tr:nth-child(odd) { background: #EEE; }
tr:nth-child(even) { background: #AAA; }
thead tr:first-child { background: #333; }
th:first-child, td:first-child { background: rgba(200,200,0,0.7); }
th:last-child, td:last-child { background: rgba(255,200,0,0.7); }
<table>
<thead>
<tr>
<th>a
<th>bbbb
<tbody>
<tr>
<td>fooo vsync dynamic
<td>bar
<tr>
<td>a
<td>b
<tr>
<td>a
<td>b
<tr>
<td>a
<td>b
<tr>
<td>a
<td>b
<tr>
<td>a
<td>b
<tr>
<td>a
<td>b
</table>
Lo he logrado fácilmente usando este código:
Entonces tienes una estructura como esta:
<table>
<thead><tr></tr></thead>
<tbody><tr></tr></tbody>
</table>
solo estilo el thead con:
<style>
thead{
position: -webkit-sticky;
position: -moz-sticky;
position: -ms-sticky;
position: -o-sticky;
position: sticky;
top: 0px;
}
</style>
Tres cosas a considerar:
Primero, esta propiedad es nueva. No es compatible en absoluto, aparte de las versiones beta de los navegadores basados en Webkit. Entonces formador de salvedades. De nuevo, si realmente desea que sus usuarios se beneficien de los encabezados fijos, vaya con una implementación de JavaScript.
En segundo lugar, si lo usa, deberá incorporar prefijos de proveedor. Tal vez posición: pegajoso funcionará un día. Por ahora, sin embargo, necesitas usar position: -webkit-sticky (y los demás, revisa el bloque de css más arriba en esta publicación).
En tercer lugar, no hay ningún valor predeterminado de posicionamiento en este momento, por lo que debe incluir al menos top: 0; en la misma declaración css que la posición: -webkit-sticky. De lo contrario, simplemente se desplazará fuera de la pantalla.
Otra implementación pero sin ningún desbordamiento en tbody
y columnas dinámicas. Requiere JavaScript sin embargo. Un contenedor div
se usa para albergar los encabezados de columna. Cuando la tabla se desplaza más allá del puerto de visualización, aparece un encabezado fijo en la parte superior. Si la tabla se desplaza horizontalmente, el encabezado fijo se desplaza también.
Los encabezados de las columnas se crean usando elementos span
con display: inline-block
y un margen negativo se usa para desplazar el encabezado horizontalmente. También optimizado utilizando RequestAnimationFrame
para evitar cualquier jank.
function rAF(scrollLeft) {
var offsetLeft = 0 - scrollLeft;
$(''.hdr__inner span:first-child'').css(''margin-left'', offsetLeft);
}
Si tiene la opción de dar un ancho fijo a las celdas de la tabla (y una altura fija al encabezado), puede usar la opción position: fixed
:
http://jsfiddle.net/thundercracker/ZxPeh/23/
Solo tendrías que pegarlo en un iframe
. También podría tener un desplazamiento horizontal al darle al iframe
una barra de desplazamiento (creo).
Editar 2015
Si puede vivir con una predefinición del ancho de las celdas de su tabla (por porcentaje), entonces aquí hay una solución un poco más elegante (solo CSS):
Solo con CSS:
CSS :
tr {
width: 100%;
display: inline-table;
table-layout: fixed;
}
table{
height:300px; // <-- Select the height of the table
display: -moz-groupbox; // Firefox Bad Effect
}
tbody{
overflow-y: scroll;
height: 200px; // <-- Select the height of the body
width: 100%;
position: absolute;
}
Bootply : http://www.bootply.com/AgI8LpDugl
Sorprendido, una solución que usa flexbox no se ha publicado todavía.
Aquí está mi solución usando display: flex
y un uso básico de :after
(gracias a Luggage ) para mantener la alineación incluso con la barra de desplazamiento rellenando un poco el tbody
. Esto se ha verificado en Chrome 45, Firefox 39 y MS Edge . Se puede modificar con propiedades prefijadas para trabajar en IE11, y más aún en IE10 con un hack de CSS y la sintaxis de flexbox de 2012 .
Tenga en cuenta que el ancho de la mesa puede ser modificado; esto incluso funciona al 100%
ancho.
La única advertencia es que todas las celdas de la tabla deben tener el mismo ancho. A continuación se muestra un ejemplo claramente inventado, pero funciona bien cuando el contenido de las celdas varía (las celdas de la tabla tienen el mismo ancho y la misma envoltura de palabras, lo que obliga a Flexbox a mantener el mismo ancho independientemente del contenido). Here hay un ejemplo donde los contenidos de las celdas son diferentes.
Solo aplica la clase .scroll
a una tabla que quieras desplazarte, y asegúrate de que tenga un thead
:
.scroll {
border: 0;
border-collapse: collapse;
}
.scroll tr {
display: flex;
}
.scroll td {
padding: 3px;
flex: 1 auto;
border: 1px solid #aaa;
width: 1px;
word-wrap: break;
}
.scroll thead tr:after {
content: '''';
overflow-y: scroll;
visibility: hidden;
height: 0;
}
.scroll thead th {
flex: 1 auto;
display: block;
border: 1px solid #000;
}
.scroll tbody {
display: block;
width: 100%;
overflow-y: auto;
height: 200px;
}
<table class="scroll" width="400px">
<thead>
<tr>
<th>Header</th>
<th>Header</th>
<th>Header</th>
<th>Header</th>
<th>Header</th>
<th>Header</th>
</tr>
</thead>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
</table>
Tuve el mismo problema y después de pasar 2 días investigando encontré esta solución de Ksesocss que me queda bien y que tal vez también sea buena para ti. Permite encabezado fijo y ancho dinámico y solo usa CSS. El único problema es que la fuente está en español, pero aquí puedes encontrar el código html y css.
Este es el enlace:
http://ksesocss.blogspot.com/2014/10/responsive-table-encabezado-fijo-scroll.html
espero que esto ayude
Veo que este hilo ha estado inactivo por un tiempo, pero este tema me interesó y ahora con algunos selectores de CSS3, esto se volvió más fácil (y bastante factible con solo CSS).
Esta solución se basa en tener una altura máxima del contenedor de la mesa. Pero es compatible siempre que pueda usar el selector de :first-child
.
Violín here .
Si alguien puede mejorar esta respuesta, ¡por favor hazlo! ¡Planeo usar esta solución en una aplicación comercial pronto!
HTML
<div id="con">
<table>
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
CSS
#con{
max-height:300px;
overflow-y:auto;
}
thead tr:first-child {
background-color:#00f;
color:#fff;
position:absolute;
}
tbody tr:first-child td{
padding-top:28px;
}
si se pone duro cuando todas las soluciones mencionadas no funcionan (como me pasó a mí), prueba una solución de dos mesas, como expliqué en esta respuesta
https://.com/a/47722456/6488361