Tabela com cabeçalho fixo e coluna fixa em CSS puro

97

Eu preciso criar uma tabela html (ou algo parecido) com um cabeçalho fixo e uma primeira coluna fixa.

Todas as soluções que vi até agora usam Javascript ou jQuerypara definir scrollTop / scrollLeft, mas não funciona bem em navegadores móveis, então estou procurando uma solução CSS pura.

Encontrei uma solução para uma coluna fixa aqui: jsfiddle.net/C8Dtf/20/ mas não sei como posso aprimorá-la para tornar o cabeçalho fixo também.

Quero que funcione em navegadores webkit ou use alguns css3recursos, mas, repito, não quero usar Javascriptpara rolar.

EDIT: Este é um exemplo do comportamento que desejo alcançar: https://web.archive.org/web/20130829032141/http://datatables.net/release-datatables/extras/FixedColumns/css_size.html

panfil
fonte
Não vejo onde <html> <table> com cabeçalho fixo <thead> tem a ver com css-level-3 no momento. O que mais você tem ? O que você tentou até agora ?
Milche Patern
Tentei aplicar um positioncomportamento complexo a linhas e células, mas não entendo muito bem onde é aplicável ou não.
panfil
2
Esta resposta pode ajudá-lo a stackoverflow.com/questions/14834198/…
Garry,

Respostas:

141

Uma solução CSS pura real com uma linha de cabeçalho fixa e primeira coluna

Tive que criar uma tabela com um cabeçalho fixo e uma primeira coluna fixa usando CSS puro e nenhuma das respostas aqui foi exatamente o que eu queria.

A position: stickypropriedade oferece suporte tanto para a fixação no topo (como já vi que é mais usada) quanto para as laterais nas versões modernas do Chrome, Firefox e Edge. Isso pode ser combinado com um divque tem a overflow: scrollpropriedade de fornecer uma tabela com cabeçalhos fixos que podem ser colocados em qualquer lugar da página:

Coloque sua mesa em um recipiente:

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

Use overflow: scrollem seu contêiner para permitir a rolagem:

div.container {
  overflow: scroll;
}

Como Dagmar apontou nos comentários, o contêiner também requer um max-widthe um max-height.

Use position: stickyter células tabela vara até a borda e top, rightou leftde escolher qual borda a vara 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 mencionou nos comentários, se sua primeira coluna contém <td>elementos em vez de <th>elementos, você pode usar tbody td:first-childem seu CSS em vez detbody th

Para que o cabeçalho da primeira coluna fique à esquerda, use:

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

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

Matthew Schlachter
fonte
22
Esta parece ser a melhor resposta.
user1190132
9
@PirateApp Se você souber o widthda sua primeira coluna, poderá usar position: stickynas células da segunda coluna com um leftvalor igual ao da primeira coluna width: jsfiddle.net/wvypo83c/794
Matthew Schlachter
4
Essa resposta prova que vale a pena ler até o fim!
mlerley
4
Isso não funciona sem max-width e max-height configurados no contêiner.
Dagmar
9
Esta resposta é um farol nos guiando de volta para casa através do mar infinito de respostas malfuncionadas, complicadas e demoradas de cartazes surpreendentemente confiantes e surpreendentemente votados aqui no SO e em toda a web. Observe que se sua primeira coluna contém <td>elementos em vez de <th>elementos, você pode usar tbody td:first-childem seu CSS em vez de tbody th.
MarredCheese
32

Hoje em dia, isso só é possível com CSS com position: stickypropriedade.

Aqui vai um snippet:

(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>

Em relação à compatibilidade. Funciona em todos os principais navegadores, mas não no IE. Existe um polyfill para, position: stickymas eu nunca tentei.

Alvaro
fonte
2
Isso é ótimo, adorei!
Capitão Lu
3
qualquer maneira de conseguir isso com <table> -tags e não <div>
Andreas
1
Acho que isso não terá um bom desempenho se você estiver desenvolvendo um aplicativo e precisar percorrer os registros para imprimir esta tabela, porque para cada coluna na tabela, você tem que percorrer todo o array do registro. Este HTML funciona coluna por coluna.
igasparetto
@igasparetto Você pode realmente organizar as linhas / colunas ao contrário e a solução ainda funcionaria. Se eu tiver algum tempo depois, posso criar um trecho com a linha ordenada da grade -> coluna.
Alvaro
2
Aconselho a não exibir dados tabulares sem usar <table> e tags associadas. Existem vários problemas em interromper o uso pretendido de HTML dessa forma, incluindo acessibilidade. Veja também: w3.org/WAI/tutorials/tables
Ben Morris
15

Isso não é tarefa fácil.

O link a seguir é para uma demonstração de trabalho:

Link atualizado de acordo com o comentário de lanoxx

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

Apenas lembre-se de adicionar estes:

<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>

não vejo outra maneira de conseguir isso. Especialmente não usando apenas css.

Isso é muito para passar. Espero que isto ajude :)

Phillip-juan
fonte
Para trocar o filtro use: "bFilter": false
lanoxx
6
Ele é possível conseguir isso com apenas css. Não é fácil, mas é possível.
Jimmy T.
de cerca de 10 soluções, esta foi a única que funcionou. A propósito, para remover o "Mostrando 1 a 57 de 57 entradas" adicionar "bInfo" : falseà .dataTable()chamada
hansaplast
datatables == "incrível"
billynoah
downvoting esta solução porque é ruim. O theadestá em sua própria tabela, que não está limitado a mudanças de tdelementos, portanto, se o texto de uma célula for longo, a thlargura não se ajustará de acordo.
vsync
14

Todas essas sugestões são ótimas e tudo, mas elas estão apenas corrigindo o cabeçalho ou uma coluna, não ambos, ou estão usando javascript. O motivo - não acredito que possa ser feito em CSS puro. O motivo:

Se fosse possível fazer isso, você precisaria aninhar vários divs roláveis ​​um dentro do outro, cada um com uma rolagem em uma direção diferente. Em seguida, você precisaria dividir sua tabela em três partes - o cabeçalho fixo, a coluna fixa e o resto dos dados.

Bem. Mas agora o problema - você pode fazer um deles ficar parado quando você rola, mas o outro está aninhado dentro da área de rolagem do primeiro e, portanto, está sujeito a ser rolado para fora da vista, então não pode ser fixado no a tela. 'Ah-ha' você diz 'mas eu posso de alguma forma usar a posição absoluta ou fixa para fazer isso' - não, você não pode. Assim que você fizer isso, você perderá a capacidade de rolar aquele contêiner. É uma situação do ovo e da galinha - você não pode ter os dois, eles se anulam.

Acredito que a única solução seja através do javascript. Você precisa separar completamente os três elementos e manter suas posições sincronizadas por meio de javascript. Existem bons exemplos em outras postagens desta página. Este também vale a pena dar uma olhada:

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

PretorianNZ
fonte
9

Fiz algumas mudanças no jsfiddle. Isso pode ser o que você está tentando fazer.

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

Codifiquei os títulos da seguinte forma:

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

E adicionei alguns estilos também.

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

Espero que seja isso que você quer :)

Phillip-juan
fonte
1
Preciso de um cabeçalho da tabela certa para rolar junto com seu conteúdo.
panfil
Aqui está o URL: jsfiddle.net/C8Dtf/84 . Você só precisa brincar com o estilo da mesa à direita para alinhar as duas mesas.
Phillip-juan
Não. Você não entende direito. Preciso que o cabeçalho da tabela à direita seja fixado no topo para que ainda fique visível quando a tabela rola para cima e para baixo, mas quando a tabela rola para a direita ou esquerda, o cabeçalho deve rolar para a direita ou esquerda, mas ainda deve ser fixado no topo. Me desculpe por meu péssimo inglês.
panfil
Então, deseja que o cabeçalho da tabela à direita seja corrigido ao rolar verticalmente e rolar ao rolar horizontalmente?
Phillip-juan
Este é um exemplo do comportamento que desejo alcançar: datatables.net/release-datatables/extras/FixedColumns/…
panfil
9

Um exemplo usando apenas 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
fonte
3
Eu precisava não só de consertar o heder, mas também da primeira coluna.
panfil de
Este exemplo mostra uma abordagem com duas tabelas no html: uma tabela renderiza apenas o cabeçalho; a segunda tabela renderiza apenas as linhas, mas o faz dentro de a div. É o divque permite a rolagem de linha enquanto o cabeçalho permanece no mesmo lugar. Essa abordagem funcionou para minhas necessidades.
David Tansey de
Se houver rolagem horizontal também, você precisará de algum JS para sincronizar as posições de rolagem das tabelas.
Zoltán Tamási
4

Para corrigir cabeçalhos e colunas, você pode usar o seguinte plug-in:


Atualizado em julho de 2019

Recentemente, surgiu também uma solução CSS pura que é baseada na propriedade CSS position: sticky;( aqui para mais detalhes sobre isso) aplicada a cada THitem (em vez de seu contêiner pai)

Luca Detomi
fonte
1
O primeiro link está quebrado. O segundo usa jQuery.
PussInBoots
Resposta atualizada para remover link
inativo
3

Encontrei uma excelente solução de Paul O'Brien para o problema e gostaria de compartilhar o link: https://codepen.io/paulobrien/pen/LBrMxa

Removi o estilo do rodapé:

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
fonte
2

Recentemente, tive que criar uma solução com um grupo de cabeçalho fixo e uma primeira coluna fixa. Eu dividi minha tabela em div e usei jquery para capturar a rolagem da janela.

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
fonte
1

Um colega de trabalho e eu acabamos de lançar um novo projeto GitHub que fornece uma diretiva Angular que você pode usar para decorar sua tabela com cabeçalhos fixos: https://github.com/objectcomputing/FixedHeader

Ele depende apenas do css e do angular, com uma diretiva que adiciona alguns divs. Não é necessário jQuery.

Esta implementação não é tão completa quanto algumas outras implementações, mas se sua necessidade for simplesmente adicionar tabelas fixas, achamos que esta pode ser uma boa opção.

user3221325
fonte
1

Depois de dois dias lutando com Internet Explorer 9 + Chrome + Firefox (Windows) e Safari (Mac), encontrei um sistema que é

  • Compatível com todos esses navegadores
  • Sem usar javascript
  • Usando apenas une div e uma mesa
  • Cabeçalho e rodapé corrigidos (exceto para IE), com corpo rolável. Cabeçalho e corpo com as mesmas larguras de coluna

Resultado: insira a descrição da imagem aqui

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à
fonte
Boa tentativa, mas não funciona muito bem para mim. Neste exemplo ( jsfiddle.net/5ka6e ), o cabeçalho não é redimensionado corretamente. Esse tipo de erro pode eventualmente resultar em incompatibilidade de dados e cabeçalho.
darkzangel de
1
Você se esquece de adicionar div.cost_center table{border-collapse: collapse;}e a terceira legenda deve ser algo que se encaixe nos 60px (neste exemplo)
Albert Català
1

As respostas existentes são adequadas para a maioria das pessoas, mas para aqueles que desejam adicionar sombras sob o cabeçalho fixo e à direita da primeira coluna (fixa), aqui está um exemplo prático (css puro):

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

O principal truque para fazer isso funcionar é ::afteradicionar sombras à direita de cada uma das primeiras tdde cada 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;
}

Levei um tempo (muito tempo ...) para fazer tudo funcionar, então decidi compartilhar para aqueles que estão em uma situação semelhante.


fonte
Você baseou isso na resposta de outra pessoa e adicionou a sombra?
PussInBoots
1

precisa corrigir o rodapé do cabeçalho

Neel Upadhyay
fonte
0

Algo assim pode funcionar para você ... Provavelmente exigirá que você defina as larguras das colunas para a linha do cabeçalho.

thead { 
    position: fixed;
}

http://jsfiddle.net/vkhNC/

Atualizar:

Não estou convencido de que o exemplo que você deu seja possível apenas com CSS. Eu adoraria que alguém provasse que estou errado. Aqui está o que tenho até agora . Não é o produto acabado, mas pode ser um começo para você. Espero que isso lhe indique uma direção útil, onde quer que seja.

bradj
fonte
Preciso não apenas do cabeçalho, mas também da primeira coluna corrigida.
panfil
5
O problema é que os cabeçalhos perdem sua largura. Parece feio com tamanhos de coluna de cabeçalho e de coluna de dados diferentes.
Akash Kava de
0

Exemplo 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/

Desvantagem: a estrutura / lógica do cabeçalho fixo depende bastante de dimensões específicas, portanto, a abstração provavelmente não é uma opção viável .

Cody
fonte
Precisa de cabeçalho fixo e primeira coluna fixa.
panfil
Ah ... obrigado por apontar isso, panfil. Vou fazer uma edição. Saúde
Cody
0

Posição: sticky não funciona para alguns elementos como (thead) no Chrome e outros navegadores de webkit como safari.

Mas funciona bem com (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>

Ou visite meu exemplo de código :

Ioga
fonte
-1

Acho que isso vai te ajudar: https://datatables.net/release-datatables/extensions/FixedHeader/examples/header_footer.html

Em suma, se você sabe como criar uma dataTable, você só precisa adicionar esta linha jQuery ao seu fundo:

$(document).ready(function() {
    var table = $('#example').DataTable();

    new $.fn.dataTable.FixedHeader( table, {
        bottom: true
    } );
} );

bottom: true // serve para tornar o cabeçalho Bottom fixo também.

JackSparrow
fonte
-2

Se você quiser usar apenas HTML e CSS puros, eu tenho uma solução para seu problema:
Neste jsFiddle você pode ver uma solução sem script que fornece uma tabela com um cabeçalho fixo. Não deve ser um problema adaptar a marcação para uma primeira coluna fixa também. Você só precisa criar uma tabela com posição absoluta para a primeira coluna dentro do hWrapper-div e reposicionar o vWrapper-div.
Fornecer conteúdo dinâmico não deve ser um problema usando motores tentadores do lado do servidor ou do navegador, minha solução funciona bem em todos os navegadores modernos e navegadores mais antigos a partir do IE8.

Lukas Hechenberger
fonte
-2

Só preciso mudar o estilo

<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>

Demo: https://plnkr.co/edit/Qxy5RMJBXmkaJAOjBtQn?p=preview

Omprakash Sharma
fonte
2
em sua demonstração, a primeira coluna não foi corrigida
Bravo