Bảng có tiêu đề cố định và cột cố định trên css thuần túy


97

Tôi cần tạo một bảng html (hoặc một cái gì đó tương tự) với tiêu đề cố định và cột đầu tiên cố định.

Mọi giải pháp tôi đã thấy cho đến nay đều sử dụng Javascript hoặc jQueryđể đặt scrollTop / scrollLeft, nhưng nó không hoạt động trơn tru trên các trình duyệt di động, vì vậy tôi đang tìm kiếm một giải pháp CSS thuần túy.

Tôi đã tìm thấy giải pháp cho một cột cố định tại đây: jsfiddle.net/C8Dtf/20/ nhưng tôi không biết làm cách nào để cải thiện nó để làm cho tiêu đề cũng cố định.

Tôi muốn nó hoạt động trên trình duyệt webkit hoặc sử dụng một số css3tính năng, nhưng tôi xin nhắc lại, tôi không muốn sử dụng Javascriptđể cuộn.

CHỈNH SỬA: Đây là ví dụ về hành vi tôi muốn đạt được: https://web.archive.org/web/20130829032141/http://datatables.net/release-datatables/extras/FixedColumns/css_size.html


Tôi không thấy <html> <table> với tiêu đề cố định <thead> phải làm gì với css-level-3 vào lúc này. Bạn còn thứ gì khác không ? Bạn đã thử những gì cho đến nay ?
Milche Patern

Tôi đã cố gắng áp dụng positionhành vi phức tạp cho các hàng và ô, nhưng tôi không hiểu rõ ở đâu nó có thể đặt được hay không.
panfil

2
Câu trả lời này có thể giúp bạn stackoverflow.com/questions/14834198/…
Garry

Câu trả lời:


141

Một giải pháp CSS thuần túy thực tế với hàng tiêu đề cố định và cột đầu tiên

Tôi phải tạo một bảng với cả tiêu đề cố định và cột đầu tiên cố định bằng cách sử dụng CSS thuần túy và không có câu trả lời nào ở đây đúng như ý tôi.

Các position: stickybất động sản hỗ trợ cả gắn bó đầu trang (như tôi đã nhìn thấy nó được sử dụng nhiều nhất) và bên cạnh các phiên bản hiện đại của Chrome, Firefox, và Edge. Điều này có thể được kết hợp với một divcó thuộc overflow: scrolltính để cung cấp cho bạn một bảng với các tiêu đề cố định có thể được đặt ở bất kỳ đâu trên trang của bạn:

Đặt bàn của bạn trong một thùng chứa:

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

Sử dụng overflow: scrolltrên vùng chứa của bạn để cho phép cuộn:

div.container {
  overflow: scroll;
}

Như Dagmar đã chỉ ra trong các nhận xét, vùng chứa cũng yêu cầu a max-widthvà a max-height.

Sử dụng position: stickyđể có các tế bào bảng dính vào mép và top, righthoặc leftđể chọn cạnh để dính vào:

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

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

Như MarredCheese đã đề cập trong các nhận xét, nếu cột đầu tiên của bạn chứa <td>các phần tử thay vì<th> phần tử, bạn có thể sử dụng tbody td:first-childtrong CSS của mình thay vìtbody th

Để tiêu đề trong cột đầu tiên dính vào bên trái, hãy sử dụng:

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

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


22
Đây có vẻ như là câu trả lời tốt nhất.
user1190132

9
@PirateApp Nếu bạn biết widthcủa cột đầu tiên của bạn, bạn có thể sử dụng position: stickytrên các tế bào trong cột thứ hai của bạn với một leftgiá trị tương đương với đầu cột của bạn width: jsfiddle.net/wvypo83c/794
Matthew Schlachter

4
Câu trả lời này chứng minh rằng nó đáng để đọc đến tận cùng!
mlerley

4
Điều này không hoạt động nếu không đặt chiều rộng tối đa và chiều cao tối đa trên vùng chứa.
Dagmar

9
Câu trả lời này là ngọn hải đăng hướng dẫn chúng ta về nhà vượt qua biển vô tận của những câu trả lời trục trặc, quá phức tạp, lãng phí thời gian từ những áp phích được ủng hộ đáng ngạc nhiên, đáng kinh ngạc ở đây trên SO và trên web. Lưu ý rằng nếu cột đầu tiên của bạn chứa <td>các phần tử thay vì các <th>phần tử, bạn có thể sử dụng tbody td:first-childtrong CSS của mình thay vì tbody th.
MarredCheese

32

Ngày nay, điều này có thể đạt được chỉ bằng cách sử dụng CSS với thuộc position: stickytính.

Đây là một đoạn mã:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  </div>
</div>

Về khả năng tương thích. Nó hoạt động trên tất cả các trình duyệt chính, nhưng không hoạt động trong IE. Có một polyfill cho position: stickynhưng tôi chưa bao giờ thử nó.


2
Điều này là tuyệt vời, tình yêu nó!
Captain Lu,

3
bất kỳ cách nào để đạt được điều này với <table> -tags chứ không phải <div>
Andreas

1
Tôi nghĩ rằng điều này sẽ không có hiệu suất tốt nếu bạn đang phát triển một ứng dụng và cần lặp qua các bản ghi để in bảng này vì đối với mỗi cột trong bảng, bạn phải lặp qua toàn bộ mảng của bản ghi. HTML này hoạt động theo từng cột.
igasparetto

@igasparetto Bạn thực sự có thể sắp xếp các hàng / cột theo cách khác và giải pháp vẫn sẽ hoạt động. Nếu có thời gian sau, tôi có thể tạo đoạn mã với hàng được sắp xếp theo lưới -> cột.
Alvaro

2
Tôi khuyên bạn không nên hiển thị dữ liệu dạng bảng mà không sử dụng <table> và các thẻ được liên kết. Có một số vấn đề với việc phá vỡ mục đích sử dụng HTML theo cách này, bao gồm cả khả năng truy cập. Xem thêm: w3.org/WAI/tutorials/tables
Ben Morris

15

Đây không phải là một kỳ công dễ dàng.

Liên kết sau đây là một bản demo đang hoạt động:

Liên kết Cập nhật theo bình luận của lanoxx

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

Chỉ cần nhớ thêm những điều sau:

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

tôi không thấy bất kỳ cách nào khác để đạt được điều này. Đặc biệt là không chỉ bằng cách sử dụng css.

Điều này là rất nhiều để trải qua. Hi vọng điêu nay co ich :)


Để chuyển đổi từ việc sử dụng bộ lọc: "bFilter": false
lanoxx

6
Đó có thể để đạt được điều này chỉ với css. Không dễ dàng nhưng có thể.
Jimmy T.

từ khoảng 10 giải pháp, đây là giải pháp duy nhất hoạt động. Btw, để loại bỏ "Hiển thị 1 đến 57 trong số 57 mục nhập" "bInfo" : falsevào .dataTable()cuộc gọi
hansaplast

datatables == "awesome"
billynoah

từ chối giải pháp này vì nó không tốt. những theadlà trong bảng riêng của mình mà không bị ràng buộc với những thay đổi của tdcác yếu tố, vì vậy nếu một văn bản tế bào là dài, thchiều rộng sẽ không điều chỉnh cho phù hợp.
vsync

14

Tất cả những đề xuất này đều tuyệt vời và tất cả, nhưng chúng chỉ sửa tiêu đề hoặc cột chứ không phải cả hai hoặc chúng đang sử dụng javascript. Lý do - nó không tin rằng nó có thể được thực hiện trong CSS thuần túy. Nguyên nhân:

Nếu có thể làm điều đó, bạn cần phải lồng một số div có thể cuộn vào bên trong nhau, mỗi div có một cuộn theo một hướng khác nhau. Sau đó, bạn sẽ cần chia bảng của mình thành ba phần - tiêu đề cố định, cột cố định và phần còn lại của dữ liệu.

Khỏe. Nhưng bây giờ vấn đề - bạn có thể đặt một trong số chúng ở nguyên khi bạn cuộn, nhưng cái còn lại được lồng bên trong vùng cuộn của đầu tiên và do đó có thể tự cuộn ra khỏi tầm nhìn, vì vậy không thể sửa tại chỗ trên màn hình. "Ah-ha" bạn nói "nhưng tôi bằng cách nào đó có thể sử dụng vị trí tuyệt đối hoặc cố định để làm điều đó" - không bạn không thể. Ngay sau khi bạn làm điều đó, bạn sẽ mất khả năng cuộn vùng chứa đó. Đó là tình huống con gà và quả trứng - bạn không thể có cả hai, chúng triệt tiêu lẫn nhau.

Tôi tin rằng giải pháp duy nhất là thông qua javascript. Bạn cần tách biệt hoàn toàn ba phần tử và giữ cho vị trí của chúng được đồng bộ thông qua javascript. Có những ví dụ tốt trong các bài viết khác trên trang này. Cái này cũng đáng xem:

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


9

Tôi đã thực hiện một số thay đổi trong jsfiddle. Đây có thể là những gì bạn đang cố gắng làm.

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

Tôi đã mã hóa các tiêu đề như vậy:

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

Và tôi cũng đã thêm một số phong cách.

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

Hy vọng đây là những gì bạn muốn :)


1
Tôi cần một tiêu đề của bảng bên phải để cuộn cùng với nội dung của nó.
panfil

Đây là URL: jsfiddle.net/C8Dtf/84 . Bạn chỉ cần thử tạo kiểu cho bàn bên phải để căn chỉnh hai bảng.
Phillip-juan

Không, bạn không hiểu lắm. Tôi cần cố định tiêu đề của bảng bên phải lên trên cùng để nó vẫn hiển thị khi bảng cuộn lên và cuộn xuống, nhưng khi bảng cuộn sang phải hoặc trái, tiêu đề phải cuộn sang phải hoặc sang trái nhưng vẫn được cố định ở trên cùng. Xin lỗi tôi vì kỹ năng tiếng Anh kém của tôi.
panfil

Vì vậy, muốn tiêu đề của bảng bên phải được cố định khi cuộn theo chiều dọc và để cuộn khi cuộn theo chiều ngang?
Phillip-juan

Đây là ví dụ về hành vi tôi muốn đạt được: datatables.net/release-datatables/extras/FixedColumns/…
panfil

9

Một ví dụ chỉ sử dụng CSS:

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

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

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

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

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

  <table class="table">

    <thead class="header">

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

    </thead>
  </table>

  <div class="body_panel">

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      </tbody>
    </table>

  </div>

</body>


3
Tôi không chỉ cần cố định heder mà còn cả cột đầu tiên.
panfil

Ví dụ này cho thấy một cách tiếp cận với hai bảng trong html: một bảng chỉ hiển thị tiêu đề; bảng thứ hai chỉ hiển thị các hàng nhưng làm như vậy trong a div. Nó divcho phép cuộn hàng trong khi tiêu đề vẫn ở cùng một vị trí. Cách tiếp cận này phù hợp với nhu cầu của tôi.
David Tansey

Nếu cũng có cuộn ngang, bạn cần một số JS để đồng bộ hóa vị trí cuộn của các bảng.
Zoltán Tamási

4

Để sửa cả Tiêu đề và Cột, bạn có thể sử dụng plugin sau:


Cập nhật vào tháng 7 năm 2019

Gần đây cũng nổi lên là một giải pháp CSS thuần túy dựa trên thuộc tính CSS position: sticky;( tại đây để biết thêm chi tiết về nó) được áp dụng cho từng THmục (thay vì vùng chứa mẹ của chúng)


1
Liên kết đầu tiên bị hỏng. Cái thứ hai sử dụng jQuery.
PussInBoots

Câu trả lời được cập nhật để loại bỏ chết liên kết
Luca Detomi

3

Tôi đã tìm thấy một giải pháp tuyệt vời của Paul O'Brien cho vấn đề này và muốn chia sẻ liên kết: https://codepen.io/paulobrien/pen/LBrMxa

Tôi đã xóa kiểu cho chân trang:

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

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

2

Gần đây tôi đã phải tạo một giải pháp với nhóm tiêu đề cố định và cột đầu tiên cố định. Tôi chia bảng của mình thành các div và sử dụng jquery để chụp cuộn cửa sổ.

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

var prevTop = 0;
var prevLeft = 0;

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

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

1

Một đồng nghiệp và tôi vừa phát hành một dự án GitHub mới cung cấp chỉ thị Angular mà bạn có thể sử dụng để trang trí bảng của mình với các tiêu đề cố định: https://github.com/objectcomputing/FixedHeader

Nó chỉ dựa vào css và angle, với một chỉ thị thêm một số div. Không cần jQuery.

Triển khai này không có đầy đủ tính năng như một số triển khai khác, nhưng nếu nhu cầu của bạn chỉ là thêm các bảng cố định, chúng tôi nghĩ đây có thể là một lựa chọn tốt.


1

Sau hai ngày chiến đấu với Internet Explorer 9 + Chrome + Firefox (Windows) và Safari (Mac), tôi đã tìm thấy một hệ thống

  • Tương thích với tất cả các trình duyệt này
  • Không sử dụng javascript
  • Chỉ sử dụng div và một bảng
  • Cố định đầu trang và chân trang (Ngoại trừ IE), với phần thân có thể cuộn được. Tiêu đề và nội dung có cùng độ rộng cột

Kết quả: nhập mô tả hình ảnh ở đây

HTML:

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

CSS:

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

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

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

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

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

div.cost_center table thead{
  display:block;
}

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

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

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

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

div.cost_center table tbody td {
  white-space: normal;
  font:  .8em/1.4em Verdana, sans-serif;
  color: #000;
  background-color: white;
}
div.cost_center table th.cabecera { 
  font:  0.8em/1.4em Verdana, sans-serif;
  color: #000;
  background-color: #FFEAB5;
}

Cố gắng tốt, nhưng không hiệu quả với tôi. Trong ví dụ này ( jsfiddle.net/5ka6e ), tiêu đề không thay đổi kích thước chính xác. Loại lỗi này cuối cùng có thể dẫn đến việc dữ liệu và tiêu đề không khớp.
darkzangel

1
Bạn quên thêm div.cost_center table{border-collapse: collapse;}và chú thích thứ ba phải là cái gì đó phù hợp trong 60px (trong ví dụ này)
Albert Català

1

Các câu trả lời hiện có sẽ phù hợp với hầu hết mọi người, nhưng đối với những người đang tìm cách thêm bóng dưới tiêu đề cố định và ở bên phải cột đầu tiên (cố định), đây là một ví dụ hoạt động (thuần css):

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

Thủ thuật chính để làm cho điều này hoạt động là sử dụng ::afterđể thêm bóng vào bên phải của từng bóng đầu tiên tdtrong mỗi tr:

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

Tôi đã mất một thời gian (quá lâu ...) để làm cho tất cả hoạt động, vì vậy tôi nghĩ rằng tôi sẽ chia sẻ cho những người đang trong tình trạng tương tự.


Bạn có căn cứ vào điều này để có ai đó trả lời và thêm bóng không?
PussInBoots

1

cần sửa chân trang đầu trang


0

Một cái gì đó như thế này có thể phù hợp với bạn ... Nó có thể sẽ yêu cầu bạn đặt độ rộng cột cho hàng tiêu đề của bạn.

thead { 
    position: fixed;
}

http://jsfiddle.net/vkhNC/

Cập nhật:

Tôi không tin rằng ví dụ bạn đưa ra có thể thực hiện được chỉ với CSS. Tôi rất thích ai đó chứng minh tôi sai. Đây là những gì tôi có cho đến nay . Nó không phải là thành phẩm nhưng nó có thể là một khởi đầu cho bạn. Tôi hy vọng điều này chỉ cho bạn một hướng hữu ích, bất cứ nơi nào có thể.


Tôi không chỉ cần tiêu đề, mà cả cột đầu tiên cũng được sửa.
panfil

5
Vấn đề là tiêu đề lỏng lẻo chiều rộng của chúng. Nó trông xấu xí với kích thước cột tiêu đề và kích thước cột dữ liệu khác nhau.
Akash Kava

0

Một giải pháp khác là sử dụng AngularJS. Mô-đun AngularUI có một chỉ thị được gọi là chỉ thị ng-gridhỗ trợ một tính năng được gọi là ghim cột. Nó không phải là CSS thuần túy 100% nhưng các giải pháp khác cũng vậy.

http://angular-ui.github.io/ng-grid/#columnPinning


0

Ví dụ về CSS thuần túy:

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


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

</div>

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

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

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

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

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

Nhược điểm: Cấu trúc / logic tiêu đề cố định khá phụ thuộc vào các kích thước cụ thể, vì vậy trừu tượng có lẽ không phải là một lựa chọn khả thi .


Cần cả tiêu đề cố định và cột đầu tiên cố định.
panfil

Ah ... thx vì đã chỉ ra điều này, panfil. Tôi sẽ chỉnh sửa. Cheers
Cody

0

Vị trí: dính không hoạt động đối với một số phần tử như (thead) trong chrome và các trình duyệt webkit khác như safari.

Nhưng nó hoạt động tốt với (th)

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

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

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

.sticky {
  position: sticky;
  top: 0;
  color: black;
  background-color: white;
}
<div class="container intro">
  <h1>Sticky Table Header</h1>
  <p>Postion : sticky doesn't work for some elements like (thead) in chrome and other webkit browsers like safari. </p>
  <p>But it works fine with (th)</p>
</div>
<div class="container wrapper">
  <table class="table table-striped">
    <thead>
      <tr>
        <th class="sticky">Firstname</th>
        <th class="sticky">Lastname</th>
        <th class="sticky">Email</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>James</td>
        <td>Vince</td>
        <td>james@example.com</td>
      </tr>
      <tr>
        <td>Jonny</td>
        <td>Bairstow</td>
        <td>jonny@example.com</td>
      </tr>
      <tr>
        <td>James</td>
        <td>Anderson</td>
        <td>james@example.com</td>
      </tr>
      <tr>
        <td>Stuart</td>
        <td>Broad</td>
        <td>stuart@example.com</td>
      </tr>
      <tr>
        <td>Eoin</td>
        <td>Morgan</td>
        <td>eoin@example.com</td>
      </tr>
      <tr>
        <td>Joe</td>
        <td>Root</td>
        <td>joe@example.com</td>
      </tr>
      <tr>
        <td>Chris</td>
        <td>Woakes</td>
        <td>chris@example.com</td>
      </tr>
      <tr>
        <td>Liam</td>
        <td>PLunkett</td>
        <td>liam@example.com</td>
      </tr>
      <tr>
        <td>Jason</td>
        <td>Roy</td>
        <td>jason@example.com</td>
      </tr>
      <tr>
        <td>Alex</td>
        <td>Hales</td>
        <td>alex@example.com</td>
      </tr>
      <tr>
        <td>Jos</td>
        <td>Buttler</td>
        <td>jos@example.com</td>
      </tr>
      <tr>
        <td>Ben</td>
        <td>Stokes</td>
        <td>ben@example.com</td>
      </tr>
      <tr>
        <td>Jofra</td>
        <td>Archer</td>
        <td>jofra@example.com</td>
      </tr>
      <tr>
        <td>Mitchell</td>
        <td>Starc</td>
        <td>mitchell@example.com</td>
      </tr>
      <tr>
        <td>Aaron</td>
        <td>Finch</td>
        <td>aaron@example.com</td>
      </tr>
      <tr>
        <td>David</td>
        <td>Warner</td>
        <td>david@example.com</td>
      </tr>
      <tr>
        <td>Steve</td>
        <td>Smith</td>
        <td>steve@example.com</td>
      </tr>
      <tr>
        <td>Glenn</td>
        <td>Maxwell</td>
        <td>glenn@example.com</td>
      </tr>
      <tr>
        <td>Marcus</td>
        <td>Stoinis</td>
        <td>marcus@example.com</td>
      </tr>
      <tr>
        <td>Alex</td>
        <td>Carey</td>
        <td>alex@example.com</td>
      </tr>
      <tr>
        <td>Nathan</td>
        <td>Coulter Nile</td>
        <td>nathan@example.com</td>
      </tr>
      <tr>
        <td>Pat</td>
        <td>Cummins</td>
        <td>pat@example.com</td>
      </tr>
      <tr>
        <td>Adam</td>
        <td>Zampa</td>
        <td>zampa@example.com</td>
      </tr>
    </tbody>
  </table>
</div>

Hoặc truy cập ví dụ codepen của tôi :



-2

Nếu bạn chỉ muốn sử dụng HTML và CSS thuần túy, tôi đã có giải pháp cho vấn đề của bạn:
Trong jsFiddle này, bạn có thể thấy một giải pháp không phải tập lệnh cung cấp một bảng có tiêu đề cố định. Cũng không thành vấn đề khi điều chỉnh đánh dấu cho cột đầu tiên cố định. Bạn chỉ cần tạo một bảng có vị trí tuyệt đối cho cột đầu tiên bên trong hWrapper-div và định vị lại vWrapper-div.
Việc cung cấp nội dung động không phải là vấn đề khi sử dụng công cụ hấp dẫn phía máy chủ hoặc phía trình duyệt, giải pháp của tôi hoạt động tốt trong tất cả các trình duyệt hiện đại và các trình duyệt cũ hơn từ IE8 trở đi.


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.