Nagłówek tabeli pozostaje na górze, gdy użytkownik przewinie ją poza widok za pomocą jQuery

145

Próbuję zaprojektować tabelę HTML, w której nagłówek pozostanie na górze strony, gdy I TYLKO wtedy, gdy użytkownik przewinie ją poza zasięg wzroku. Na przykład tabela może znajdować się 500 pikseli w dół od strony, jak to zrobić, aby jeśli użytkownik przewinął nagłówek poza zasięgiem widoku (przeglądarka jakoś wykryje, że nie ma go już w widoku Windows), pozostanie on na górze ? Czy ktoś może mi dać rozwiązanie tego problemu w Javascript?

<table>
  <thead>
    <tr>
      <th>Col1</th>
      <th>Col2</th>
      <th>Col3</th>
    </tr>
  </thead>
  <tbody>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
  </tbody>
</table>

W powyższym przykładzie chcę, <thead>aby przewijał się wraz ze stroną, jeśli zniknie z widoku.

WAŻNE: NIE szukam rozwiązania, w którym <tbody>będzie miał pasek przewijania (przepełnienie: auto).

Sam Dufel
źródło
2
duplikować? stackoverflow.com/questions/1030043
Brad Tofel,
Odpowiedziałem na to inne pytanie, proszę spojrzeć. stackoverflow.com/a/56764334/9388978
Ersel Aktas

Odpowiedzi:

131

Możesz zrobić coś takiego, dotykając modułu scrollobsługi zdarzeń windowi używając innego tableo ustalonej pozycji, aby wyświetlić nagłówek u góry strony.

HTML:

<table id="header-fixed"></table>

CSS:

#header-fixed {
    position: fixed;
    top: 0px; display:none;
    background-color:white;
}

JavaScript:

var tableOffset = $("#table-1").offset().top;
var $header = $("#table-1 > thead").clone();
var $fixedHeader = $("#header-fixed").append($header);

$(window).bind("scroll", function() {
    var offset = $(this).scrollTop();

    if (offset >= tableOffset && $fixedHeader.is(":hidden")) {
        $fixedHeader.show();
    }
    else if (offset < tableOffset) {
        $fixedHeader.hide();
    }
});

Spowoduje to wyświetlenie nagłówka tabeli, gdy użytkownik przewinie w dół na tyle daleko, aby ukryć oryginalną nagłówek tabeli. Ukryje się ponownie, gdy użytkownik ponownie przewinie stronę w górę.

Przykład roboczy: http://jsfiddle.net/andrewwhitaker/fj8wM/

Andrew Whitaker
źródło
60
Myślałem o tym, ale co, jeśli szerokość kolumn nagłówka zmieni się w zależności od zawartości? O ile szerokości kolumn nie są ustalone, wiersz nagłówka może nie być wyrównany z wierszami zawartości. Tylko myśl.
Yzmir Ramirez
16
ten przykład nie działa, jeśli nazwy nagłówków kolumn są krótsze niż wartości danych kolumn. Spróbuj zmienić to skrzypce, aby zamiast informacji miały wartości takie jak infoooooooo. Myślę o jakiejś zakodowanej na stałe szerokości, która jest ustawiona podczas klonowania tabeli.
whiterook6
6
Ma to poważne ograniczenia, z których najmniejszym jest użycie tabeli w innym kontenerze niż window. mkoryak.github.io/floatThead ma bardziej ogólne rozwiązanie.
Fuj
13
To może pomóc każdemu, kto potrzebuje dynamicznych szerokości, to właśnie zrobiłem, to widelec @AndrewWhitaker: jsfiddle.net/noahkoch/wLcjh/1
Noah Koch
1
Stały nagłówek @NoahKoch używający twojego rozwiązania może nadal nie być tak szeroki jak oryginalna głowa, gdy oryginalne komórki mają wypełnienie. Udoskonaliłem Twoje rozwiązanie, dodając wypełnienie do zduplikowanych komórek. Widelec JSFiddle
fandasson
46

Cóż, próbowałem uzyskać ten sam efekt bez uciekania się do kolumn o stałym rozmiarze lub posiadania stałej wysokości dla całego stołu.

Rozwiązanie, które wymyśliłem, to hack. Polega na powieleniu całej tabeli, a następnie ukryciu wszystkiego oprócz nagłówka i nadaniu mu stałej pozycji.

HTML

<div id="table-container">
<table id="maintable">
    <thead>
        <tr>
            <th>Col1</th>
            <th>Col2</th>
            <th>Col3</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>info</td>
            <td>info</td>
            <td>info</td>
        </tr>
        <tr>
            <td>info</td>
            <td>info</td>
            <td>info</td>
        </tr>
        <tr>
            <td>info</td>
            <td>some really long line here instead</td>
            <td>info</td>
        </tr>
        <tr>
            <td>info</td>
            <td>info</td>
            <td>info</td>
        </tr>
                <tr>
            <td>info</td>
            <td>info</td>
            <td>info</td>
        </tr>
                <tr>
            <td>info</td>
            <td>info</td>
            <td>info</td>
        </tr>
        <tr>
            <td>info</td>
            <td>info</td>
            <td>info</td>
        </tr>
    </tbody>
</table>
<div id="bottom_anchor"></div>
</div>

CSS

body { height: 1000px; }
thead{
    background-color:white;
}

javascript

function moveScroll(){
    var scroll = $(window).scrollTop();
    var anchor_top = $("#maintable").offset().top;
    var anchor_bottom = $("#bottom_anchor").offset().top;
    if (scroll>anchor_top && scroll<anchor_bottom) {
    clone_table = $("#clone");
    if(clone_table.length == 0){
        clone_table = $("#maintable").clone();
        clone_table.attr('id', 'clone');
        clone_table.css({position:'fixed',
                 'pointer-events': 'none',
                 top:0});
        clone_table.width($("#maintable").width());
        $("#table-container").append(clone_table);
        $("#clone").css({visibility:'hidden'});
        $("#clone thead").css({'visibility':'visible','pointer-events':'auto'});
    }
    } else {
    $("#clone").remove();
    }
}
$(window).scroll(moveScroll); 

Zobacz tutaj: http://jsfiddle.net/QHQGF/7/

Edycja: zaktualizowano kod tak, aby thead mógł odbierać zdarzenia wskaźnika (aby przyciski i linki w nagłówku nadal działały). To rozwiązuje problem zgłoszony przez luhfluha i Joe M.

Nowy jsfiddle tutaj: http://jsfiddle.net/cjKEx/

entropia
źródło
3
Próbowałem tego najpierw, problem polega na tym, że rozmiar elementów w nagłówku zależy od zawartości tabeli. Jeśli masz wiersz z dużą zawartością, wzrośnie cała kolumna, łącznie z nagłówkiem. Jeśli sklonujesz tylko thead, stracisz te informacje i nie uzyskasz pożądanego efektu. Zobacz komentarz Yzmira Ramireza na temat zaakceptowanej odpowiedzi. To jedyny sposób, w jaki stwierdziłem, że działa bez kolumn o stałej szerokości. Wiem, że to nie jest czyste, i tak powiedziałem, że to hack.
entropia
1
Och, rozumiem. Ta metoda jest świetna, ponieważ działa z płynnymi kolumnami, wyszukałem trochę w Google i nie mogłem znaleźć innej z taką funkcjonalnością. W każdym razie, jeśli jakoś to zrobię, wspomnę o tym tutaj
M2_
1
@luhfluh, tak, problem był spowodowany zdarzeniami wskaźnika: brak w sklonowanej tabeli. Jest to używane, aby kliknięcia przechodziły przez klon i do oryginalnej tabeli. Przywrócenie go w nagłówku sklonowanej tabeli, tak aby nagłówek (i tylko nagłówek) był klikalny, rozwiązuje problem. Zaktualizowałem swój post, aby to odzwierciedlić :)
entropia
4
problem z dodaniem obramowania na <thead> <th>
Jam Ville,
1
@JamVille Ponieważ sklonowana tabela ma visibility: hidden. Możesz tylko ukryć, #clone tbodya potem ustawić ramkę ... Skrzypce
Lajdák Marek
46

Czysty CSS (bez obsługi IE11):

table th {
    position: -webkit-sticky; // this is for all Safari (Desktop & iOS), not for Chrome
    position: sticky;
    top: 0;
    z-index: 5;
    background: #fff;
}
Ihor Zenich
źródło
1
Nawet nie widzę, żeby to działało w Chrome. Narzędzia kontrolne pokazują -webkit-stickynieprawidłową wartość dla position.
karmenizm
@carmenism -webkit-stickyjest przeznaczone dla Safari (komputery stacjonarne i iOS), a nie dla Chrome. position: stickydziała w Chrome od wersji 56. Powinieneś ustawić OBIE reguły: -webkit-stickyi stickydokładnie w tej samej kolejności, jak w moim przykładzie kodu. Safari pobiera webkit-stickyi wszystkie inne przeglądarki nadpisują to sticky.
Ihor Zenich
2
Nie mogłem zmusić tego do pracy. Z szybkiego google wygląda na to, że position: stickynie będzie działać z elementami tabeli.
rjh
3
ubieganie się o pracę pracowało dla mnie: table thead tr {...}
nurp
1
Musisz go zastosować do tego, ponieważ nie zadziała na thead ani tr
helado.
26

Napisałem wtyczkę, która to robi. Pracuję nad tym od około roku i myślę, że całkiem dobrze radzi sobie ze wszystkimi narożnymi sprawami:

  • przewijanie w kontenerze z przepełnieniem
  • przewijanie w oknie
  • dbanie o to, co się stanie, gdy zmienisz rozmiar okna
  • utrzymywanie wydarzeń związanych z nagłówkiem
  • co najważniejsze, nie zmusza cię to do zmiany css tabeli, aby działała

Oto kilka demonstracji / dokumentów:
http://mkoryak.github.io/floatThead/

mkoryak
źródło
wielki wysiłek, ale nie działa z IE 10 i ma pewne dziwactwa przy zmianie rozmiaru okien na firefox23 / ubuntu.
Janning
2
FYI: naprawiłem problemy z IE9 i 10 w najnowszej wersji.
mkoryak
2
Czy możesz stworzyć wersję, która nie wymaga jQuery?
Curtis W,
2
prawdopodobnie dlatego, że nie używa jquery ... i nie - nie stworzę wersji, która nie używa jquery.
mkoryak
1
Używam prostej wtyczki jQery tableorter i zgodnie z twoim FAQ, twoja wtyczka nie lubi większości reguł CSS, takich jak #sortable td {..} i tak dalej. Próbowałem trochę poprawić, ale nie mogłem zmusić go do pracy.
masche
25

Udało mi się rozwiązać problem ze zmianą szerokości kolumn. Zacząłem od powyższego rozwiązania Andrew (wielkie dzięki!), A następnie dodałem jedną małą pętlę, aby ustawić szerokości sklonowanych td:

$("#header-fixed td").each(function(index){
    var index2 = index;
    $(this).width(function(index2){
        return $("#table-1 td").eq(index).width();
    });
});

To rozwiązuje problem bez konieczności klonowania całego stołu i ukrywania ciała. Jestem zupełnie nowy w JavaScript i jQuery (i przepełnieniu stosu), więc wszelkie komentarze są mile widziane.

rockusbacchus
źródło
4
Działało dobrze, ale potrzebowałem dodać następujący wiersz $ ("# header-fixed"). Width ($ ("# table-1"). Width ()); aby kolumny były prawidłowo wyrównane.
Ilya Fedotov
17

Jest to zdecydowanie najlepsze rozwiązanie, jakie znalazłem w przypadku stałego nagłówka tabeli.

AKTUALIZACJA 5/11: Naprawiono błąd przewijania w poziomie, wskazany przez Kerry Johnson

Codepen: https://codepen.io/josephting/pen/demELL

;(function($) {
   $.fn.fixMe = function() {
      return this.each(function() {
         var $this = $(this),
            $t_fixed;
         function init() {
            $this.wrap('<div class="container" />');
            $t_fixed = $this.clone();
            $t_fixed.find("tbody").remove().end().addClass("fixed").insertBefore($this);
            resizeFixed();
         }
         function resizeFixed() {
           $t_fixed.width($this.outerWidth());
            $t_fixed.find("th").each(function(index) {
               $(this).css("width",$this.find("th").eq(index).outerWidth()+"px");
            });
         }
         function scrollFixed() {
            var offsetY = $(this).scrollTop(),
            offsetX = $(this).scrollLeft(),
            tableOffsetTop = $this.offset().top,
            tableOffsetBottom = tableOffsetTop + $this.height() - $this.find("thead").height(),
            tableOffsetLeft = $this.offset().left;
            if(offsetY < tableOffsetTop || offsetY > tableOffsetBottom)
               $t_fixed.hide();
            else if(offsetY >= tableOffsetTop && offsetY <= tableOffsetBottom && $t_fixed.is(":hidden"))
               $t_fixed.show();
            $t_fixed.css("left", tableOffsetLeft - offsetX + "px");
         }
         $(window).resize(resizeFixed);
         $(window).scroll(scrollFixed);
         init();
      });
   };
})(jQuery);

$(document).ready(function(){
   $("table").fixMe();
   $(".up").click(function() {
      $('html, body').animate({
      scrollTop: 0
   }, 2000);
 });
});
body{
  font:1.2em normal Arial,sans-serif;
  color:#34495E;
}

h1{
  text-align:center;
  text-transform:uppercase;
  letter-spacing:-2px;
  font-size:2.5em;
  margin:20px 0;
}

.container{
  width:90%;
  margin:auto;
}

table{
  border-collapse:collapse;
  width:100%;
}

.blue{
  border:2px solid #1ABC9C;
}

.blue thead{
  background:#1ABC9C;
}

.purple{
  border:2px solid #9B59B6;
}

.purple thead{
  background:#9B59B6;
}

thead{
  color:white;
}

th,td{
  text-align:center;
  padding:5px 0;
}

tbody tr:nth-child(even){
  background:#ECF0F1;
}

tbody tr:hover{
background:#BDC3C7;
  color:#FFFFFF;
}

.fixed{
  top:0;
  position:fixed;
  width:auto;
  display:none;
  border:none;
}

.scrollMore{
  margin-top:600px;
}

.up{
  cursor:pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>&darr; SCROLL &darr;</h1>
<table class="blue">
  <thead>
    <tr>
      <th>Colonne 1</th>
      <th>Colonne 2</th>
      <th>Colonne 3</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Non</td>
      <td>MaisMaisMaisMaisMaisMaisMaisMaisMaisMaisMaisMaisMaisMaisMaisMaisMaisMaisMaisMais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
       <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
  </tbody>
</table>

<h1 class="scrollMore">&darr; SCROLL MORE &darr;</h1>
<table class="purple">
  <thead>
    <tr>
      <th>Colonne 1</th>
      <th>Colonne 2</th>
      <th>Colonne 3</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
       <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
       <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
  </tbody>
</table>
<h1 class="up scrollMore">&uarr; UP &uarr;</h1>

Josephting
źródło
Naprawiłem ten skrypt, aby mógł obsługiwać <th> elementy, które mają obramowanie i dopełnienie (w przeciwnym razie ustawia stałą szerokość <th> nagłówka za zbyt szeroką). Po prostu zmień outerWidthna widthw definicji funkcji resizeFixed ().
alanng
Konieczne może być również dodanie właściwości CSS z-indexdo pewnej liczby dodatniej w .fixedklasie, aby obiekty renderowane po załadowaniu strony w tabeli nie unosiły się nad stałym nagłówkiem podczas przewijania.
alanng
Proste i użyteczne.
RitchieD
jak dynamicznie obsługiwać najwyższą pozycję. Powiedzmy, że muszę przewinąć w górę pod stałą zawartością nagłówka mojej strony głównej. .fixed {top: 0;} .
VijayVishnu
2
@KerryJohnson Dzięki za notatkę. Dokonałem pewnych zmian, więc obsługuje przewijanie w poziomie i dynamiczne szerokości kolumn.
josephting
7

Najlepszym rozwiązaniem jest użycie tej wtyczki jquery:

https://github.com/jmosbech/StickyTableHeaders

Ta wtyczka działała świetnie i wypróbowaliśmy wiele innych rozwiązań. Przetestowaliśmy to w IE, Chrome i Firefox

Janning
źródło
Czy znasz jakieś rozwiązanie, które zachowuje również funkcjonalność kontrolek związanych z danymi w nagłówku?
Csaba Toth
U mnie nie działa: nagłówki są poza tabelą i trzymają się górnej części przeglądarki (okna), nawet z opcją „scrollableArea”. Widziałem, że wspomniano o tym wcześniej bez dodatkowych komentarzy. Może potrzebuje CSS, którego używa i nie jest dostępny, aby działał.
Exel Gamboa,
6

Jest tu już wiele naprawdę dobrych rozwiązań. Ale jedno z najprostszych rozwiązań CSS, których używam w takich sytuacjach, jest następujące:

table {
  /* Not required only for visualizing */
  border-collapse: collapse;
  width: 100%;
}

table thead tr th {
  /* Important */
  background-color: red;
  position: sticky;
  z-index: 100;
  top: 0;
}

td {
  /* Not required only for visualizing */
  padding: 1em;
}
<table>
  <thead>
    <tr>
      <th>Col1</th>
      <th>Col2</th>
      <th>Col3</th>
    </tr>
  </thead>
  <tbody>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
  </tbody>
</table>

Ponieważ nie jest wymagany JavaScript, znacznie upraszcza to sytuację. Zasadniczo musisz skupić się na drugiej regule CSS, która zawiera warunki zapewniające, że nagłówek tabeli pozostaje na górze bez względu na przestrzeń przewijania.

Aby szczegółowo omówić każdą z zasad. positionma na celu wskazanie przeglądarce, że obiekt głowy, jego wiersz i komórki muszą przyklejać się do góry. Koniecznie musi temu towarzyszyć top, który wskazuje przeglądarce, że głowa będzie przyklejona do góry strony lub widocznego obszaru. Dodatkowo możesz dodać, z-indexaby zawartość głowy zawsze pozostała na górze.

Kolor tła służy jedynie do zilustrowania sprawy. Aby uzyskać ten efekt, nie musisz używać żadnego dodatkowego JavaScript. Jest to obsługiwane w większości głównych przeglądarek po 2016 roku.

Srivats Shankar
źródło
1
imo najprostsza i najczystsza odpowiedź, zawsze istnieje prosty sposób rozwiązania jednego problemu, tak jest. Mimo że używam ng-repeat z angularjs, to działa jak urok.
David Castro
3

Cóż, po przejrzeniu wszystkich dostępnych rozwiązań napisałem wtyczkę, która może zamrozić dowolny wiersz (nie tylko ten) na górze strony lub kontenera. To bardzo proste i bardzo szybkie. Zapraszam do korzystania z niego. http://maslianok.github.io/stickyRows/

Vitalii Maslianok
źródło
3

możesz użyć tego podejścia, czysty HTML i CSS nie potrzeba JS :)

.table-fixed-header {
  display: flex;
  justify-content: space-between;
  margin-right: 18px
}

.table-fixed {
  display: flex;
  justify-content: space-between;
  height: 150px;
  overflow: scroll;
}

.column {
  flex-basis: 24%;
  border-radius: 5px;
  padding: 5px;
  text-align: center;
}
.column .title {
  border-bottom: 2px grey solid;
  border-top: 2px grey solid;
  text-align: center;
  display: block;
  font-weight: bold;
}

.cell {
  padding: 5px;
  border-right: 1px solid;
  border-left: 1px solid;
}

.cell:nth-of-type(even) {
  background-color: lightgrey;
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Fixed header Bin</title>
</head>
<body>
<div class="table-fixed-header">
    
    <div class="column">
      <span class="title">col 1</span>
    </div>
    <div class="column">
      <span class="title">col 2</span>
    </div>
    <div class="column">
      <span class="title">col 3</span>
    </div>
    <div class="column">
      <span class="title">col 4</span>
    </div>
    
  </div>
  
  <div class="table-fixed">
    
    <div class="column">
      <div class="cell">alpha</div>
      <div class="cell">beta</div>
      <div class="cell">ceta</div>
    </div>
    
    <div class="column">
      <div class="cell">alpha</div>
      <div class="cell">beta</div>
      <div class="cell">ceta</div>
      <div class="cell">alpha</div>
      <div class="cell">beta</div>
      <div class="cell">ceta</div>
      <div class="cell">alpha</div>
      <div class="cell">beta</div>
      <div class="cell">ceta</div>
    </div>
    
    <div class="column">
      <div class="cell">alpha</div>
      <div class="cell">beta</div>
      <div class="cell">ceta</div>
      <div class="cell">beta</div>
      <div class="cell">beta</div>
      <div class="cell">beta</div>
      
    </div>
    
    <div class="column">
      <div class="cell">alpha</div>
      <div class="cell">beta</div>
      <div class="cell">ceta</div>
    </div>
    
  </div>
</body>
</html>

xelilof
źródło
3

Znalazłem proste rozwiązanie bez użycia JQuery i używania tylko CSS .

Musisz umieścić stałą zawartość wewnątrz znaczników „th” i dodać CSS

table th {
    position:sticky;
    top:0;
    z-index:1;
    border-top:0;
    background: #ededed;
}
   

Wystarczy pozycja, indeks z i właściwości górne. Ale możesz zastosować resztę, aby uzyskać lepszy widok.

Abhi Das
źródło
2

Ja również doświadczyłem tych samych problemów z formatowaniem obramowania, które nie było wyświetlane za pomocą kodu entrofii, ale kilka drobnych poprawek, a teraz tabela jest rozwijana i wyświetla wszystkie reguły stylizacji CSS, które możesz dodać.

do css dodać:

#maintable{width: 100%}    

to tutaj jest nowy javascript:

    function moveScroll(){
    var scroll = $(window).scrollTop();
    var anchor_top = $("#maintable").offset().top;
    var anchor_bottom = $("#bottom_anchor").offset().top;
    if (scroll > anchor_top && scroll < anchor_bottom) {
        clone_table = $("#clone");
        if(clone_table.length === 0) {          
            clone_table = $("#maintable").clone();
            clone_table.attr({id: "clone"})
            .css({
                position: "fixed",
                "pointer-events": "none",
                 top:0
            })
            .width($("#maintable").width());

            $("#table-container").append(clone_table);
            // dont hide the whole table or you lose border style & 
            // actively match the inline width to the #maintable width if the 
            // container holding the table (window, iframe, div) changes width          
            $("#clone").width($("#maintable").width());
            // only the clone thead remains visible
            $("#clone thead").css({
                visibility:"visible"
            });
            // clone tbody is hidden
            $("#clone tbody").css({
                visibility:"hidden"
            });
            // add support for a tfoot element
            // and hide its cloned version too
            var footEl = $("#clone tfoot");
            if(footEl.length){
                footEl.css({
                    visibility:"hidden"
                });
            }
        }
    } 
    else {
        $("#clone").remove();
    }
}
$(window).scroll(moveScroll);
seeit360
źródło
Działa to lepiej niż rozwiązanie entropii, jeśli chodzi o formatowanie obramowań w nagłówku. Jednak w obecnej przeglądarce Firefox (ale nie Chrome) tworzy widoczne artefakty obramowania komórek poniżej tabeli po rozpoczęciu przewijania.
alanng
2

Oto rozwiązanie, które opiera się na zaakceptowanej odpowiedzi. Koryguje o: szerokości kolumn, dopasowany styl tabeli i kiedy tabela jest przewijana w kontenerze div.

Stosowanie

Upewnij się, że Twoja tabela ma <thead>tag, ponieważ poprawiona zostanie tylko zawartość reklamy.

$("#header-fixed").fixHeader();

JavaSript

//Custom JQuery Plugin
(function ($) {
    $.fn.fixHeader = function () {
        return this.each(function () {
            var $table = $(this);
            var $sp = $table.scrollParent();
            var tableOffset = $table.position().top;
            var $tableFixed = $("<table />")
                .prop('class', $table.prop('class'))
                .css({ position: "fixed", "table-layout": "fixed", display: "none", "margin-top": "0px" });
            $table.before($tableFixed);
            $tableFixed.append($table.find("thead").clone());

            $sp.bind("scroll", function () {
                var offset = $(this).scrollTop();

                if (offset > tableOffset && $tableFixed.is(":hidden")) {
                    $tableFixed.show();
                    var p = $table.position();
                    var offset = $sp.offset();

                    //Set the left and width to match the source table and the top to match the scroll parent
                    $tableFixed.css({ left: p.left + "px", top: (offset ? offset.top : 0) + "px", }).width($table.width());

                    //Set the width of each column to match the source table
                    $.each($table.find('th, td'), function (i, th) {
                        $($tableFixed.find('th, td')[i]).width($(th).width());
                    });

                }
                else if (offset <= tableOffset && !$tableFixed.is(":hidden")) {
                    $tableFixed.hide();
                }
            });
        });
    };
})(jQuery);
Ben Gripka
źródło
1
To działało dobrze dla mnie. Problem dotyczy tylko tabel, które wymagają przewijania w poziomie. Zrobiłem aktualizację w JSFiddle tutaj jsfiddle.net/4mgneob1/1 Odejmuję , $sp.scrollLeft()co powoduje przewijanie kwoty od lewej, więc podczas przewijania w dół ustalona tabela jest ustawiona prawidłowo. Dodano również sprawdzanie podczas przewijania w poziomie, czy widoczna jest stała tabela, aby dostosować lewą pozycję. Innym problemem, którego nie mogłem rozwiązać, jest to, że gdy tabela znajduje się nad widocznym obszarem, stała tabela powinna się ukrywać, dopóki użytkownik nie przewinie w górę.
Henesnarfel
1
PierwszeUncaught TypeError: $table.scrollParent is not a function
karlingen
1

Pomoże ci to mieć stały nagłówek, który można również przewijać w poziomie z danymi.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Shubh</title>



<script type="text/javascript">
    var lastSeen = [ 0, 0 ];
    function checkScroll(div1, div2) {
        if (!div1 || !div2)
            return;
        var control = null;
        if (div1.scrollLeft != lastSeen[0])
            control = div1;
        else if (div2.scrollLeft != lastSeen[1])
            control = div2;
        if (control == null)
            return;
        else
            div1.scrollLeft = div2.scrollLeft = control.scrollLeft;
        lastSeen[0] = div1.scrollLeft;
        lastSeen[1] = div2.scrollLeft;
    }

    window
            .setInterval(
                    "checkScroll(document.getElementById('innertablediv'), document.getElementById('headertable'))",
                    1);
</script>

<style type="text/css">
#full {
    width: 400px;
    height: 300px;
}

#innertablediv {
    height: 200px;
    overflow: auto;
}

#headertable {
    overflow: hidden;
}
</style>
</head>
<body>

    <div id="full">




        <div id="headertable">
            <table border="1" bgcolor="grey" width="150px" id="headertable">
                <tr>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>

                    <td>&nbsp;&nbsp;&nbsp;</td>
                </tr>

            </table>
        </div>




        <div id="innertablediv">

            <table border="1" id="innertableid">
                <tr>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                </tr>
                <tr>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                </tr>
                <tr>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                </tr>
                <tr>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                </tr>
                <tr>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                </tr>
                <tr>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                </tr>
                <tr>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                </tr>
                <tr>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                </tr>
                <tr>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                    <td>shubh, ansh</td>
                </tr>

            </table>
        </div>
    </div>
</body>
</html>
user2669926
źródło
Pomoże ci to mieć stały nagłówek, który można również przewijać w poziomie z danymi.
user2669926
1
function fix_table_header_position(){
 var width_list = [];
 $("th").each(function(){
    width_list.push($(this).width());
 });
 $("tr:first").css("position", "absolute");
 $("tr:first").css("z-index", "1000");
 $("th, td").each(function(index){
    $(this).width(width_list[index]);
 });

 $("tr:first").after("<tr height=" + $("tr:first").height() + "></tr>");}

To jest moje rozwiązanie

Tylko my
źródło
1

Trochę za późno na imprezę, ale oto implementacja, która działa z wieloma tabelami na tej samej stronie i jest darmowa (przy użyciu requestAnimationFrame). Nie ma też potrzeby podawania szerokości kolumn. Przewijanie w poziomie również działa.

Nagłówki są zdefiniowane w a, divwięc w razie potrzeby możesz dodać tam dowolne znaczniki (takie jak przyciski). To jest cały kod HTML, który jest potrzebny:

<div class="tbl-resp">
  <table id="tbl1" class="tbl-resp__tbl">
     <thead>
      <tr>
        <th>col 1</th>
        <th>col 2</th>
        <th>col 3</th>
      </tr>
    </thead> 
  </table>
</div>

https://jsfiddle.net/lloydleo/bk5pt5gs/

Lew
źródło
1

W tym rozwiązaniu ustalony nagłówek tworzony jest dynamicznie, zawartość i styl klonuje się z THEAD

wystarczy na przykład dwie linie:

var $myfixedHeader = $("#Ttodo").FixedHeader(); //create fixed header $(window).scroll($myfixedHeader.moveScroll); //bind function to scroll event

Mój plugin jquery FixedHeader i getStyleObject podane poniżej możesz umieścić w pliku .js

// JAVASCRIPT



/*
 * getStyleObject Plugin for jQuery JavaScript Library
 * From: http://upshots.org/?p=112
 
Basic usage:
$.fn.copyCSS = function(source){
  var styles = $(source).getStyleObject();
  this.css(styles);
}
*/

(function($){
    $.fn.getStyleObject = function(){
        var dom = this.get(0);
        var style;
        var returns = {};
        if(window.getComputedStyle){
            var camelize = function(a,b){
                return b.toUpperCase();
            };
            style = window.getComputedStyle(dom, null);
            for(var i = 0, l = style.length; i < l; i++){
                var prop = style[i];
                var camel = prop.replace(/\-([a-z])/g, camelize);
                var val = style.getPropertyValue(prop);
                returns[camel] = val;
            };
            return returns;
        };
        if(style = dom.currentStyle){
            for(var prop in style){
                returns[prop] = style[prop];
            };
            return returns;
        };
        return this.css();
    }
})(jQuery);



   
//Floating Header of long table  PiotrC
(function ( $ ) {
    var tableTop,tableBottom,ClnH;
    $.fn.FixedHeader = function(){
        tableTop=this.offset().top,
        tableBottom=this.outerHeight()+tableTop;
        //Add Fixed header
        this.after('<table id="fixH"></table>');
        //Clone Header
        ClnH=$("#fixH").html(this.find("thead").clone());
        //set style
        ClnH.css({'position':'fixed', 'top':'0', 'zIndex':'60', 'display':'none',
        'border-collapse': this.css('border-collapse'),
		'border-spacing': this.css('border-spacing'),
        'margin-left': this.css('margin-left'),
        'width': this.css('width')            
        });
        //rewrite style cell of header
        $.each(this.find("thead>tr>th"), function(ind,val){
            $(ClnH.find('tr>th')[ind]).css($(val).getStyleObject());
        });
    return ClnH;}
    
    $.fn.moveScroll=function(){
        var offset = $(window).scrollTop();
        if (offset > tableTop && offset<tableBottom){
            if(ClnH.is(":hidden"))ClnH.show();
            $("#fixH").css('margin-left',"-"+$(window).scrollLeft()+"px");
        }
        else if (offset < tableTop || offset>tableBottom){
            if(!ClnH.is(':hidden'))ClnH.hide();
        }
    };
})( jQuery );





var $myfixedHeader = $("#repTb").FixedHeader();
$(window).scroll($myfixedHeader.moveScroll);
/* CSS - important only NOT transparent background */

#repTB{border-collapse: separate;border-spacing: 0;}

#repTb thead,#fixH thead{background: #e0e0e0 linear-gradient(#d8d8d8 0%, #e0e0e0 25%, #e0e0e0 75%, #d8d8d8 100%) repeat scroll 0 0;border:1px solid #CCCCCC;}

#repTb td{border:1px solid black}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>


<h3>example</h3> 
<table id="repTb">
<thead>
<tr><th>Col1</th><th>Column2</th><th>Description</th></tr>
</thead>
<tr><td>info</td><td>info</td><td>info</td></tr>
<tr><td>info</td><td>info</td><td>info</td></tr>
<tr><td>info</td><td>info</td><td>info</td></tr>
<tr><td>info</td><td>info</td><td>info</td></tr>
<tr><td>info</td><td>info</td><td>info</td></tr>
<tr><td>info</td><td>info</td><td>info</td></tr>
<tr><td>info</td><td>info</td><td>info</td></tr>
<tr><td>info</td><td>info</td><td>info</td></tr>
<tr><td>info</td><td>info</td><td>info</td></tr>
<tr><td>info</td><td>info</td><td>info</td></tr>
<tr><td>info</td><td>info</td><td>info</td></tr>
</table>

Piotr C.
źródło
1

Utwórz dodatkową tabelę z takim samym nagłówkiem jak główna tabela. Po prostu umieść thead w nowej tabeli z jednym wierszem i wszystkimi nagłówkami. Ustaw położenie bezwzględne i białe tło. Dla głównej tabeli umieść go w div i użyj przewijania wysokości i przepełnienia. W ten sposób nasz nowy stół pokona nagłówek głównego stołu i tam pozostanie. Otocz wszystko w div. Poniżej znajduje się przybliżony kod, aby to zrobić.

      <div class="col-sm-8">

        <table id="header-fixed" class="table table-bordered table-hover" style="width: 351px;position: absolute;background: white;">
        <thead>
        <tr>
            <th>Col1</th>
            <th>Col2</th>
            <th>Col3</th>
        </tr>
    </thead>
      </table>


    <div style="height: 300px;overflow-y: scroll;">
          <table id="tableMain" class="table table-bordered table-hover" style="table-layout:fixed;overflow-wrap: break-word;cursor:pointer">
<thead>
    <tr>
      <th>Col1</th>
      <th>Col2</th>
      <th>Col3</th>
    </tr>
  </thead>
  <tbody>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
  </tbody>

                                    </table>
              </div>
        </div>
Novice_JS
źródło
1

div.wrapper {
    padding:20px;
}
table.scroll thead {
    width: 100%;
    background: #FC6822;
}
table.scroll thead tr:after {
    content: '';
    overflow-y: scroll;
    visibility: hidden;
}
table.scroll thead th {
    flex: 1 auto;
    display: block;
    color: #fff;
}
table.scroll tbody {
    display: block;
    width: 100%;
    overflow-y: auto;
    height: auto;
    max-height: 200px;
}
table.scroll thead tr,
table.scroll tbody tr {
    display: flex;
}
table.scroll tbody tr td {
    flex: 1 auto;
    word-wrap: break;
}
table.scroll thead tr th,
table.scroll tbody tr td {
    width: 25%;
    padding: 5px;
    text-align-left;
    border-bottom: 1px solid rgba(0,0,0,0.3);
}
<div class="wrapper">
    <table border="0" cellpadding="0" cellspacing="0" class="scroll">
        <thead>
            <tr>
                <th>Name</th>
                <th>Vorname</th>
                <th>Beruf</th>
                <th>Alter</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>Müller</td>
                <td>Marie</td>
                <td>Künstlerin</td>
                <td>26</td>
            </tr>
            <tr>
                <td>Meier</td>
                <td>Stefan</td>
                <td>Chemiker</td>
                <td>52</td>
            </tr>
            <tr>
                <td>Schmidt</td>
                <td>Sabrine</td>
                <td>Studentin</td>
                <td>38</td>
            </tr>
            <tr>
                <td>Mustermann</td>
                <td>Max</td>
                <td>Lehrer</td>
                <td>41</td>
            </tr>
            <tr>
                <td>Müller</td>
                <td>Marie</td>
                <td>Künstlerin</td>
                <td>26</td>
            </tr>
            <tr>
                <td>Meier</td>
                <td>Stefan</td>
                <td>Chemiker</td>
                <td>52</td>
            </tr>
            <tr>
                <td>Schmidt</td>
                <td>Sabrine</td>
                <td>Studentin</td>
                <td>38</td>
            </tr>
            <tr>
                <td>Mustermann</td>
                <td>Max</td>
                <td>Lehrer</td>
                <td>41</td>
            </tr>
            <tr>
                <td>Müller</td>
                <td>Marie</td>
                <td>Künstlerin</td>
                <td>26</td>
            </tr>
            <tr>
                <td>Meier</td>
                <td>Stefan</td>
                <td>Chemiker</td>
                <td>52</td>
            </tr>
            <tr>
                <td>Schmidt</td>
                <td>Sabrine</td>
                <td>Studentin</td>
                <td>38</td>
            </tr>
            <tr>
                <td>Mustermann</td>
                <td>Max</td>
                <td>Lehrer</td>
                <td>41</td>
            </tr>
        </tbody>
    </table>
</div>

Demo: demo css z poprawionym nagłówkiem tabeli

revilodesign.de
źródło
1

Rozwiąż swój problem z tym

tbody {
  display: table-caption;
  height: 200px;
  caption-side: bottom;
  overflow: auto;
}
J Benjamín Samayoa
źródło
0

Można to osiągnąć za pomocą transformacji właściwości stylu. Wszystko, co musisz zrobić, to zawinąć tabelę w jakiś div o stałej wysokości i przepełnieniu ustawionym na auto, na przykład:

.tableWrapper {
  overflow: auto;
  height: calc( 100% - 10rem );
}

Następnie możesz dołączyć do niego moduł obsługi przewijania onscroll, tutaj masz metodę, która znajduje każdą tabelę opakowaną <div class="tableWrapper"></div>:

  fixTables () {
    document.querySelectorAll('.tableWrapper').forEach((tableWrapper) => {
      tableWrapper.addEventListener('scroll', () => {
        var translate = 'translate(0,' + tableWrapper.scrollTop + 'px)'
        tableWrapper.querySelector('thead').style.transform = translate
      })
    })
  }

A oto działający przykład tego w akcji (użyłem bootstrapa, aby był ładniejszy): skrzypce

Dla tych, którzy chcą również obsługiwać IE i Edge, oto fragment kodu:

  fixTables () {
    const tableWrappers = document.querySelectorAll('.tableWrapper')
    for (let i = 0, len = tableWrappers.length; i < len; i++) {
      tableWrappers[i].addEventListener('scroll', () => {
        const translate = 'translate(0,' + tableWrappers[i].scrollTop + 'px)'
        const headers = tableWrappers[i].querySelectorAll('thead th')
        for (let i = 0, len = headers.length; i < len; i++) {
          headers[i].style.transform = translate
        }
      })
    }
  }

W IE i Edge przewijanie jest trochę opóźnione ... ale działa

Oto odpowiedź, która pomaga mi się tego dowiedzieć: odpowiedź

Daniel Budzyński
źródło
0

Wypróbowałem większość tych rozwiązań i ostatecznie znalazłem (IMO) najlepsze, nowoczesne rozwiązanie:

Siatki CSS


Dzięki siatkom CSS możesz zdefiniować `` siatkę '', a na koniec możesz stworzyć ładne, wolne od JavaScript rozwiązanie dla różnych przeglądarek dla tabeli ze stałym nagłówkiem i przewijaną treścią. Wysokość nagłówka może być nawet dynamiczna.

CSS : Wyświetl jako siatkę i ustaw liczbę template-rows:

.grid {
    display: grid;
    grid-template-rows: 50px auto; // For fixed height header
    grid-template-rows: auto auto; // For dynamic height header
}

HTML : Utwórz kontener siatki i liczbę zdefiniowanych rows:

<div class="grid">
    <div></div>
    <div></div>
</div>

Oto działający przykład:

CSS

body {
  margin: 0px;
  padding: 0px;
  text-align: center;
}

.table {
  width: 100%;
  height: 100%;
  display: grid;
  grid-template-rows: 50px auto;
}
.table-heading {
  background-color: #ddd;
}
.table-content {
  overflow-x: hidden;
  overflow-y: scroll;
}

HTML

<html>
    <head>
    </head>
    <body>
        <div class="table">
            <div class="table-heading">
                HEADING
            </div>
            <div class="table-content">
                CONTENT - CONTENT - CONTENT <br/>
                CONTENT - CONTENT - CONTENT <br/>
                CONTENT - CONTENT - CONTENT <br/>
                CONTENT - CONTENT - CONTENT <br/>
                CONTENT - CONTENT - CONTENT <br/>
                CONTENT - CONTENT - CONTENT <br/>
            </div>
        </div>
    </body>
</html>
Jeffrey Roosendaal
źródło
0

Wypróbowałem to używając transformacji: translate . Chociaż działa dobrze w Firefoksie i Chrome, po prostu nie ma funkcji w IE11. Brak podwójnych pasków przewijania. Obsługuje tfoot tabeli i podpis. Czysty Javascript, bez jQuery.

http://jsfiddle.net/wbLqzrfb/42/

thead.style.transform="translate(0,"+(dY-top-1)+"px)";
Henrik Haftmann
źródło
0

Znalazłem rozwiązanie bez jQuery

HTML

<table class="fixed_header">
  <thead>
    <tr>
      <th>Col 1</th>
      <th>Col 2</th>
      <th>Col 3</th>
      <th>Col 4</th>
      <th>Col 5</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>row 1-0</td>
      <td>row 1-1</td>
      <td>row 1-2</td>
      <td>row 1-3</td>
      <td>row 1-4</td>
    </tr>
    <tr>
      <td>row 2-0</td>
      <td>row 2-1</td>
      <td>row 2-2</td>
      <td>row 2-3</td>
      <td>row 2-4</td>
    </tr>
    <tr>
      <td>row 3-0</td>
      <td>row 3-1</td>
      <td>row 3-2</td>
      <td>row 3-3</td>
      <td>row 3-4</td>
    </tr>
    <tr>
      <td>row 4-0</td>
      <td>row 4-1</td>
      <td>row 4-2</td>
      <td>row 4-3</td>
      <td>row 4-4</td>
    </tr>
    <tr>
      <td>row 5-0</td>
      <td>row 5-1</td>
      <td>row 5-2</td>
      <td>row 5-3</td>
      <td>row 5-4</td>
    </tr>
    <tr>
      <td>row 6-0</td>
      <td>row 6-1</td>
      <td>row 6-2</td>
      <td>row 6-3</td>
      <td>row 6-4</td>
    </tr>
    <tr>
      <td>row 7-0</td>
      <td>row 7-1</td>
      <td>row 7-2</td>
      <td>row 7-3</td>
      <td>row 7-4</td>
    </tr>
  </tbody>
</table>

CSS

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

.fixed_header tbody{
  display:block;
  width: 100%;
  overflow: auto;
  height: 100px;
}

.fixed_header thead tr {
   display: block;
}

.fixed_header thead {
  background: black;
  color:#fff;
}

.fixed_header th, .fixed_header td {
  padding: 5px;
  text-align: left;
  width: 200px;
}

Możesz zobaczyć, jak działa tutaj: https://jsfiddle.net/lexsoul/fqbsty3h

Źródło: https://medium.com/@vembarrajan/html-css-tricks-scroll-able-table-body-tbody-d23182ae0fbc

Lexsoul
źródło