Tiêu đề bảng để cố định ở trên cùng khi người dùng cuộn nó ra khỏi tầm nhìn với jQuery


145

Tôi đang cố gắng thiết kế một bảng HTML trong đó tiêu đề sẽ ở đầu trang khi VÀ CHỈ khi người dùng cuộn nó ra khỏi tầm nhìn. Ví dụ: bảng có thể giảm 500 pixel so với trang, làm thế nào để tôi tạo bảng sao cho nếu người dùng cuộn tiêu đề ra khỏi chế độ xem (trình duyệt phát hiện không còn trong chế độ xem windows nữa), nó sẽ luôn ở trên cùng ? Bất cứ ai cũng có thể cho tôi một giải pháp Javascript cho việc này?

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

Vì vậy, trong ví dụ trên, tôi muốn <thead>cuộn với trang nếu nó không nhìn thấy.

QUAN TRỌNG: Tôi KHÔNG tìm kiếm một giải pháp trong đó <tbody>sẽ có một thanh cuộn (tràn: tự động).




Tôi đã trả lời điều này cho một câu hỏi khác, xin hãy xem. stackoverflow.com/a/56764334/9388978
Ersel Aktas

Câu trả lời:


131

Bạn sẽ làm một cái gì đó như thế này bằng cách chạm vào scrolltrình xử lý sự kiện windowvà sử dụng cái khác tablevới vị trí cố định để hiển thị tiêu đề ở đầu trang.

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();
    }
});

Điều này sẽ hiển thị đầu bảng khi người dùng cuộn xuống đủ xa để ẩn đầu bảng gốc. Nó sẽ ẩn lần nữa khi người dùng đã cuộn trang lên đủ xa một lần nữa.

Ví dụ hoạt động: http://jsfiddle.net/andrewwhitaker/fj8wM/


60
Tôi đã nghĩ về điều này nhưng nếu độ rộng của các cột tiêu đề thay đổi dựa trên nội dung thì sao? Trừ khi độ rộng cột được cố định, bạn có thể có hàng tiêu đề không thẳng hàng với các hàng nội dung. Chỉ là một ý nghĩ.
Yzmir Ramirez

16
ví dụ này không hoạt động nếu tên của các tiêu đề cột ngắn hơn các giá trị dữ liệu cột. Hãy thử thay đổi fiddle đó để có các giá trị như infoooooooo thay vì thông tin. Tôi đang nghĩ một số loại chiều rộng được mã hóa cứng được thiết lập khi nhân bản bảng.
whiterook6

6
Điều này có những hạn chế lớn, ít nhất là khi cố gắng sử dụng bảng trong một thùng chứa khác window. mkoryak.github.io/floatThead có một giải pháp thường được áp dụng hơn.
Yuck

13
Điều này có thể giúp bất cứ ai cần chiều rộng thứ động, đó là những gì tôi đang làm, đó là một ngã ba của @AndrewWhitaker: jsfiddle.net/noahkoch/wLcjh/1
Noah Koch

1
Tiêu đề cố định @NoahKoch sử dụng giải pháp của bạn có thể vẫn không rộng bằng tiêu đề ban đầu khi các ô ban đầu có phần đệm. Tôi đã cải thiện giải pháp của bạn để thêm phần đệm vào các ô trùng lặp. Ngã ba của JSFiddle: jsfiddle.net/1n23m69u/2
fandasson

46

Vâng, tôi đã cố gắng để có được hiệu ứng tương tự mà không cần dùng đến các cột có kích thước cố định hoặc có chiều cao cố định cho toàn bộ bảng.

Giải pháp tôi đưa ra là hack. Nó bao gồm sao chép toàn bộ bảng sau đó ẩn tất cả mọi thứ trừ tiêu đề và làm cho nó có một vị trí cố định.

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

Xem tại đây: http://jsfiddle.net/QHQGF/7/

Chỉnh sửa: đã cập nhật mã để thead có thể nhận các sự kiện con trỏ (vì vậy các nút và liên kết trong tiêu đề vẫn hoạt động). Điều này khắc phục sự cố được báo cáo bởi luhfluh và Joe M.

Jsfiddle mới tại đây: http://jsfiddle.net/cjKEx/


3
Tôi đã thử điều đó trước tiên, vấn đề với điều đó là kích thước của các phần tử trong tiêu đề phụ thuộc vào nội dung của bảng. Nếu bạn có một hàng có nội dung lớn, toàn bộ cột, bao gồm cả tiêu đề sẽ phát triển. Nếu bạn chỉ sao chép thông tin bạn sẽ mất thông tin đó và bạn không nhận được hiệu quả mong muốn. Xem bình luận của Yzmir Ramirez về câu trả lời được chấp nhận. Đây là cách duy nhất tôi thấy rằng hoạt động mà không có cột chiều rộng cố định. Nó không sạch, tôi biết, đó là cách tôi nói đó là một vụ hack.
entropy

1
Ồ, tôi hiểu rồi Phương pháp này rất hay vì nó hoạt động với các cột chất lỏng, tôi đã googled một chút và không thể tìm thấy một cái khác có chức năng đó. Dù sao đi nữa, nếu tôi sẽ hoàn thành nó bằng cách nào đó, tôi sẽ đề cập đến nó ở đây
M2_

1
@luhfluh, yeah, vấn đề là do các sự kiện con trỏ: không có trong bảng nhân bản. Điều này được sử dụng để các nhấp chuột đi qua bản sao và đến bảng gốc. Hoàn nguyên nó trong tiêu đề của bảng nhân bản để tiêu đề (và chỉ tiêu đề) có thể nhấp được khắc phục vấn đề. Tôi đã cập nhật bài viết của mình để phản ánh điều này :)
entropy

4
vấn đề thêm đường viền trên <thead> <th>
Jam Ville

1
@JamVille Vì bảng nhân bản có visibility: hidden. Bạn chỉ có thể ẩn #clone tbodyvà sau đó bạn có thể đặt đường viền ... Fiddle hoạt động
Lajdák Marek 15/2/18

46

CSS thuần túy (không hỗ trợ 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;
}

1
Tôi thậm chí không thấy điều này hoạt động trong Chrome. Các công cụ kiểm tra hiển thị -webkit-stickynhư một giá trị không hợp lệ cho position.
thuyết carmen

@carmenism -webkit-stickydành cho Safari (Máy tính để bàn & iOS), không dành cho Chrome. position: stickyhoạt động trong Chrome từ phiên bản 56. Bạn nên đặt quy tắc BÓNG: -webkit-stickystickychính xác theo thứ tự như trong ví dụ mã của tôi. Safari được webkit-stickyvà tất cả các trình duyệt khác ghi đè lên nó sticky.
Ihor Zenich

2
Tôi đã không thể làm điều này để làm việc. Từ một google nhanh, có vẻ như position: stickysẽ không hoạt động với các yếu tố bảng.
rjh

3
áp dụng cho tôi làm việc cho tôi: bảng thead tr th {...}
hãy nuôi dưỡng

1
Bạn phải áp dụng nó cho thứ này vì nó sẽ không hoạt động trên cả
tread

26

Tôi đã viết một plugin làm điều này. Tôi đã làm việc với nó khoảng một năm nay và tôi nghĩ rằng nó xử lý tất cả các trường hợp góc khá tốt:

  • cuộn trong một container với tràn
  • cuộn trong cửa sổ
  • quan tâm đến những gì xảy ra khi bạn thay đổi kích thước cửa sổ
  • giữ cho các sự kiện của bạn bị ràng buộc với tiêu đề
  • quan trọng nhất là nó không buộc bạn phải thay đổi css của bảng để làm cho nó hoạt động

Dưới đây là một số bản demo / tài liệu:
http://mkoryak.github.io/floatThead/


nỗ lực rất lớn, nhưng không hoạt động với IE 10 và có một số điểm kỳ lạ trong việc thay đổi kích thước cửa sổ trên firefox23 / ubfox.
JANNING

2
FYI: tôi đã sửa các vấn đề với IE9 và 10 trong phiên bản mới nhất.
mkoryak

2
Bạn có thể tạo một phiên bản không yêu cầu jQuery không?
Curtis W

2
có lẽ bởi vì anh ta không sử dụng jquery ... và không - tôi sẽ không tạo ra một phiên bản không sử dụng jquery.
mkoryak

1
Tôi sử dụng một trình cắm bảng jQery đơn giản và theo câu hỏi thường gặp của bạn, plugin của bạn không giống như hầu hết các quy tắc CSS như #sortable td {..}, v.v. Tôi đã cố gắng để điều chỉnh một chút nhưng tôi không thể làm cho nó hoạt động.
masche

25

Tôi đã có thể khắc phục vấn đề với việc thay đổi độ rộng cột. Tôi đã bắt đầu với giải pháp của Andrew ở trên (cảm ơn rất nhiều!) Và sau đó thêm một vòng lặp nhỏ để đặt độ rộng của td nhân bản:

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

Điều này giải quyết vấn đề mà không cần phải sao chép toàn bộ bảng và ẩn cơ thể. Tôi hoàn toàn mới đối với JavaScript và jQuery (và để xếp chồng tràn), vì vậy mọi bình luận đều được đánh giá cao.


4
Hoạt động tốt nhưng tôi cần thêm dòng sau $ ("# header-fixed"). Width ($ ("# table-1"). Width ()); cho các cột để xếp hàng chính xác.
Ilya Fedotov

17

Đây là giải pháp tốt nhất mà tôi đã tìm thấy để có một tiêu đề bảng cố định.

CẬP NHẬT 5/11: Đã sửa lỗi cuộn ngang được chỉ ra bởi 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>


Tôi đã sửa tập lệnh này để nó có thể xử lý các phần tử <th> có viền và phần đệm (nếu không, nó đặt tiêu đề cố định <th> chiều rộng quá rộng). Chỉ cần thay đổi outerWidththành widthđịnh nghĩa hàm resizeFixed ().
alanng

Bạn cũng có thể cần thêm một thuộc tính CSS của z-indexmột số số dương trên .fixedlớp để các đối tượng được hiển thị sau khi tải trang trong bảng không nổi lên trên tiêu đề cố định khi bạn cuộn.
alanng

Đơn giản và hữu ích.
RitchieD

Làm thế nào để tự động xử lý vị trí hàng đầu. Giả sử, tôi cần cuộn lên bên dưới nội dung tiêu đề cố định trang chính của mình. .fixed {top: 0;} .
VijayVishnu

2
@KerryJohnson Cảm ơn bạn đã lưu ý. Tôi đã thực hiện một số thay đổi để hỗ trợ cuộn ngang và độ rộng cột động.
josephting

7

Giải pháp tốt nhất là sử dụng plugin jquery này:

https://github.com/jmosbech/StickyTableHeaders

Plugin này hoạt động rất tốt cho chúng tôi và chúng tôi đã thử rất nhiều giải pháp khác. Chúng tôi đã thử nghiệm nó trong IE, Chrome và Firefox


Bạn có biết bất kỳ giải pháp nào cũng bảo tồn chức năng của các điều khiển ràng buộc dữ liệu loại bỏ trong tiêu đề không?
Csaba Toth

Không hoạt động đối với tôi: các tiêu đề nằm ngoài bảng và bám sát đầu trình duyệt (cửa sổ), ngay cả với tùy chọn "scrollableArea". Tôi thấy rằng điều này đã được đề cập trước đó mà không có ý kiến ​​bổ sung. Có lẽ nó cần một CSS mà anh ta sử dụng và không có sẵn để làm cho nó hoạt động.
Exel Gamboa

6

Có rất nhiều giải pháp thực sự tốt ở đây rồi. Nhưng một trong những giải pháp CSS đơn giản nhất mà tôi sử dụng trong các tình huống này là như sau:

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>

Vì không có yêu cầu đối với JavaScript, nó đơn giản hóa đáng kể tình huống. Về cơ bản, bạn cần tập trung vào quy tắc CSS thứ hai , trong đó có các điều kiện để đảm bảo rằng phần đầu của bảng vẫn ở trên cùng bất kể không gian cuộn.

Để giải thích chi tiết về từng quy tắc. positioncó nghĩa là để chỉ cho trình duyệt biết rằng đối tượng đầu, hàng của nó và các ô của nó đều cần phải bám trên đỉnh. Điều này nhất thiết cần phải đi kèm top, trong đó chỉ định cho trình duyệt rằng phần đầu sẽ dính vào đầu trang hoặc chế độ xem. Ngoài ra, bạn có thể thêm z-indexđể đảm bảo rằng nội dung của đầu luôn luôn ở trên cùng.

Màu nền chỉ đơn thuần là để minh họa điểm. Bạn không cần sử dụng bất kỳ JavaScript bổ sung nào để có được hiệu ứng này. Điều này được hỗ trợ trong hầu hết các trình duyệt chính sau năm 2016.


1
Imo câu trả lời đơn giản và sạch sẽ nhất, luôn có một cách đơn giản để giải quyết một vấn đề, đây là trường hợp. Mặc dù tôi đang sử dụng ng-repeat với angularjs, nó vẫn hoạt động như một bùa mê.
David Castro

5

Tôi tìm thấy một thư viện jQuery đơn giản có tên là Tiêu đề bảng dính. Hai dòng mã và nó đã làm đúng những gì tôi muốn. Các giải pháp ở trên không quản lý độ rộng cột, vì vậy nếu bạn có các ô bảng chiếm nhiều không gian, kích thước kết quả của tiêu đề liên tục sẽ không khớp với chiều rộng của bảng của bạn.

http://plugins.jquery.com/StickyTableHeaders/

Thông tin sử dụng tại đây: https://github.com/jmosbech/StickyTableHeaders


3

Chà, sau khi xem xét tất cả các giải pháp có sẵn, tôi đã viết plugin có thể đóng băng bất kỳ hàng nào (không chỉ thứ) ở đầu trang hoặc vùng chứa. Nó rất đơn giản và rất nhanh. Hãy sử dụng nó. http://maslianok.github.io/stickyRows/


3

bạn có thể sử dụng phương pháp này, HTML thuần túy và CSS không cần 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>


3

Tôi đã tìm thấy một giải pháp đơn giản mà không cần sử dụng JQuery và chỉ sử dụng CSS .

Bạn phải đặt nội dung cố định vào trong thẻ 'th' và thêm CSS

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

Vị trí, chỉ số z và thuộc tính hàng đầu là đủ. Nhưng bạn có thể áp dụng phần còn lại để cung cấp cho một cái nhìn tốt hơn.


2

Tôi cũng đã trải qua các vấn đề tương tự với định dạng đường viền không được hiển thị bằng mã entrophy nhưng một vài sửa chữa và bây giờ bảng có thể mở rộng và hiển thị tất cả các quy tắc kiểu dáng css bạn có thể thêm.

để css thêm:

#maintable{width: 100%}    

đây là javascript mới:

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

Điều này không hoạt động tốt hơn giải pháp của entropy khi định dạng đường viền đi vào tiêu đề. Tuy nhiên, trong Firefox hiện tại (nhưng không phải Chrome), nó tạo ra các tạo phẩm viền ô hiển thị bên dưới bảng khi quá trình cuộn bắt đầu.
alanng

2

Đây là một giải pháp dựa trên câu trả lời được chấp nhận. Nó sửa cho: độ rộng cột, kiểu bảng phù hợp và khi bảng được cuộn trong div container.

Sử dụng

Đảm bảo bảng của bạn có <thead>thẻ vì chỉ nội dung thead sẽ được sửa.

$("#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);

1
Điều này làm việc tốt cho tôi. Chỉ có điều là một vấn đề với các bảng cần phải cuộn theo chiều ngang. Tôi đã thực hiện cập nhật trong một JSFiddle tại đây jsfiddle.net/4mgneob1/1 Tôi trừ đi $sp.scrollLeft()số tiền được cuộn từ bên trái để khi cuộn xuống bảng cố định được đặt đúng vị trí. Đồng thời thêm kiểm tra khi cuộn theo chiều ngang nếu bảng cố định hiển thị để điều chỉnh vị trí bên trái. Một vấn đề khác tôi không thể giải quyết là khi bảng vượt lên trên khung nhìn, bảng cố định sẽ ẩn cho đến khi người dùng cuộn lại.
Henesnarfel

1
BắtUncaught TypeError: $table.scrollParent is not a function
karlingen

1

Điều này sẽ giúp bạn có một tiêu đề cố định cũng có thể được cuộn theo chiều ngang với dữ liệu.

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

Điều này sẽ giúp bạn có một tiêu đề cố định cũng có thể được cuộn theo chiều ngang với dữ liệu.
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>");}

Đây là giải pháp của tôi


1

Một chút muộn cho bữa tiệc, nhưng đây là một triển khai hoạt động với nhiều bảng trên cùng một trang và "jank" miễn phí (sử dụng requestAnimationFrame). Ngoài ra, không cần cung cấp bất kỳ chiều rộng nào trên các cột. Cuộn ngang cũng hoạt động.

Các tiêu đề được xác định trong một divđể bạn có thể tự do thêm bất kỳ đánh dấu nào ở đó (như các nút), nếu cần. Đây là tất cả các HTML cần thiết:

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


1

Trong giải pháp này, tiêu đề cố định được tạo động, nội dung và kiểu được sao chép từ THEAD

tất cả những gì bạn cần là hai dòng chẳng hạn:

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

Plugin jquery của tôi FixedHeader và getStyleObject được cung cấp bên dưới bạn có thể đặt vào tệp .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>


1

Tạo bảng phụ có cùng tiêu đề với bảng chính. Chỉ cần đặt thead trong bảng mới với một hàng và tất cả các tiêu đề trong đó. Làm vị trí tuyệt đối và nền trắng. Đối với bảng chính, đặt nó vào một div và sử dụng một số cuộn chiều cao và tràn. Bằng cách này, bảng mới của chúng tôi sẽ vượt qua tiêu đề của bảng chính và ở đó. Bao quanh mọi thứ trong một div. Dưới đây là mã thô để làm điều đó.

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

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>

Bản trình diễn: bản thử nghiệm tiêu đề bảng cố định css


1

Khắc phục sự cố của bạn với điều này

tbody {
  display: table-caption;
  height: 200px;
  caption-side: bottom;
  overflow: auto;
}

0

Điều này có thể đạt được bằng cách sử dụng chuyển đổi thuộc tính phong cách. Tất cả những gì bạn phải làm là gói bảng của bạn vào một số div với chiều cao cố định và tràn được đặt thành tự động, ví dụ:

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

Và sau đó bạn có thể đính kèm trình xử lý onscroll vào nó, ở đây bạn có phương thức tìm thấy mỗi bảng được gói bằng <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
      })
    })
  }

Và đây là ví dụ hoạt động của điều này trong hành động (tôi đã sử dụng bootstrap để làm cho nó đẹp hơn): fiddle

Đối với những người cũng muốn hỗ trợ IE và Edge, đây là đoạn trích:

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

Trong IE và Edge cuộn hơi chậm một chút ... nhưng nó hoạt động

Đây là câu trả lời giúp tôi tìm ra điều này: câu trả lời


0

Tôi đã thử hầu hết các giải pháp này và cuối cùng tìm thấy (IMO) giải pháp tốt nhất, hiện đại nhất:

Lưới CSS


Với các lưới CSS, bạn có thể xác định một 'lưới' và cuối cùng bạn có thể tạo ra một giải pháp trình duyệt chéo đẹp, không có javascript cho một bảng có tiêu đề cố định và nội dung có thể cuộn. Chiều cao tiêu đề thậm chí có thể năng động.

CSS : Hiển thị dưới dạng lưới và đặt số lượng template-rows:

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

HTML : Tạo một thùng chứa lưới và số lượng được xác định rows:

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

Dưới đây là ví dụ hoạt động:

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>

0

Tôi đã thử nó bằng cách sử dụng chuyển đổi: dịch . Mặc dù nó hoạt động tốt trong Firefox và Chrome, nhưng đơn giản là không có chức năng nào trong IE11. Không có thanh cuộn đôi. Hỗ trợ bàn chân và chú thích. Javascript thuần túy, không có jQuery.

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

thead.style.transform="translate(0,"+(dY-top-1)+"px)";

0

Tôi tìm thấy một giải pháp mà không cần 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;
}

Bạn có thể thấy nó hoạt động ở đây: https://jsfiddle.net/lexsoul/fqbsty3h

Nguồn: https://medium.com/@vembarrajan/html-css-tricks-scroll-able-table-body-tbody-d23182ae0fbc

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.