Tabela ze stałym nagłówkiem i stałą kolumną w czystym CSS

100

Muszę utworzyć tabelę html (lub coś podobnego) ze stałym nagłówkiem i stałą pierwszą kolumną.

Każde rozwiązanie, które do tej pory widziałem, używa JavaScript lub jQuery ustawia scrollTop / scrollLeft, ale nie działa płynnie w przeglądarkach mobilnych, więc szukam czystego rozwiązania CSS.

Znalazłem rozwiązanie dla stałej kolumny tutaj: jsfiddle.net/C8Dtf/20/ ale nie wiem, jak mogę to ulepszyć, aby naprawić również nagłówek.

Chcę, aby działał w przeglądarkach webkit lub korzystał z niektórych css3funkcji, ale powtarzam, nie chcę używać Javascriptdo przewijania.

EDYCJA: To jest przykład zachowania, które chcę osiągnąć: https://web.archive.org/web/20130829032141/http://datatables.net/release-datatables/extras/FixedColumns/css_size.html

panfil
źródło
Nie wiem, gdzie <html> <table> ze stałym nagłówkiem <thead> ma w tej chwili do czynienia z css-level-3. Co jeszcze masz ? Czego spróbowałeś do tej pory ?
Milche Patern
Próbowałem zastosować złożone positionzachowanie do wierszy i komórek, ale nie do końca rozumiem, gdzie jest to możliwe, czy nie.
panfil
2
Ta odpowiedź może pomóc ci stackoverflow.com/questions/14834198/…
Garry

Odpowiedzi:

146

Rzeczywiste rozwiązanie CSS ze stałym wierszem nagłówka i pierwszą kolumną

Musiałem utworzyć tabelę ze stałym nagłówkiem i ustaloną pierwszą kolumną przy użyciu czystego CSS i żadna z odpowiedzi nie była tym, czego chciałem.

position: stickyNieruchomość obsługuje zarówno przyklejaniu do góry (jak widziałem kiedyś najbardziej) i na bok w nowoczesnych wersjach Chrome, Firefox i Edge. Można to połączyć z divrozszerzeniem, które maoverflow: scroll właściwość, aby utworzyć tabelę ze stałymi nagłówkami, które można umieścić w dowolnym miejscu na stronie:

Umieść swój stół w pojemniku:

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

Użyj overflow: scrollna swoim kontenerze, aby włączyć przewijanie:

div.container {
  overflow: scroll;
}

Jak zauważyła Dagmar w komentarzach, kontener wymaga również a max-widthi a max-height.

Użyj position: stickymieć komórki tabeli trzymać się krawędzi i top, rightlub leftdo wyboru która krawędź trzymać się:

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

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

Jak wspomniała MarredCheese w komentarzach, jeśli pierwsza kolumna zawiera <td>elementy zamiast <th>elementów, możesz użyć tbody td:first-childw swoim CSS zamiasttbody th

Aby nagłówek w pierwszej kolumnie znajdował się po lewej stronie, użyj:

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

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

Matthew Schlachter
źródło
22
Wydaje się, że to najlepsza odpowiedź.
user1190132,
9
@PirateApp Jeśli znasz widthswoją pierwszą kolumnę, możesz użyć position: stickyw komórkach w drugiej kolumnie leftwartości równej wartości z pierwszej kolumny width: jsfiddle.net/wvypo83c/794
Matthew Schlachter
4
Ta odpowiedź dowodzi, że warto przeczytać ją do samego końca!
mlerley
4
To nie działa bez ustawionych w kontenerze max-width i max-height.
Dagmar
9
Ta odpowiedź to latarnia morska prowadząca nas do domu przez niekończące się morze nieprawidłowo funkcjonujących, nadmiernie skomplikowanych, marnujących czas odpowiedzi z zaskakująco pewnych, zaskakująco pozytywnie ocenianych plakatów tutaj w SO i w Internecie. Zwróć uwagę, że jeśli pierwsza kolumna zawiera <td>elementy zamiast <th>elementów, możesz użyć tbody td:first-childw swoim CSS zamiast tbody th.
MarredCheese
33

Obecnie jest to możliwe do osiągnięcia za pomocą CSS tylko z position: stickywłaściwościami.

Oto fragment:

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

Odnośnie kompatybilności. Działa we wszystkich głównych przeglądarkach, ale nie w IE. Jest polyfill, position: stickyale nigdy go nie próbowałem.

Alvaro
źródło
2
To jest świetne, uwielbiam to!
Kapitan Lu
3
jakikolwiek sposób na osiągnięcie tego za pomocą <table> -tags, a nie <div>
Andreas
1
Myślę, że nie zapewni to dobrej wydajności, jeśli tworzysz aplikację i potrzebujesz pętli przez rekordy, aby wydrukować tę tabelę, ponieważ dla każdej kolumny w tabeli musisz zapętlić całą tablicę rekordów. Ten kod HTML działa kolumna po kolumnie.
igasparetto
@igasparetto Możesz tak naprawdę rozmieścić wiersze / kolumny na odwrót, a rozwiązanie nadal będzie działać. Jeśli będę miał jakiś czas później, mogę utworzyć fragment z uporządkowaną siatką wiersz -> kolumna.
Alvaro
2
Odradzałbym wyświetlanie danych tabelarycznych bez użycia <table> i powiązanych tagów. Istnieje kilka problemów z łamaniem zamierzonego użycia HTML w ten sposób, w tym z ułatwieniami dostępu. Zobacz też: w3.org/WAI/tutorials/tables
Ben Morris,
15

To nie jest łatwe zadanie.

Poniższy link prowadzi do działającej wersji demonstracyjnej:

Link zaktualizowany zgodnie z komentarzem lanoxx

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

Pamiętaj tylko, aby dodać te:

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

nie widzę innego sposobu osiągnięcia tego. Zwłaszcza nie używając tylko css.

To dużo do przejścia. Mam nadzieję że to pomoże :)

Phillip-Juan
źródło
Aby zmienić filtr użyj: "bFilter": false
lanoxx
6
Można to osiągnąć tylko za pomocą CSS. Nie jest to łatwe, ale możliwe.
Jimmy T.
z około 10 rozwiązań tylko ten działał. Przy okazji, aby usunąć "Wyświetlam 1 do 57 z 57 wpisów" dodaj "bInfo" : falsedo .dataTable()zaproszenia
hansaplast
datatables == "awesome"
billynoah
odrzucanie tego rozwiązania, ponieważ jest złe. theadjest we własnej tabeli, która nie jest związana ze zmianami tdelementów, więc jeśli komórka tekst jest długi, thszerokość nie będzie odpowiednio dostosować.
vsync
14

Wszystkie te sugestie są świetne i wszystkie, ale albo naprawiają tylko nagłówek lub kolumnę, a nie oba, albo używają javascript. Powód - nie wierzy, że można to zrobić w czystym CSS. Powód:

Gdyby to było możliwe, należałoby zagnieździć kilka przewijalnych elementów DIV, jeden w drugim, każdy ze zwojem w innym kierunku. Następnie musisz podzielić tabelę na trzy części - stały nagłówek, stałą kolumnę i resztę danych.

W porządku. Ale teraz problem - możesz sprawić, że jeden z nich pozostanie na miejscu podczas przewijania, ale drugi jest zagnieżdżony w obszarze przewijania pierwszego i dlatego może być przewijany poza zasięgiem wzroku, więc nie można go naprawić na miejscu ekran. „Aha” mówisz „ale mogę jakoś użyć do tego pozycji bezwzględnej lub stałej” - nie, nie możesz. Gdy tylko to zrobisz, stracisz możliwość przewijania tego kontenera. To sytuacja jajka i kury - nie możesz mieć obu, one się wykluczają.

Uważam, że jedynym rozwiązaniem jest użycie JavaScript. Musisz całkowicie oddzielić te trzy elementy i zsynchronizować ich pozycje za pomocą JavaScript. W innych postach na tej stronie znajdują się dobre przykłady. Ten też jest wart obejrzenia:

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

PretorianNZ
źródło
9

Dokonałem pewnych zmian w jsfiddle. To może być to, co próbujesz zrobić.

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

Zakodowałem tytuły w następujący sposób:

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

Dodałem też kilka stylów.

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

Mam nadzieję, że tego chcesz :)

Phillip-Juan
źródło
1
Potrzebuję nagłówka prawej tabeli, aby przewijać jej zawartość.
panfil
Oto adres URL: jsfiddle.net/C8Dtf/84 . Wystarczy pobawić się stylizacją stołu po prawej stronie, aby wyrównać oba stoły.
Phillip-juan
Nie. Nie całkiem rozumiesz. Potrzebuję, aby nagłówek prawej tabeli był przymocowany do góry, aby był nadal widoczny, gdy tabela przewija się w górę iw dół, ale gdy tabela przewija się w prawo lub w lewo, nagłówek musi przewijać w prawo lub w lewo, ale nadal jest ustalony na górze. Przepraszam za moje słabe umiejętności językowe.
panfil
Chcesz więc, aby nagłówek tabeli po prawej stronie był ustalony podczas przewijania w pionie i przewijał podczas przewijania w poziomie?
Phillip-juan
Oto przykład zachowania, które chcę osiągnąć: datatables.net/release-datatables/extras/FixedColumns/ ...
panfil
9

Przykład wykorzystujący tylko 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
źródło
3
Musiałem naprawić nie tylko heder, ale także pierwszą kolumnę.
panfil
Ten przykład pokazuje podejście z dwiema tabelami w html: jedna tabela renderuje tylko nagłówek; druga tabela renderuje tylko wiersze, ale robi to w ramach pliku div. To właśnie divpozwala na przewijanie wierszy, podczas gdy nagłówek pozostaje w tym samym miejscu. To podejście spełniło moje potrzeby.
David Tansey
Jeśli jest również przewijanie w poziomie, potrzebujesz trochę JS, aby zsynchronizować pozycje przewijania tabel.
Zoltán Tamási
4

Znalazłem doskonałe rozwiązanie tego problemu autorstwa Paula O'Briena i chciałbym udostępnić link: https://codepen.io/paulobrien/pen/LBrMxa

Usunąłem styl stopki:

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
źródło
4

Aby naprawić zarówno nagłówki, jak i kolumny, możesz użyć następującej wtyczki:


Zaktualizowano w lipcu 2019 r

Niedawno pojawiło się również czyste rozwiązanie CSS, które jest oparte na właściwości CSS position: sticky;( tutaj, aby uzyskać więcej informacji), zastosowanej do każdego THelementu (zamiast jego kontenera nadrzędnego)

Luca Detomi
źródło
1
Pierwszy link jest uszkodzony. Drugi wykorzystuje jQuery.
PussInBoots
Zaktualizowana odpowiedź, aby usunąć martwy link
Luca Detomi
2

Niedawno musiałem stworzyć rozwiązanie ze stałą grupą nagłówków i stałą pierwszą kolumną. Podzieliłem tabelę na elementy div i użyłem jquery do przechwycenia przewijania okien.

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
źródło
1

Razem ze współpracownikiem właśnie wydaliśmy nowy projekt GitHub, który dostarcza dyrektywę Angular, której możesz użyć do udekorowania stołu za pomocą stałych nagłówków: https://github.com/objectcomputing/FixedHeader

Opiera się tylko na css i angular, z dyrektywą, która dodaje kilka elementów div. Nie jest wymagane jQuery.

Ta implementacja nie jest tak w pełni funkcjonalna, jak niektóre inne implementacje, ale jeśli potrzebujesz po prostu dodać ustalone tabele, uważamy, że może to być dobra opcja.

user3221325
źródło
1

Po dwóch dniach walki z Internet Explorer 9 + Chrome + Firefox (Windows) i Safari (Mac) znalazłem system, który jest

  • Kompatybilny ze wszystkimi tymi przeglądarkami
  • Bez używania javascript
  • Używa tylko une div i jednej tabeli
  • Naprawiono nagłówek i stopkę (z wyjątkiem IE) z przewijaną treścią. Nagłówek i treść o tej samej szerokości kolumn

Wynik: wprowadź opis obrazu tutaj

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à
źródło
Dobra próba, ale dla mnie nie działa zbyt dobrze. W tym przykładzie ( jsfiddle.net/5ka6e ) nagłówek nie zmienia poprawnie rozmiaru. Ten rodzaj błędu może w końcu skończyć się niezgodnością danych i nagłówka.
darkzangel
1
Zapominasz o dodaniu, div.cost_center table{border-collapse: collapse;}a trzeci podpis musi być czymś, co mieści się w 60 pikselach (w tym przykładzie)
Albert Català
1

Istniejące odpowiedzi będą odpowiadać większości ludzi, ale dla tych, którzy chcą coś dodać cienie pod stałym nagłówkiem i po prawej stronie pierwszej (ustalonej) kolumny, oto działający przykład (czysty CSS):

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

Główną sztuczką, aby to zadziałało, jest ::afterdodanie cieni po prawej stronie każdego z pierwszych tdw każdym z nich 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;
}

Zajęło mi trochę czasu (zbyt długo ...), zanim to wszystko działało, więc pomyślałem, że podzielę się tym dla tych, którzy są w podobnej sytuacji.


źródło
Czy oparłeś to na czyjejś odpowiedzi i dodałeś cień?
PussInBoots
1

trzeba naprawić stopkę nagłówka

neel upadhyay
źródło
0

Coś takiego może ci pomóc ... Prawdopodobnie będzie to wymagało ustawienia szerokości kolumn w wierszu nagłówka.

thead { 
    position: fixed;
}

http://jsfiddle.net/vkhNC/

Aktualizacja:

Nie jestem przekonany, że przykład, który podałeś, jest możliwy tylko z CSS. Chciałbym, żeby ktoś udowodnił mi, że się mylę. Oto, co mam do tej pory . To nie jest gotowy produkt, ale może być dla Ciebie początkiem. Mam nadzieję, że to wskaże ci pomocny kierunek, gdziekolwiek by to nie było.

bradj
źródło
Potrzebuję nie tylko nagłówka, ale też pierwszej kolumny.
panfil
5
Problem polega na tym, że nagłówki tracą szerokość. Wygląda brzydko z innym rozmiarem kolumny nagłówka i rozmiarem kolumny danych.
Akash Kava,
0

Przykład czystego CSS:

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

Wada: Stała struktura / logika nagłówka jest dość zależna od określonych wymiarów, więc abstrakcja prawdopodobnie nie jest realną opcją .

Cody
źródło
Potrzebujesz zarówno stałego nagłówka, jak i naprawionej pierwszej kolumny.
panfil
Ach ... dzięki za wskazanie tego, panfil. Zrobię edycję. Pozdrawiam
Cody,
0

Pozycja: lepki nie działa w przypadku niektórych elementów, takich jak (thead) w Chrome i innych przeglądarkach webkit, takich jak safari.

Ale działa dobrze z (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>

Lub odwiedź mój przykład z kodem :

Joga
źródło
-1

Myślę, że to ci pomoże: https://datatables.net/release-datatables/extensions/FixedHeader/examples/header_footer.html

Krótko mówiąc, jeśli wiesz, jak utworzyć tabelę danych, wystarczy dodać tę linię jQuery na dole:

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

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

bottom: true // służy również do naprawienia dolnego nagłówka.

Jack Sparrow
źródło
-2

Jeśli chcesz używać tylko czystego HTML i CSS, mam rozwiązanie dla twojego problemu:
W tym jsFiddle możesz zobaczyć rozwiązanie nieskryptowe , które zawiera tabelę ze stałym nagłówkiem. Nie powinno być problemu z dostosowaniem znaczników również do ustalonej pierwszej kolumny. Wystarczyłoby utworzyć tabelę pozycjonowaną bezwzględnie dla pierwszej kolumny wewnątrz hWrapper-div i zmienić położenie vWrapper-div.
Zapewnienie dynamicznej zawartości nie powinno stanowić problemu przy użyciu kuszących silników po stronie serwera lub przeglądarki, moje rozwiązanie działa dobrze we wszystkich nowoczesnych przeglądarkach i starszych przeglądarkach począwszy od IE8.

Lukas Hechenberger
źródło
-2

Wystarczy zmienić styl jako

<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
źródło
2
w twoim demo pierwsza kolumna nie jest naprawiona
Bravo