Tabla con encabezado fijo y columna fija en css puro

97

Necesito crear una tabla html (o algo similar) con un encabezado fijo y una primera columna fija.

Todas las soluciones que he visto hasta ahora usan Javascript o jQuerypara configurar scrollTop / scrollLeft, pero no funciona sin problemas en navegadores móviles, así que estoy buscando una solución CSS pura.

Encontré una solución para una columna fija aquí: jsfiddle.net/C8Dtf/20/ pero no sé cómo puedo mejorarla para que el encabezado también sea fijo.

Quiero que funcione en navegadores webkit o use algunas css3características, pero repito, no quiero usarlo Javascriptpara desplazarse.

EDITAR: Este es un ejemplo del comportamiento que quiero lograr: https://web.archive.org/web/20130829032141/http://datatables.net/release-datatables/extras/FixedColumns/css_size.html

panfil
fuente
No veo dónde <html> <table> con encabezado fijo <thead> tiene que ver con css-level-3 por el momento. Qué mas tienes ? Qué has intentado hasta ahora ?
Milche Patern
Intenté aplicar un positioncomportamiento complejo a filas y celdas, pero no entiendo bien dónde es aplicable o no.
panfil
2
Esta respuesta puede ayudarlo a stackoverflow.com/questions/14834198/…
Garry

Respuestas:

141

Una solución CSS pura real con una fila de encabezado fija y una primera columna

Tuve que crear una tabla con un encabezado fijo y una primera columna fija usando CSS puro y ninguna de las respuestas aquí era lo que quería.

La position: stickypropiedad admite tanto pegarse a la parte superior (como he visto que se usa más) como a los lados en las versiones modernas de Chrome, Firefox y Edge. Esto se puede combinar con una divque tiene la overflow: scrollpropiedad de brindarle una tabla con encabezados fijos que se pueden colocar en cualquier lugar de su página:

Coloque su mesa en un recipiente:

<div class="container">
  <table></table>
</div>

Úselo overflow: scrollen su contenedor para habilitar el desplazamiento:

div.container {
  overflow: scroll;
}

Como señaló Dagmar en los comentarios, el contenedor también requiere un max-widthy un max-height.

Utilice position: stickytener celdas de la tabla se adhieren a la orilla y top, righto leftpara elegir el borde de palo para:

thead th {
  position: -webkit-sticky; /* for Safari */
  position: sticky;
  top: 0;
}

tbody th {
  position: -webkit-sticky; /* for Safari */
  position: sticky;
  left: 0;
}

Como MarredCheese mencionó en los comentarios, si su primera columna contiene <td>elementos en lugar de <th>elementos, puede usarlos tbody td:first-childen su CSS en lugar detbody th

Para que el encabezado de la primera columna se pegue a la izquierda, use:

thead th:first-child {
  left: 0;
  z-index: 1;
}

https://jsfiddle.net/qwubvg9m/1/

Matthew Schlachter
fuente
22
Esta parece la mejor respuesta.
user1190132
9
@PirateApp Si conoce el widthde su primera columna, puede usarlo position: stickyen las celdas de su segunda columna con un leftvalor igual al de su primera columna width: jsfiddle.net/wvypo83c/794
Matthew Schlachter
4
¡Esta respuesta demuestra que vale la pena leerla hasta el final!
mlerley
4
Esto no funciona sin un ancho máximo y una altura máxima establecidos en el contenedor.
Dagmar
9
Esta respuesta es un faro que nos guía a casa a través de un mar interminable de respuestas defectuosas, demasiado complicadas y que hacen perder el tiempo de los carteles sorprendentemente seguros y desconcertantemente votados aquí en SO y en toda la web. Tenga en cuenta que si su primera columna contiene <td>elementos en lugar de <th>elementos, puede usarlos tbody td:first-childen su CSS en lugar de tbody th.
MarredCheese
32

Hoy en día, esto se puede lograr usando CSS solo con position: stickypropiedad.

Aquí va un fragmento:

(jsFiddle: https://jsfiddle.net/hbqzdzdt/5/ )

.grid-container {
  display: grid; /* This is a (hacky) way to make the .grid element size to fit its content */
  overflow: auto;
  height: 300px;
  width: 600px;
}
.grid {
  display: flex;
  flex-wrap: nowrap;
}
.grid-col {
  width: 150px;
  min-width: 150px;
}

.grid-item--header {
  height: 100px;
  min-height: 100px;
  position: sticky;
  position: -webkit-sticky;
  background: white;
  top: 0;
}

.grid-col--fixed-left {
  position: sticky;
  left: 0;
  z-index: 9998;
  background: white;
}
.grid-col--fixed-right {
  position: sticky;
  right: 0;
  z-index: 9998;
  background: white;
}

.grid-item {
  height: 50px;
  border: 1px solid gray;
}
<div class="grid-container">
  <div class="grid">
    <div class="grid-col grid-col--fixed-left">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col grid-col--fixed-right">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
    </div>

  </div>
</div>

Respecto a la compatibilidad. Funciona en todos los navegadores principales, pero no en IE. Hay un polyfill para position: stickypero nunca lo probé.

Álvaro
fuente
2
¡Esto es genial, me encanta!
Capitán Lu
3
cualquier forma de lograr esto con <table> -tags y no <div>
Andreas
1
Creo que esto no tendrá un buen rendimiento si está desarrollando una aplicación y necesita recorrer los registros para imprimir esta tabla porque para cada columna de la tabla, debe recorrer la matriz de registros completa. Este HTML funciona columna por columna.
igasparetto
@igasparetto En realidad, puede organizar las filas / columnas al revés y la solución aún funcionaría. Si tengo algún tiempo más tarde, puedo crear un fragmento con la fila ordenada en la cuadrícula -> columna.
Álvaro
2
Aconsejaría no mostrar datos tabulares sin usar <table> y etiquetas asociadas. Existen varios problemas para romper el uso previsto de HTML de esta manera, incluida la accesibilidad. Ver también: w3.org/WAI/tutorials/tables
Ben Morris
15

Esto no es tarea fácil.

El siguiente enlace es a una demostración funcional:

Enlace actualizado de acuerdo con el comentario de lanoxx

http://jsfiddle.net/C8Dtf/366/

Solo recuerda agregar estos:

<script type="text/javascript" charset="utf-8" src="http://datatables.net/release-datatables/media/js/jquery.js"></script>
<script type="text/javascript" charset="utf-8" src="http://datatables.net/release-datatables/media/js/jquery.dataTables.js"></script>
<script type="text/javascript" charset="utf-8" src="http://datatables.net/release-datatables/extras/FixedColumns/media/js/FixedColumns.js"></script>

No veo ninguna otra forma de lograrlo. Especialmente no usando solo css.

Esto es mucho por lo que pasar. Espero que esto ayude :)

Phillip-juan
fuente
Para cambiar el uso del filtro: "bFilter": false
lanoxx
6
Que es posible lograr esto con sólo el css. No es fácil, pero es posible.
Jimmy T.
de aproximadamente 10 soluciones, esta fue la única que funcionó. Por cierto, para eliminar el "Mostrando 1 a 57 de 57 entradas", agregue "bInfo" : falsea la .dataTable()llamada
hansaplast
tablas de datos == "impresionante"
billynoah
rechazando esta solución porque es mala. el theadse encuentra en su propia mesa que no está unido a los cambios de tdelementos, de modo que si un texto de la celda es largo, la thanchura no se ajustará en consecuencia.
vsync
14

Todas estas sugerencias son geniales y todo, pero solo están arreglando el encabezado o una columna, no ambas, o están usando javascript. La razón: no cree que se pueda hacer con CSS puro. La razón:

Si fuera posible hacerlo, necesitaría anidar varios divs desplazables uno dentro del otro, cada uno con un desplazamiento en una dirección diferente. Luego, necesitaría dividir su tabla en tres partes: el encabezado fijo, la columna fija y el resto de los datos.

Multa. Pero ahora el problema: puede hacer que uno de ellos se quede quieto cuando se desplaza, pero el otro está anidado dentro del área de desplazamiento del primero y, por lo tanto, está sujeto a desplazarse fuera de la vista, por lo que no se puede fijar en su lugar en la pantalla. 'Ah-ha' dices 'pero de alguna manera puedo usar la posición absoluta o fija para hacer eso', no, no puedes. Tan pronto como lo haga, perderá la capacidad de desplazarse por ese contenedor. Es una situación de la gallina y el huevo: no puedes tener ambos, se cancelan entre sí.

Creo que la única solución es a través de javascript. Debe separar completamente los tres elementos y mantener sus posiciones sincronizadas a través de javascript. Hay buenos ejemplos en otras publicaciones de esta página. Este también vale la pena verlo:

http://tympanus.net/codrops/2014/01/09/sticky-table-headers-columns/

PretorianNZ
fuente
9

Hice algunos cambios en jsfiddle. Esto podría ser lo que estás intentando hacer.

http://jsfiddle.net/C8Dtf/81/

He codificado los títulos de esta manera:

<table id="left_table" class="freeze_table">
    <tr class='tblTitle'>
         <th>Title 1</th>
         <th>Title 2</th>
    </tr>
</table>

Y también agregué algunos estilos.

.tblTitle{
   position:absolute;
    top:0px;
    margin-bottom:30px;
    background:lightblue;
}
td, th{
    padding:5px;
    height:40px;
    width:40px;
    font-size:14px;
}

Espero que esto sea lo que quieres :)

Phillip-juan
fuente
1
Necesito un encabezado de la tabla derecha para desplazarme junto con su contenido.
panfil
Aquí está la URL: jsfiddle.net/C8Dtf/84 . Solo necesita jugar con el estilo de la mesa de la derecha para alinear las dos mesas.
Phillip-juan
No. No lo entiendes del todo. Necesito que el encabezado de la tabla derecha se fije en la parte superior para que aún sea visible cuando la tabla se desplaza hacia arriba y hacia abajo, pero cuando la tabla se desplaza hacia la derecha o hacia la izquierda, el encabezado debe desplazarse hacia la derecha o hacia la izquierda, pero aún estar fijo en la parte superior. Lo siento por mis malas habilidades en inglés.
Panfil
Entonces, ¿desea que el encabezado de la tabla de la derecha se corrija cuando se desplaza verticalmente y que se desplace cuando se desplaza horizontalmente?
Phillip-juan
Este es un ejemplo del comportamiento que quiero lograr: datatables.net/release-datatables/extras/FixedColumns/…
panfil
9

Un ejemplo usando solo CSS:

.table {
  table-layout: fixed;
  width: 500px;
  border-collapse: collapse;
}

.header th {
  font-family: Calibri;
  font-size: small;
  font-weight: lighter;
  border-left: 1px solid #000;
  background: #d0d0d0;
}

.body_panel {
  display: inline-block;
  width: 520px;
  height: 300px;
  overflow-y: scroll;
}

.body tr {
  border-bottom: 1px solid #d0d0d0;
}

.body td {
  border-left: 1px solid #d0d0d0;
  padding-left: 3px;
  font-family: Calibri;
  font-size: small;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
<body>

  <table class="table">

    <thead class="header">

      <tr>
        <th style="width:20%;">teste</th>
        <th style="width:30%;">teste 2</th>
        <th style="width:50%;">teste 3</th>
      </tr>

    </thead>
  </table>

  <div class="body_panel">

    <table class="table">
      <tbody class="body">

        <tr>
          <td style="width:20%;">asbkj k kajsb ksb kabkb</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

      </tbody>
    </table>

  </div>

</body>

Dyego.JhOu
fuente
3
No solo necesitaba que lo arreglaran, sino también la primera columna.
panfil
Este ejemplo muestra un enfoque con dos tablas en html: una tabla representa solo el encabezado; la segunda tabla representa solo las filas, pero lo hace dentro de a div. Es el divque permite el desplazamiento de filas mientras el encabezado permanece en el mismo lugar. Este enfoque funcionó para mis necesidades.
David Tansey
Si también hay un desplazamiento horizontal, necesita algo de JS para sincronizar las posiciones de desplazamiento de las tablas.
Zoltán Tamási
4

Para corregir tanto los encabezados como las columnas, puede usar el siguiente complemento:


Actualizado en julio de 2019

Recientemente también surgió una solución CSS pura que se basa en la propiedad CSS position: sticky;( aquí para obtener más detalles al respecto) aplicada a cada THelemento (en lugar de su contenedor principal)

Luca Detomi
fuente
1
El primer enlace está roto. El segundo usa jQuery.
PussInBoots
Respuesta actualizada para eliminar el enlace muerto
Luca Detomi
3

Encontré una excelente solución de Paul O'Brien para el problema y me gustaría compartir el enlace: https://codepen.io/paulobrien/pen/LBrMxa

Eliminé el estilo del pie de página:

html {
  box-sizing: border-box;
}
*,
*:before,
*:after {
  box-sizing: inherit;
}
.intro {
  max-width: 1280px;
  margin: 1em auto;
}
.table-scroll {
  position: relative;
  width:100%;
  z-index: 1;
  margin: auto;
  overflow: auto;
  height: 350px;
}
.table-scroll table {
  width: 100%;
  min-width: 1280px;
  margin: auto;
  border-collapse: separate;
  border-spacing: 0;
}
.table-wrap {
  position: relative;
}
.table-scroll th,
.table-scroll td {
  padding: 5px 10px;
  border: 1px solid #000;
}
.table-scroll thead th {
  position: -webkit-sticky;
  position: sticky;
  top: 0;
}

th:first-child {
  position: -webkit-sticky;
  position: sticky;
  left: 0;
  z-index: 2;
  background: #ccc;
}
thead th:first-child {
  z-index: 5;
}
Artiom Kozyrev
fuente
2

Recientemente tuve que crear una solución con un grupo de encabezado fijo y una primera columna fija. Dividí mi tabla en div y usé jquery para capturar el desplazamiento de la ventana.

http://jsfiddle.net/TinT/EzXub/2346/

var prevTop = 0;
var prevLeft = 0;

$(window).scroll(function(event){
  var currentTop = $(this).scrollTop();
  var currentLeft = $(this).scrollLeft();

  if(prevLeft !== currentLeft) {
    prevLeft = currentLeft;
    $('.header').css({'left': -$(this).scrollLeft()})
  }
  if(prevTop !== currentTop) {
    prevTop = currentTop;
    $('.leftCol').css({'top': -$(this).scrollTop() + 40})
  }
});
Tristan
fuente
1

Un compañero de trabajo y yo acabamos de lanzar un nuevo proyecto de GitHub que proporciona una directiva Angular que puede usar para decorar su mesa con encabezados fijos: https://github.com/objectcomputing/FixedHeader

Se basa solo en css y angular, con una directiva que agrega algunos divs. No se requiere jQuery.

Esta implementación no tiene tantas funciones como otras implementaciones, pero si su necesidad es simplemente agregar tablas fijas, creemos que esta podría ser una buena opción.

user3221325
fuente
1

Después de dos días luchando con Internet Explorer 9 + Chrome + Firefox (Windows) y Safari (Mac), encontré un sistema que es

  • Compatible con todos estos navegadores
  • Sin usar javascript
  • Usando solo une div y una tabla
  • Encabezado y pie de página fijos (excepto IE), con cuerpo desplazable. Encabezado y cuerpo con el mismo ancho de columna

Resultado: ingrese la descripción de la imagen aquí

HTML:

  <thead>
    <tr>
      <th class="nombre"><%= f.label :cost_center %></th>
      <th class="cabecera cc">Personal</th>
      <th class="cabecera cc">Dpto</th>
    </tr>
  </thead>
  <tbody>
    <% @cost_centers.each do |cc| %>
    <tr>
      <td class="nombre"><%= cc.nombre_corto %></td>
      <td class="cc"><%= cc.cacentrocoste %></td>
      <td class="cc"><%= cc.cacentrocoste_dpto %></td>
    </tr>
    <% end %>
  </tbody>
  <tfoot>
    <tr>
      <td colspan="3"><a href="#">Mostrar mas usuarios</a></td>
    </tr>
  </tfoot>
</table>

CSS:

div.cost_center{
  width:320px;
  font-size:75%;
  margin-left:5px;
  margin-top:5px;
  margin-bottom: 2px;
  float: right;
  display: inline-block;
  overflow-y: auto;
  overflow-x: hidden;
  max-height:300px;  
}

div.cost_center label { 
  float:none;
  font-size:14px;
}

div.cost_center table{
  width:300px;
  border-collapse: collapse; 
  float:right;
  table-layout:fixed;
}

div.cost_center table tr{
  height:16px;
}
div.cost_center th{
  font-weight:normal;
}

div.cost_center table tbody{
  display: block;
  overflow: auto;
  max-height:240px;
}

div.cost_center table thead{
  display:block;
}

div.cost_center table tfoot{
  display:block;
}
div.cost_center table tfoot td{
  width:280px;
}
div.cost_center .cc{
  width:60px;
  text-align: center; 
  border: 1px solid #999;
}

div.cost_center .nombre{
  width:150px;
}
div.cost_center tbody .nombre{
  border: 1px solid #999;
}

div.cost_center table tfoot td{
 text-align:center;  
 border: 1px solid #999; 
} 

div.cost_center table th, 
div.cost_center table td { 
  padding: 2px;
  vertical-align: middle; 
}

div.cost_center table tbody td {
  white-space: normal;
  font:  .8em/1.4em Verdana, sans-serif;
  color: #000;
  background-color: white;
}
div.cost_center table th.cabecera { 
  font:  0.8em/1.4em Verdana, sans-serif;
  color: #000;
  background-color: #FFEAB5;
}
Albert Català
fuente
Buen intento, pero no me funciona muy bien. En este ejemplo ( jsfiddle.net/5ka6e ), el encabezado no cambia de tamaño correctamente. Este tipo de error podría eventualmente terminar teniendo datos y encabezados que no coincidan.
darkzangel
1
Te olvidas de agregar div.cost_center table{border-collapse: collapse;}y el tercer título tiene que ser algo que encaje dentro de los 60px (en este ejemplo)
Albert Català
1

Las respuestas existentes se adaptarán a la mayoría de las personas, pero para aquellos que buscan agregar sombras debajo del encabezado fijo y a la derecha de la primera columna (fija), aquí hay un ejemplo de trabajo (CSS puro):

http://jsbin.com/nayifepaxo/1/edit?html,output

El truco principal para que esto funcione es usar ::afterpara agregar sombras a la derecha de cada una de las primeras tden cada una tr:

tr td:first-child:after {
  box-shadow: 15px 0 15px -15px rgba(0, 0, 0, 0.05) inset;
  content: "";
  position:absolute;
  top:0;
  bottom:0;
  right:-15px;
  width:15px;
}

Me tomó un tiempo (demasiado ...) hacer que todo funcionara, así que pensé que lo compartiría para aquellos que se encuentran en una situación similar.


fuente
¿Basó esto en la respuesta de alguien más y agregó la sombra?
PussInBoots
1

Necesito arreglar el pie de página del encabezado

neel upadhyay
fuente
0

Algo como esto puede funcionar para usted ... Probablemente requerirá que haya establecido anchos de columna para su fila de encabezado.

thead { 
    position: fixed;
}

http://jsfiddle.net/vkhNC/

Actualizar:

No estoy convencido de que el ejemplo que dio sea posible solo con CSS. Me encantaría que alguien me demostrara que estoy equivocado. Esto es lo que tengo hasta ahora . No es el producto terminado, pero podría ser un comienzo para usted. Espero que esto le oriente en una dirección útil, dondequiera que sea.

Bradj
fuente
No solo necesito el encabezado, sino también la primera columna.
panfil
5
El problema es que los encabezados pierden su ancho. Se ve feo con diferentes tamaños de columna de encabezado y de columna de datos.
Akash Kava
0

Ejemplo de CSS puro:

<div id="cntnr">
    <div class="tableHeader">
        <table class="table-header table table-striped table-bordered">
            <thead>
                <tr>
                    <th>this</th>
                    <th>transmission</th>
                    <th>is</th>
                    <th>coming</th>
                    <th>to</th>
                    <th>you</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>we've got it...</td>
                    <td>alright you are go</td>
                    <td>uh, we see the Earth now</td>
                    <td>we've got it...</td>
                    <td>alright you are go</td>
                    <td>uh, we see the Earth now</td>
                </tr>
            </tbody>
        </table>
    </div>


    <div class="tableBody">
        <table class="table-body table table-striped table-bordered">
            <thead>
                <tr>
                    <th>this</th>
                    <th>transmission</th>
                    <th>is</th>
                    <th>coming</th>
                    <th>to</th>
                    <th>you</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>we've got it...</td>
                    <td>alright you are go</td>
                    <td>uh, we see the Earth now</td>
                    <td>we've got it...</td>
                    <td>alright you are go</td>
                    <td>uh, we see the Earth now</td>
                </tr>
            </tbody>
        </table>
    </div>

</div>

#cntnr {
    width: auto;
    height: 200px;
    border: solid 1px #444;
    overflow: auto;
}

.tableHeader {
    position: fixed;
    height: 40px;
    overflow: hidden;
    margin-right: 18px;
    background: white;
}

.table-header tbody {
    height: 0;
    visibility: hidden;
}

.table-body thead {
    height: 0;
    visibility: hidden;
}

http://jsfiddle.net/cCarlson/L98m854d/

Inconveniente: la estructura / lógica del encabezado fijo depende bastante de dimensiones específicas, por lo que la abstracción probablemente no sea una opción viable .

Cody
fuente
Necesita un encabezado fijo y una primera columna fija.
panfil
Ah ... gracias por señalar esto, Panfil. Haré una edición. Saludos
Cody
0

Posición: sticky no funciona para algunos elementos como (thead) en Chrome y otros navegadores webkit como safari.

Pero funciona bien con (th)

body {
  background-color: rgba(0, 255, 200, 0.1);
}

.intro {
  color: rgb(228, 23, 23);
}

.wrapper {
  overflow-y: scroll;
  height: 300px;
}

.sticky {
  position: sticky;
  top: 0;
  color: black;
  background-color: white;
}
<div class="container intro">
  <h1>Sticky Table Header</h1>
  <p>Postion : sticky doesn't work for some elements like (thead) in chrome and other webkit browsers like safari. </p>
  <p>But it works fine with (th)</p>
</div>
<div class="container wrapper">
  <table class="table table-striped">
    <thead>
      <tr>
        <th class="sticky">Firstname</th>
        <th class="sticky">Lastname</th>
        <th class="sticky">Email</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>James</td>
        <td>Vince</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Jonny</td>
        <td>Bairstow</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>James</td>
        <td>Anderson</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Stuart</td>
        <td>Broad</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Eoin</td>
        <td>Morgan</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Joe</td>
        <td>Root</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Chris</td>
        <td>Woakes</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Liam</td>
        <td>PLunkett</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Jason</td>
        <td>Roy</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Alex</td>
        <td>Hales</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Jos</td>
        <td>Buttler</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Ben</td>
        <td>Stokes</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Jofra</td>
        <td>Archer</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Mitchell</td>
        <td>Starc</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Aaron</td>
        <td>Finch</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>David</td>
        <td>Warner</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Steve</td>
        <td>Smith</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Glenn</td>
        <td>Maxwell</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Marcus</td>
        <td>Stoinis</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Alex</td>
        <td>Carey</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Nathan</td>
        <td>Coulter Nile</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Pat</td>
        <td>Cummins</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Adam</td>
        <td>Zampa</td>
        <td>[email protected]</td>
      </tr>
    </tbody>
  </table>
</div>

O visite mi ejemplo de codepen :

Yoga
fuente
-2

Si solo desea usar HTML y CSS puros, tengo una solución para su problema:
en este jsFiddle puede ver una solución sin script que proporciona una tabla con un encabezado fijo. No debería ser un problema adaptar el marcado para una primera columna fija también. Solo necesitaría crear una tabla de posición absoluta para la primera columna dentro de hWrapper-div y reposicionar vWrapper-div.
Proporcionar contenido dinámico no debería ser un problema utilizando motores tentadores del lado del servidor o del lado del navegador, mi solución funciona bien en todos los navegadores modernos y navegadores más antiguos desde IE8 en adelante.

Lukas Hechenberger
fuente
-2

Solo necesito cambiar el estilo como

<table style="position: relative;">
   <thead>
      <thead>
        <tr>
           <th></th>
        </tr>
      </thead>
   </thead>
   <tbody style="position: absolute;height: 300px;overflow:auto;">
      <tr>
         <td></td>
      </tr>
   </tbody>
</table>

Demostración: https://plnkr.co/edit/Qxy5RMJBXmkaJAOjBtQn?p=preview

Omprakash Sharma
fuente
2
en su demostración, la primera columna no está arreglada
Bravo