ตาราง HTML ที่มีส่วนหัวคงที่หรือไม่


231

มีเทคนิค CSS / JavaScript ข้ามเบราว์เซอร์เพื่อแสดงตาราง HTML แบบยาวเช่นว่าส่วนหัวคอลัมน์จะคงที่บนหน้าจอและไม่เลื่อนไปตามส่วนของตาราง นึกถึงเอฟเฟกต์ "freeze panes" ใน Microsoft Excel

ฉันต้องการที่จะสามารถเลื่อนดูเนื้อหาของตาราง แต่จะสามารถดูส่วนหัวคอลัมน์ที่ด้านบนเสมอ


3
ลองสิ่งนี้: Pure CSS Scrollable Table พร้อม Fixed Header EDIT : อันนี้ควรทำงานใน Internet Explorer 7 ดังที่เห็นในตัวอย่าง : การเลื่อนตาราง HTML พร้อม Fixed Header EDIT 2:ฉันพบลิงค์พิเศษอีกสองอย่างที่สามารถใช้: - Stupid fixed header - ปลั๊กอิน jQuery ที่มีข้อ จำกัด บางอย่าง - [ส่วนหัวตารางคงที่] ( cross-browser.com/x/examp
gcores

ฉันเจอวิธีแก้ปัญหาหลายอย่างที่ใช้งานได้ทั่วไป แต่ไม่มีใครทำงาน div เลื่อนได้ ฉันหมายความว่าตารางของคุณอยู่ใน div ที่เลื่อนได้และคุณยังต้องการให้ส่วนหัวของตารางของคุณอยู่ใน div นั้น ฉันได้รับการแก้ไขและแบ่งปันวิธีการแก้ปัญหาที่นี่
Yogee

9
ในปี 2018, thead th { position: sticky; top: 0; }เบราว์เซอร์สามารถใช้วิธีง่ายๆต่อไปนี้: Safari ต้องการคำนำหน้าผู้ขาย:-webkit-sticky
Daniel Waltrip

1
@DanielWaltrip คุณควรเพิ่มคำตอบนี้เพื่อให้ได้คะแนนสูง - คำตอบอื่น ๆ ทั้งหมดซ้ำซ้อนกับตำแหน่ง: เหนียวได้รับการสนับสนุนที่ดีขึ้นทุกวันนี้
Peter Kerr

คำตอบ:


88

ฉันกำลังหาวิธีแก้ปัญหานี้อยู่ครู่หนึ่งและพบว่าคำตอบส่วนใหญ่ไม่ทำงานหรือไม่เหมาะกับสถานการณ์ของฉันดังนั้นฉันจึงเขียนวิธีแก้ปัญหาง่ายๆด้วย jQuery

นี่คือเค้าร่างโซลูชัน:

  1. โคลนตารางที่จำเป็นต้องมีส่วนหัวคงที่และวางสำเนาโคลนที่ด้านบนของต้นฉบับ
  2. ลบส่วนของตารางออกจากตารางด้านบน
  3. ลบส่วนหัวของตารางออกจากตารางด้านล่าง
  4. ปรับความกว้างคอลัมน์ (เราติดตามความกว้างของคอลัมน์เดิม)

ด้านล่างเป็นรหัสในการสาธิตที่ทำงานได้

function scrolify(tblAsJQueryObject, height) {
  var oTbl = tblAsJQueryObject;

  // for very large tables you can remove the four lines below
  // and wrap the table with <div> in the mark-up and assign
  // height and overflow property  
  var oTblDiv = $("<div/>");
  oTblDiv.css('height', height);
  oTblDiv.css('overflow', 'scroll');
  oTbl.wrap(oTblDiv);

  // save original width
  oTbl.attr("data-item-original-width", oTbl.width());
  oTbl.find('thead tr td').each(function() {
    $(this).attr("data-item-original-width", $(this).width());
  });
  oTbl.find('tbody tr:eq(0) td').each(function() {
    $(this).attr("data-item-original-width", $(this).width());
  });


  // clone the original table
  var newTbl = oTbl.clone();

  // remove table header from original table
  oTbl.find('thead tr').remove();
  // remove table body from new table
  newTbl.find('tbody tr').remove();

  oTbl.parent().parent().prepend(newTbl);
  newTbl.wrap("<div/>");

  // replace ORIGINAL COLUMN width				
  newTbl.width(newTbl.attr('data-item-original-width'));
  newTbl.find('thead tr td').each(function() {
    $(this).width($(this).attr("data-item-original-width"));
  });
  oTbl.width(oTbl.attr('data-item-original-width'));
  oTbl.find('tbody tr:eq(0) td').each(function() {
    $(this).width($(this).attr("data-item-original-width"));
  });
}

$(document).ready(function() {
  scrolify($('#tblNeedsScrolling'), 160); // 160 is height
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>

<div style="width:300px;border:6px green solid;">
  <table border="1" width="100%" id="tblNeedsScrolling">
    <thead>
      <tr><th>Header 1</th><th>Header 2</th></tr>
    </thead>
    <tbody>
      <tr><td>row 1, cell 1</td><td>row 1, cell 2</td></tr>
      <tr><td>row 2, cell 1</td><td>row 2, cell 2</td></tr>
      <tr><td>row 3, cell 1</td><td>row 3, cell 2</td></tr>
      <tr><td>row 4, cell 1</td><td>row 4, cell 2</td></tr>			
      <tr><td>row 5, cell 1</td><td>row 5, cell 2</td></tr>
      <tr><td>row 6, cell 1</td><td>row 6, cell 2</td></tr>
      <tr><td>row 7, cell 1</td><td>row 7, cell 2</td></tr>
      <tr><td>row 8, cell 1</td><td>row 8, cell 2</td></tr>			
    </tbody>
  </table>
</div>

โซลูชันนี้ใช้ได้กับ Chrome และ IE เนื่องจากมันใช้ jQuery จึงควรทำงานกับเบราว์เซอร์ที่รองรับ jQuery อื่น ๆ ด้วย


4
และเราจะแก้ไขปัญหาได้อย่างไรเมื่อเนื้อหามีขนาดใหญ่กว่าความกว้าง
Maertz

1
@tetra td {ความกว้างสูงสุด: 30px; } สิ่งนี้จะช่วยให้ผู้พัฒนาสามารถควบคุมวิธีการแสดงแถว
Lyuben Todorov

แต่ถ้าเนื้อหาในเซลล์ส่วนหัวบางรายการยาวกว่าในเซลล์ td ล่ะ ฉันลองใน IE7 และ width () ทำลายทุกอย่าง IE8 และ IE9 ปรับการทำงาน แต่ ...
JustAMartin

4
น่าเสียดายที่หากคุณต้องการการจัดแนวพิกเซลที่สมบูรณ์แบบของคอลัมน์สิ่งนี้จะใช้ไม่ได้: jsbin.com/elekiq/1 ( ซอร์สโค้ด ) คุณจะเห็นว่าส่วนหัวบางส่วนถูกชดเชยจากตำแหน่งที่ควรจะเป็นเพียงเล็กน้อย ผลจะชัดเจนมากขึ้นถ้าคุณใช้พื้นหลัง: jsbin.com/elekiq/2 ( ซอร์สโค้ด ) (ฉันทำงานตามบรรทัดเดียวกันนี้วิ่งเข้าไปในรหัสของฉันพบคุณและคิดว่า "โอ้ฉันสงสัยว่าเขาแก้ไขให้ฉัน!" ไม่น่าเศร้า :-)) เบราว์เซอร์เป็นความเจ็บปวดเกี่ยวกับการต้องการควบคุม ความกว้างของเซลล์ ...
TJ Crowder

ดูเหมือนจะไม่ทำงานกับการเลื่อนในแนวนอน - มันสร้างส่วนหัว แต่ขยายออกไปนอกพื้นที่ที่เลื่อนได้ (มองเห็นได้) และไม่เลื่อนไปตามเนื้อหา
Crash

183

สามารถแก้ไขได้อย่างสมบูรณ์ในโค้ดสี่บรรทัด

หากคุณสนใจเฉพาะเบราว์เซอร์รุ่นใหม่ส่วนหัวคงที่สามารถทำได้ง่ายขึ้นโดยใช้การแปลง CSS ฟังดูแปลก แต่ใช้งานได้ดี:

  • HTML และ CSS ยังคงเหมือนเดิม
  • ไม่มีการพึ่งพา JavaScript ภายนอก
  • รหัสสี่บรรทัด
  • ใช้งานได้สำหรับการกำหนดค่าทั้งหมด (เค้าโครงตาราง: แก้ไข ฯลฯ )
document.getElementById("wrap").addEventListener("scroll", function(){
   var translate = "translate(0,"+this.scrollTop+"px)";
   this.querySelector("thead").style.transform = translate;
});

รองรับการแปลง CSS อย่างกว้างขวางยกเว้น Internet Explorer 8-

นี่คือตัวอย่างเต็มรูปแบบสำหรับการอ้างอิง:


8
ฉันต้องบอกว่าความคิดเห็นก่อนหน้าของฉันแม้จะเป็นสิ่งที่ใกล้เคียงกับโซลูชั่นที่สมบูรณ์แบบที่ฉันเคยเห็น แม้แต่การเลื่อนในแนวนอนก็สมบูรณ์แบบ (ดีกว่าโซลูชันของฉันเอง) นี่คือตัวอย่างที่มีเส้นขอบ (คุณไม่สามารถใช้การยุบขอบ) และแถบเลื่อนที่ยึดกับตารางแทนที่จะเป็นคอนเทนเนอร์: jsfiddle
DoctorDestructo

11
พบว่าใช้งานได้ แต่ต้องใช้การแปลงกับ th / td ไม่ใช่ thead
แดง

5
@AlexAlexeev โซลูชันของคุณยอดเยี่ยมมาก ขอบคุณ. ฉันสังเกตเห็นว่าส่วนหัวคงที่ที่ได้นั้นไม่มีเส้นขอบที่แยกคอลัมน์ สไตล์ CSS เริ่มต้นหายไป แม้ว่าฉันจะรวมสิ่งนี้ ... $(this).addClass('border')เปลี่ยนส่วนที่เหลือของตารางมีแบบอักษรขนาดและสีที่ฉันผ่านในคลาสของเส้นขอบ แต่จะไม่เพิ่มบรรทัดลงในส่วนหัวคงที่ ขอบคุณอินพุตใด ๆ เกี่ยวกับวิธีแก้ไขปัญหานี้
user5249203

5
@ user5249203 ฉันรู้ว่าคุณถามไม่กี่เดือนที่ผ่านมา แต่ฉันมีปัญหาเดียวกันและเป็นเพราะการยุบชายแดน: ดูนี่: stackoverflow.com/questions/33777751/
archz

6
สิ่งนี้ไม่ทำงานใน IE เวอร์ชันใด ๆ หรือใน Edge นี่คือรุ่นที่ใช้ความคิดเห็นของ @ redhead jsfiddle.net/n6o8ocwb/2
rob

58

ฉันเพิ่งเสร็จสิ้นการรวมปลั๊กอิน jQuery ที่จะใช้ตารางเดี่ยวที่ถูกต้องโดยใช้ HTML ที่ถูกต้อง (ต้องมี thead และ tbody) และจะส่งออกตารางที่มีส่วนหัวคงที่ส่วนท้ายคงที่ตัวเลือกที่อาจเป็นส่วนหัวโคลนหรือ เนื้อหาที่คุณเลือก (การแบ่งหน้า ฯลฯ ) หากคุณต้องการใช้ประโยชน์จากจอภาพขนาดใหญ่มันจะปรับขนาดตารางเมื่อปรับขนาดเบราว์เซอร์ด้วย คุณสมบัติที่เพิ่มเข้ามาอีกประการหนึ่งคือสามารถเลื่อนด้านข้างได้หากคอลัมน์ตารางไม่สามารถอยู่ในมุมมองทั้งหมดได้

http://fixedheadertable.com/

บน GitHub: http://markmalek.github.com/Fixed-Header-Table/

มันง่ายมากที่จะติดตั้งและคุณสามารถสร้างสไตล์ของคุณเองได้ นอกจากนี้ยังใช้มุมโค้งมนในเบราว์เซอร์ทั้งหมด โปรดทราบว่าฉันเพิ่งวางจำหน่ายจึงยังคงเป็นรุ่นเบต้าในทางเทคนิคและมีปัญหาเล็กน้อยเพียงเล็กน้อยที่ฉันกำลังจะเปิดตัว

มันทำงานได้ใน Internet Explorer 7, Internet Explorer 8, Safari, Firefox และ Chrome


ขอบคุณ! ฉันจะเพิ่มรีลีสใหม่ในวันนี้เมื่อฉันกลับถึงบ้านจากที่ทำงาน นี่คือลิงค์ไปยังรายการบล็อกของฉันพร้อมสิ่งที่ฉันเพิ่ม: fixedheadertable.mmalek.com/2009/10/07/ …
ทำเครื่องหมาย

ขอบคุณสำหรับสิ่งนี้. ฉันรู้ว่าคำถามนี้มีอายุเกินหนึ่งปี แต่ถึงแม้จะมีความเสี่ยงที่จะเกิดตะกอนตกตะกอนฉันอยากจะบอกคุณว่างานของคุณได้รับการชื่นชม
sova

ในการสาธิตของคุณความกว้างถูกปิดใน ie6 :-( ส่วนหัวของตารางและเนื้อความไม่เรียงกัน
Cheekysoft

4
รุ่นล่าสุดไม่ทำงานใน IE6 ฉันไม่สนับสนุน IE6 อีกต่อไป
ทำเครื่องหมาย

การทำงานที่ยอดเยี่ยมเครื่องหมาย - โชคไม่ดีมีปัญหาบางอย่างกับการเลื่อนส่วนหัวและคอลัมน์คงที่ในอุปกรณ์มือถือ (iPad, แท็บเล็ต Android) - เมื่อฉันเลื่อนเนื้อหาส่วนที่คงที่เหล่านั้นไม่เลื่อน - เมื่อฉันหยุดเลื่อนและแตะหนึ่งครั้ง ส่วนคงที่ "กระโดด" ไปยังตำแหน่งที่เหมาะสม - มีวิธีง่ายๆในการแก้ไขปัญหานี้หรือไม่?
Okizb

23

ฉันยังสร้างปลั๊กอินที่แก้ไขปัญหานี้ โปรเจคของฉัน - jQuery.floatTheadมีมานานกว่า 4 ปีแล้วและเป็นผู้ใหญ่มาก

มันไม่จำเป็นต้องมีสไตล์ภายนอกและไม่ได้คาดหวังว่าโต๊ะของคุณจะมีสไตล์ในแบบใดก็ตาม รองรับ Internet Explorer9 + และ Firefox / Chrome

ปัจจุบัน (2018-05) มี:

คอมมิชชัน 405 และ 998 ดาวบน GitHub


คำตอบจำนวนมาก (ไม่ใช่ทั้งหมด) ที่นี่คือแฮ็คด่วนที่อาจแก้ไขปัญหาที่บุคคลหนึ่งมี แต่จะไม่ทำงานสำหรับทุกโต๊ะ

ปลั๊กอินอื่น ๆ บางรุ่นเก่าและอาจใช้งานได้ดีกับ Internet Explorer แต่จะหยุดใน Firefox และ Chrome


1
ปลั๊กอินที่ยอดเยี่ยมรองรับตารางที่ซ้อนกันและออฟเซ็ต
Mihai Alex

2
ยิ่งใหญ่ ขอบคุณมาก. ปลั๊กอินทำงานได้ดีใน Firefox 45.2, Chromium 51 และ IE 11 นอกจากนี้จะไม่รบกวนกับโค้ด JS และ jQuery จำนวนมากที่สร้างขึ้นในหน้าเดียวกัน
Aldo Paradiso

ขอบคุณ. ฉันดีใจที่รายงานว่าโครงการได้รับรายงานบั๊กประมาณ 1 ครั้งทุก 4 เดือน ณ จุดนี้ ฉันไม่ได้ทำการเปลี่ยนแปลงมากมาย มันค่อนข้างแข็งและใช้งานได้ดี
mkoryak

20

TL; DR

หากคุณกำหนดเป้าหมายเบราว์เซอร์ที่ทันสมัยและไม่มีความต้องการสไตล์ฟุ่มเฟือย: http://jsfiddle.net/dPixie/byB9d/3/ ... ... ถึงแม้ว่ารุ่นสี่ขนาดใหญ่จะค่อนข้างหวาน

ข่าวดีสำหรับทุกคน!

ด้วยความก้าวหน้าของ HTML5 และ CSS3 ทำให้ตอนนี้เป็นไปได้อย่างน้อยสำหรับเบราว์เซอร์สมัยใหม่ hackish เล็กน้อยการดำเนินการที่ฉันมาด้วยสามารถพบได้ที่นี่: http://jsfiddle.net/dPixie/byB9d/3/ ฉันได้ทำการทดสอบใน FX 25, Chrome 31 และ IE 10 ...

HTML ที่เกี่ยวข้อง (แทรกประเภทเอกสาร HTML5 ที่ด้านบนของเอกสารของคุณ):

html,
body {
  margin: 0;
  padding: 0;
  height: 100%;
}

section {
  position: relative;
  border: 1px solid #000;
  padding-top: 37px;
  background: #500;
}

section.positioned {
  position: absolute;
  top: 100px;
  left: 100px;
  width: 800px;
  box-shadow: 0 0 15px #333;
}

.container {
  overflow-y: auto;
  height: 200px;
}

table {
  border-spacing: 0;
  width: 100%;
}

td+td {
  border-left: 1px solid #eee;
}

td,
th {
  border-bottom: 1px solid #eee;
  background: #ddd;
  color: #000;
  padding: 10px 25px;
}

th {
  height: 0;
  line-height: 0;
  padding-top: 0;
  padding-bottom: 0;
  color: transparent;
  border: none;
  white-space: nowrap;
}

th div {
  position: absolute;
  background: transparent;
  color: #fff;
  padding: 9px 25px;
  top: 0;
  margin-left: -25px;
  line-height: normal;
  border-left: 1px solid #800;
}

th:first-child div {
  border: none;
}
<section class="positioned">
  <div class="container">
    <table>
      <thead>
        <tr class="header">
          <th>
            Table attribute name
            <div>Table attribute name</div>
          </th>
          <th>
            Value
            <div>Value</div>
          </th>
          <th>
            Description
            <div>Description</div>
          </th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>align</td>
          <td>left, center, right</td>
          <td>Not supported in HTML5. Deprecated in HTML 4.01. Specifies the alignment of a table according to surrounding text</td>
        </tr>
        <tr>
          <td>bgcolor</td>
          <td>rgb(x,x,x), #xxxxxx, colorname</td>
          <td>Not supported in HTML5. Deprecated in HTML 4.01. Specifies the background color for a table</td>
        </tr>
        <tr>
          <td>border</td>
          <td>1,""</td>
          <td>Specifies whether the table cells should have borders or not</td>
        </tr>
        <tr>
          <td>cellpadding</td>
          <td>pixels</td>
          <td>Not supported in HTML5. Specifies the space between the cell wall and the cell content</td>
        </tr>
        <tr>
          <td>cellspacing</td>
          <td>pixels</td>
          <td>Not supported in HTML5. Specifies the space between cells</td>
        </tr>
        <tr>
          <td>frame</td>
          <td>void, above, below, hsides, lhs, rhs, vsides, box, border</td>
          <td>Not supported in HTML5. Specifies which parts of the outside borders that should be visible</td>
        </tr>
        <tr>
          <td>rules</td>
          <td>none, groups, rows, cols, all</td>
          <td>Not supported in HTML5. Specifies which parts of the inside borders that should be visible</td>
        </tr>
        <tr>
          <td>summary</td>
          <td>text</td>
          <td>Not supported in HTML5. Specifies a summary of the content of a table</td>
        </tr>
        <tr>
          <td>width</td>
          <td>pixels, %</td>
          <td>Not supported in HTML5. Specifies the width of a table</td>
        </tr>
      </tbody>
    </table>
  </div>
</section>

แต่อย่างไร!

เพียงทำให้คุณมีส่วนหัวของตารางซึ่งคุณสามารถซ่อนได้ด้วยการทำให้สูงถึง 0px ที่มี div ที่ใช้เป็นส่วนหัวคงที่ คอนเทนเนอร์ของตารางออกจากห้องเพียงพอที่ด้านบนเพื่ออนุญาตให้ส่วนหัวในตำแหน่งที่แน่นอนและตารางที่มีแถบเลื่อนปรากฏขึ้นตามที่คุณคาดไว้

รหัสด้านบนใช้คลาสที่วางตำแหน่งเพื่อวางตำแหน่งตารางอย่างแน่นอน (ฉันใช้มันในกล่องโต้ตอบสไตล์ป๊อปอัพ) แต่คุณสามารถใช้มันในการไหลของเอกสารได้เช่นกันโดยการลบpositionedคลาสออกจากภาชนะ

แต่ ...

มันไม่สมบูรณ์แบบ Firefox ปฏิเสธที่จะทำให้แถวส่วนหัว 0px (อย่างน้อยฉันไม่พบวิธีใด ๆ ) แต่หัวชนฝาเก็บไว้อย่างน้อย 4px ... มันไม่ใช่ปัญหาใหญ่ แต่ขึ้นอยู่กับสไตล์ของคุณมันจะยุ่งกับเส้นขอบของคุณ ฯลฯ

ตารางนี้ยังใช้วิธีการแบบคอลัมน์ faux ซึ่งใช้สีพื้นหลังของคอนเทนเนอร์เป็นพื้นหลังสำหรับ div ส่วนหัวที่โปร่งใส

สรุป

โดยรวมแล้วอาจมีปัญหาในการจัดแต่งทรงผมโดยขึ้นอยู่กับความต้องการของคุณ อาจมีปัญหากับการคำนวณฉันยังไม่ได้ตรวจสอบในเบราว์เซอร์ที่หลากหลาย (โปรดแสดงความคิดเห็นกับประสบการณ์ของคุณถ้าคุณลอง) แต่ฉันไม่พบอะไรอย่างนั้นฉันคิดว่ามันคุ้มค่าที่จะโพสต์ อย่างไรก็ตาม ...


หากคุณลดขนาดความกว้างของหน้าต่างจนกระทั่งการเลื่อนในแนวนอนเริ่มขึ้นหัวกระดาษจะไม่เลื่อนตามแนวนอนกับร่างกาย ยี้
dlaliberte

@dlaliberte - ดีเนื่องจากส่วนหัวและตารางเป็นสององค์ประกอบที่แตกต่างกันคุณสามารถ ofc เข้าสู่ความแปลก แต่ตัวอย่างของฉันไม่อนุญาตให้มีการล้นในคอลัมน์ตารางและส่วนหัวมักจะควบคุมได้ง่ายกว่าเนื้อหาตาราง ที่กล่าวว่าหากคุณทำให้ส่วนหัว "ล้น" หากจะยื่นออกมาทางด้านขวาของตารางและดูแตกอย่างรุนแรง คุณสามารถแก้ไขได้โดยการตั้งค่าความกว้างขั้นต่ำบนโต๊ะบังคับให้ล้นหน้าเว็บเช่นกัน ... แต่มันเป็นแฮ็คดังนั้นมันจะไม่สมบูรณ์แบบ ...
Jonas Schubert Erlandsson

1
น่าจะชี้ให้เห็นว่าสิ่งนี้ต้องการการออกแบบที่สามารถระบุตารางความสูงคงที่ได้
Cheekysoft

1
@Cheekysoft - ไม่เนื้อหาในตารางและแถวสามารถไหลได้อย่างอิสระ ในตัวอย่าง<section>องค์ประกอบของคอนเทนเนอร์ต้องมีความสูงที่ จำกัด เท่านั้นเพื่อบังคับให้โอเวอร์โฟลว์และแสดงการเลื่อน เลย์เอาต์ใด ๆ ที่จะทำให้คอนเทนเนอร์ล้นสามารถใช้งานได้ หากคุณพบกรณีที่ไม่ได้โปรดโพสต์ลิงค์ไปที่ซอ
Jonas Schubert Erlandsson

ค่าฮาร์ดโค้ดpadding-topยังหมายความว่าหากข้อความส่วนหัวของตารางอยู่ในมากกว่าหนึ่งบรรทัดข้อความนั้นจะปรากฏที่ด้านบนของเซลล์ตาราง สงสารเพราะมันใช้งานได้เหมือนมีเสน่ห์เกือบตลอดเวลา เคล็ดลับที่ดีจริงๆที่มีdivในthที่จะได้รับแก้ไขปัญหาคอลัมน์ปรับขนาดโซลูชั่นอื่น ๆ ส่วนใหญ่จะมี
Bernhard Hofmann

19

ความพยายามทั้งหมดเพื่อแก้ไขปัญหานี้จากนอกข้อกำหนด CSS เป็นเงาสีซีดจางของสิ่งที่เราต้องการ: การจัดส่งตามสัญญาโดยนัยของ THEAD

ปัญหาส่วนหัวแช่แข็งสำหรับตารางนี้เป็นแผลเปิดใน HTML / CSS เป็นเวลานาน

ในโลกที่สมบูรณ์แบบนั้นจะมีทางออก CSS บริสุทธิ์สำหรับปัญหานี้ โชคไม่ดีที่ดูเหมือนจะไม่เป็นคนดีในสถานที่

การอภิปรายมาตรฐานที่เกี่ยวข้องในหัวข้อนี้รวมถึง:

อัปเดต : Firefox จัดส่งเป็นposition:stickyเวอร์ชั่น 32 ทุกคนชนะ!


มันคงจะดีถ้ามีคอลัมน์จิ้งจอกเหมือนกัน
Csaba Toth

4
เรื่อง Firefox และตำแหน่ง: ไม่สามารถใช้งานได้กับส่วนหัวของตาราง: bugzilla.mozilla.org/show_bug.cgi?id=925259#c8 ... แพทช์สำหรับข้อผิดพลาดนั้นระบุอย่างชัดเจนว่า: "เราไม่สนับสนุนการวางตำแหน่งแบบสัมพัทธ์ ขององค์ประกอบตารางด้านในดังนั้นเราจึงแยกองค์ประกอบเหล่านั้นออกจากตำแหน่งที่เหนียวเช่นกัน "
Jonas Schubert Erlandsson

2
วิธีนี้ใช้ได้กับทุกเบราว์เซอร์ในขณะนี้: thead th { position: sticky; top: 0; }. เราสามารถอัปเดตคำตอบนี้เพื่อระบุสิ่งนี้ได้อย่างชัดเจนหรือไม่?
Daniel Waltrip

1
@DanielWaltrip เบราว์เซอร์ทั้งหมดหรือไม่ stackoverflow.com/a/37646284/3640407ยังคงมี MSIEs มากกว่า Edges อยู่
edc65

จุดยุติธรรม รองรับ 86% ของผู้ใช้เว็บทั่วโลกตามcaniuse.com/#search=position%3Asticky
Daniel Waltrip

14

นี่คือปลั๊กอิน jQuery สำหรับส่วนหัวของตารางคงที่ จะช่วยให้หน้าทั้งหมดเพื่อเลื่อนการแช่แข็งส่วนหัวเมื่อถึงด้านบน มันทำงานได้ดีกับตารางTwitter Bootstrap

ที่เก็บ GitHub: https://github.com/oma/table-fixed-header

มันไม่ได้เลื่อนเนื้อหาตารางเท่านั้น ดูเครื่องมืออื่น ๆ สำหรับสิ่งนั้นซึ่งเป็นหนึ่งในคำตอบอื่น ๆ เหล่านี้ คุณตัดสินใจเลือกสิ่งที่เหมาะกับกรณีของคุณที่สุด


1
Bummer - ลิงค์ตัวอย่างตาย "อุ๊ป! Denne siden ble ikke funnet ... " ต้องการให้รหัสวางที่นี่
JosephK

ใช่ ... ขอโทษด้วย นำลิงก์ออก โครงการจะไม่ได้รับการบำรุงรักษาอีกต่อไป
oma

ไม่ต้องกังวล - ฉันลองใช้วิธีแก้ไขปัญหาที่ทำไว้ล่วงหน้าเหล่านี้หลายแห่ง - ไม่มีใครทำงานกับตารางความกว้างแบบเฟล็กซ์ที่เกินความกว้างหน้าจอ ฉันเขียนวิธีแก้ปัญหาของตัวเอง
JosephK

9

โซลูชันส่วนใหญ่ที่โพสต์ที่นี่ต้องการ jQuery หากคุณกำลังมองหาโซลูชันอิสระของเฟรมเวิร์กลองใช้ Grid: http://www.matts411.com/post/grid/

มีการโฮสต์ใน Github ที่นี่: https://github.com/mmurph211/Grid

ไม่เพียง แต่รองรับส่วนหัวแบบคงที่เท่านั้น แต่ยังรองรับคอลัมน์และส่วนท้ายแบบคงที่เหนือสิ่งอื่นใด


นี่เป็นระเบียบจริงๆถ้ามันตรงกับความต้องการของคุณฉันเพิ่งเล่นกับมันวันนี้ น่าเสียดายที่มันเป็นตารางสี่เหลี่ยม (ตามความหมายจริง ๆ แล้ว) และไม่ใช่ตารางจริงที่ปรับความสูงแถวตามเนื้อหา และสไตล์ของแต่ละแถวนั้นดูลำบาก ฉันไม่สามารถสร้างตารางลายทางม้าลายได้ แต่ไม่ได้พยายามอย่างหนักเพราะความต้องการของฉันซับซ้อนกว่าจริง ๆ อย่างไรก็ตามงานที่ดี
mplwork

1
เฮ้ฉันรู้จักคุณ! เราดูเหมือนจะเขียนอึที่คล้ายกันมาก ( github.com/mkoryak/floatThead ) - Misha
mkoryak

9

คุณสมบัติ CSS position: stickyมีการสนับสนุนที่ยอดเยี่ยมในเบราว์เซอร์ที่ทันสมัยที่สุด (ฉันมีปัญหากับ Edge ดูด้านล่าง)

สิ่งนี้ช่วยให้เราสามารถแก้ปัญหาส่วนหัวคงที่ได้อย่างง่ายดาย:

thead th { position: sticky; top: 0; }

-webkit-stickyซาฟารีต้องการคำนำหน้าผู้ขาย:

สำหรับ Firefox ฉันต้องเพิ่มmin-height: 0องค์ประกอบผู้ปกครองหนึ่งรายการ ฉันลืมไปเลยว่าทำไมสิ่งนี้ถึงต้องการ

น่าเสียดายที่การใช้งาน Microsoft Edge นั้นดูเหมือนจะเป็นเพียงกึ่งงาน อย่างน้อยฉันก็มีเซลล์ตารางที่ริบหรี่และไม่ตรงแนวในการทดสอบของฉัน ตารางยังคงใช้งานได้ แต่มีปัญหาด้านความงามที่สำคัญ


ใช้position: sticky;กับโต๊ะภายใน div ที่มีoverflow: scroll;, หรือoverflow-x: scroll; overflow-y: scroll;ดูเหมือนจะเป็นทางออกที่ดีที่สุดและง่ายที่สุดสำหรับส่วนหัวและคอลัมน์คงที่ในเบราว์เซอร์สมัยใหม่ คำตอบนี้ต้องได้รับการโหวตไปด้านบน
Aberrant

มันง่าย แต่มีประสิทธิภาพ มันคือสิ่งที่ฉันกำลังมองหา ขอบคุณ
Catbuilts

6

ตารางเลื่อน CSS ที่บริสุทธิ์ยิ่งขึ้น

โซลูชัน CSS บริสุทธิ์ทั้งหมดที่ฉันเคยเห็นมาก่อน - ฉลาดแม้ว่าพวกเขาอาจจะ - ขาดระดับของการขัดเงาหรือเพียงแค่ไม่ทำงานในบางสถานการณ์ ดังนั้นฉันตัดสินใจที่จะสร้างของตัวเอง ...

คุณสมบัติ:

  • มันเป็น CSS ที่แท้จริงดังนั้นจึงไม่จำเป็นต้อง jQuery (หรือรหัส JavaScript ใด ๆ เลยสำหรับเรื่องนั้น)
  • คุณสามารถตั้งค่าความกว้างของตารางเป็นเปอร์เซ็นต์ (aka "ของเหลว") หรือค่าคงที่หรือให้เนื้อหากำหนดความกว้าง (aka "อัตโนมัติ")
  • ความกว้างของคอลัมน์อาจเป็นของเหลวคงที่หรืออัตโนมัติ
  • คอลัมน์จะไม่ตรงกับส่วนหัวเนื่องจากการเลื่อนในแนวนอน (ปัญหาที่เกิดขึ้นในโซลูชัน CSS-based อื่น ๆ ที่ฉันเคยเห็นซึ่งไม่ต้องใช้ความกว้างคงที่)
  • เข้ากันได้กับเบราว์เซอร์เดสก์ท็อปยอดนิยมทั้งหมดรวมถึง Internet Explorer กลับไปเป็นเวอร์ชัน 8
  • ลักษณะสะอาดขัดมัน; ไม่มีช่องว่างขนาด 1 พิกเซลหรือเส้นขอบไม่ตรง ดูเหมือนกันในเบราว์เซอร์ทั้งหมด

ต่อไปนี้เป็นปริศนาสองสามข้อที่แสดงตัวเลือกของไหลและความกว้างอัตโนมัติ:

  • ความกว้างและความสูงของของไหล (ปรับให้เหมาะกับขนาดหน้าจอ): jsFiddle (โปรดทราบว่าแถบเลื่อนจะปรากฏขึ้นเฉพาะเมื่อจำเป็นในการกำหนดค่านี้ดังนั้นคุณอาจต้องลดขนาดเฟรมเพื่อดู)

  • ความกว้างอัตโนมัติ, ความสูงคงที่ (ง่ายต่อการรวมเข้ากับเนื้อหาอื่น ๆ ): jsFiddle

การกำหนดค่าความกว้างอัตโนมัติความสูงคงที่อาจมีกรณีการใช้งานมากกว่าดังนั้นฉันจะโพสต์รหัสด้านล่าง

/* The following 'html' and 'body' rule sets are required only
   if using a % width or height*/

/*html {
  width: 100%;
  height: 100%;
}*/

body {
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0 20px 0 20px;
  text-align: center;
}
.scrollingtable {
  box-sizing: border-box;
  display: inline-block;
  vertical-align: middle;
  overflow: hidden;
  width: auto; /* If you want a fixed width, set it here, else set to auto */
  min-width: 0/*100%*/; /* If you want a % width, set it here, else set to 0 */
  height: 188px/*100%*/; /* Set table height here; can be fixed value or % */
  min-height: 0/*104px*/; /* If using % height, make this large enough to fit scrollbar arrows + caption + thead */
  font-family: Verdana, Tahoma, sans-serif;
  font-size: 16px;
  line-height: 20px;
  padding: 20px 0 20px 0; /* Need enough padding to make room for caption */
  text-align: left;
  color: black;
}
.scrollingtable * {box-sizing: border-box;}
.scrollingtable > div {
  position: relative;
  border-top: 1px solid black;
  height: 100%;
  padding-top: 20px; /* This determines column header height */
}
.scrollingtable > div:before {
  top: 0;
  background: cornflowerblue; /* Header row background color */
}
.scrollingtable > div:before,
.scrollingtable > div > div:after {
  content: "";
  position: absolute;
  z-index: -1;
  width: 100%;
  height: 100%;
  left: 0;
}
.scrollingtable > div > div {
  min-height: 0/*43px*/; /* If using % height, make this large
                            enough to fit scrollbar arrows */
  max-height: 100%;
  overflow: scroll/*auto*/; /* Set to auto if using fixed
                               or % width; else scroll */
  overflow-x: hidden;
  border: 1px solid black; /* Border around table body */
}
.scrollingtable > div > div:after {background: white;} /* Match page background color */
.scrollingtable > div > div > table {
  width: 100%;
  border-spacing: 0;
  margin-top: -20px; /* Inverse of column header height */
  /*margin-right: 17px;*/ /* Uncomment if using % width */
}
.scrollingtable > div > div > table > caption {
  position: absolute;
  top: -20px; /*inverse of caption height*/
  margin-top: -1px; /*inverse of border-width*/
  width: 100%;
  font-weight: bold;
  text-align: center;
}
.scrollingtable > div > div > table > * > tr > * {padding: 0;}
.scrollingtable > div > div > table > thead {
  vertical-align: bottom;
  white-space: nowrap;
  text-align: center;
}
.scrollingtable > div > div > table > thead > tr > * > div {
  display: inline-block;
  padding: 0 6px 0 6px; /*header cell padding*/
}
.scrollingtable > div > div > table > thead > tr > :first-child:before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  height: 20px; /*match column header height*/
  border-left: 1px solid black; /*leftmost header border*/
}
.scrollingtable > div > div > table > thead > tr > * > div[label]:before,
.scrollingtable > div > div > table > thead > tr > * > div > div:first-child,
.scrollingtable > div > div > table > thead > tr > * + :before {
  position: absolute;
  top: 0;
  white-space: pre-wrap;
  color: white; /*header row font color*/
}
.scrollingtable > div > div > table > thead > tr > * > div[label]:before,
.scrollingtable > div > div > table > thead > tr > * > div[label]:after {content: attr(label);}
.scrollingtable > div > div > table > thead > tr > * + :before {
  content: "";
  display: block;
  min-height: 20px; /* Match column header height */
  padding-top: 1px;
  border-left: 1px solid black; /* Borders between header cells */
}
.scrollingtable .scrollbarhead {float: right;}
.scrollingtable .scrollbarhead:before {
  position: absolute;
  width: 100px;
  top: -1px; /* Inverse border-width */
  background: white; /* Match page background color */
}
.scrollingtable > div > div > table > tbody > tr:after {
  content: "";
  display: table-cell;
  position: relative;
  padding: 0;
  border-top: 1px solid black;
  top: -1px; /* Inverse of border width */
}
.scrollingtable > div > div > table > tbody {vertical-align: top;}
.scrollingtable > div > div > table > tbody > tr {background: white;}
.scrollingtable > div > div > table > tbody > tr > * {
  border-bottom: 1px solid black;
  padding: 0 6px 0 6px;
  height: 20px; /* Match column header height */
}
.scrollingtable > div > div > table > tbody:last-of-type > tr:last-child > * {border-bottom: none;}
.scrollingtable > div > div > table > tbody > tr:nth-child(even) {background: gainsboro;} /* Alternate row color */
.scrollingtable > div > div > table > tbody > tr > * + * {border-left: 1px solid black;} /* Borders between body cells */
<div class="scrollingtable">
  <div>
    <div>
      <table>
        <caption>Top Caption</caption>
        <thead>
          <tr>
            <th><div label="Column 1"/></th>
            <th><div label="Column 2"/></th>
            <th><div label="Column 3"/></th>
            <th>
              <!-- More versatile way of doing column label; requires two identical copies of label -->
              <div><div>Column 4</div><div>Column 4</div></div>
            </th>
            <th class="scrollbarhead"/> <!-- ALWAYS ADD THIS EXTRA CELL AT END OF HEADER ROW -->
          </tr>
        </thead>
        <tbody>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
        </tbody>
      </table>
    </div>
    Faux bottom caption
  </div>
</div>

<!--[if lte IE 9]><style>.scrollingtable > div > div > table {margin-right: 17px;}</style><![endif]-->

วิธีที่ฉันใช้ในการตรึงแถวส่วนหัวนั้นคล้ายกับ d-Pixie's ดังนั้นโปรดอ้างอิงคำอธิบายของโพสต์ของเขา มีข้อบกพร่องและข้อ จำกัด บางอย่างเกี่ยวกับเทคนิคที่สามารถแก้ไขได้ด้วยกอง CSS เพิ่มเติมและคอนเทนเนอร์ div เพิ่มเติมหรือสองเท่านั้น


คำตอบนี้เป็นวิธี underappreciated! ฉันใช้เวลาหลายวันพยายามหาวิธีแก้ปัญหาอื่น ๆ มาใช้กับเคสที่น่ารำคาญเป็นพิเศษ ทุกคนไม่สามารถอยู่ในแนวเดียวกันไม่ทางใดก็ทางหนึ่ง ในที่สุดมันก็ทำมัน! ตอนแรกดูเหมือนจะซับซ้อนเกินไป แต่เมื่อคุณได้รับมันแล้ว คุณสามารถลบบางสิ่งที่คุณไม่ต้องการในตอนท้ายเมื่อไม่ได้ใช้ความกว้างของของไหล ฯลฯ
Justin Sane

1
@JustinSane ดีใจที่คุณชอบ! ฉันเดาขาดจากการแข็งค่าเป็นเพราะความจริงที่ว่าหุ้นมันหน้าด้วยวิธีการแก้ปัญหาที่น่าตื่นตาตื่นใจ Maximilian Hils' หากคุณไม่ได้ต่อต้านการใช้ JS เพียงเล็กน้อยคุณควรลองใช้ดู
DoctorDestructo

ประณามนั่นเป็นทางออกที่สมบูรณ์แบบเกือบแน่นอน ฉันใช้ jQuery อยู่แล้วพยายามทำให้มันทำงานก่อนที่ฉันจะพบคุณ (ผ่านความคิดเห็นของคุณไปยังคำถามอื่น) ไม่ได้นึกถึงผู้ฟังสโครลและแปล ... อืมพวกเขาบอกว่าต้องใช้อัจฉริยะเพื่อหาคำตอบง่ายๆ .. ;) ฉันทำโปรเจ็กต์เสร็จและทำงานได้อย่างสมบูรณ์แบบโดยไม่มี js แต่ฉันจะเก็บไว้ในนี้ ใจสำหรับอนาคต ถึงกระนั้นก็ยังปิดบังคุณไว้เพราะความเจ๋ง!
Justin Sane

ปัญหาเล็ก ๆ แต่ถ้าคุณใช้สีของระบบที่แตกต่างกันคุณจะเห็นสีของข้อความไม่ได้ถูกตั้งค่าสำหรับสิ่งใดยกเว้นส่วนหัว แต่พื้นหลังของตารางมีสีพื้นหลังที่ชัดเจน ฉันมีข้อความสีเหลืองบนพื้นหลังสีขาวและสีเทาสำหรับตารางนี้
Matt Arnold

1
@MattArnold แก้ไขแล้ว ขอบคุณสำหรับเคล็ดลับ!
DoctorDestructo

5

ปลั๊กอิน jQuery ง่าย ๆ

นี่คือรูปแบบที่แตกต่างกันในโซลูชันของ Mahes คุณสามารถเรียกมันว่าชอบ$('table#foo').scrollableTable();

ความคิดคือ:

  • แยกtheadและtbodyเป็นtableองค์ประกอบแยกต่างหาก
  • ทำให้ความกว้างของเซลล์ตรงกันอีกครั้ง
  • ห่อที่สองtableในdiv.scrollable
  • ใช้ CSS เพื่อทำให้div.scrollableเลื่อนได้จริง

CSS อาจเป็น:

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

คำเตือน

  • เห็นได้ชัดว่าการแยกตารางเหล่านี้ทำให้มาร์กอัปความหมายน้อยลง ฉันไม่แน่ใจว่าสิ่งนี้มีผลกระทบกับการเข้าถึงได้อย่างไร
  • ปลั๊กอินนี้ไม่ได้มีส่วนท้ายส่วนหัวหลายส่วน ฯลฯ
  • ฉันทดสอบเฉพาะใน Chrome รุ่น 20 เท่านั้น

ที่กล่าวว่ามันทำงานได้ตามวัตถุประสงค์ของฉันและคุณมีอิสระที่จะใช้และแก้ไข

นี่คือปลั๊กอิน:

jQuery.fn.scrollableTable = function () {
  var $newTable, $oldTable, $scrollableDiv, originalWidths;
  $oldTable = $(this);

  // Once the tables are split, their cell widths may change. 
  // Grab these so we can make the two tables match again.
  originalWidths = $oldTable.find('tr:first td').map(function() {
    return $(this).width();
  });

  $newTable = $oldTable.clone();
  $oldTable.find('tbody').remove();
  $newTable.find('thead').remove();

  $.each([$oldTable, $newTable], function(index, $table) {
    $table.find('tr:first td').each(function(i) {
      $(this).width(originalWidths[i]);
    });
  });

  $scrollableDiv = $('<div/>').addClass('scrollable');
  $newTable.insertAfter($oldTable).wrap($scrollableDiv);
};

1
สคริปต์ที่ดีอันนี้ทำงานได้ดีที่สุดในสภาพแวดล้อมของฉัน ฉันขยายสคริปต์ของคุณด้วยการสนับสนุนส่วนท้ายคงที่ตรวจสอบโพสต์ของฉันด้านล่าง
gitaarik

4

:)

วิธีแก้ปัญหา HTML / CSS ที่ไม่สะอาด แต่บริสุทธิ์

table {
    overflow-x:scroll;
}

tbody {
    max-height: /*your desired max height*/
    overflow-y:scroll;
    display:block;
}

อัปเดตสำหรับตัวอย่าง IE8 + JSFiddle


2
ทางออกที่ดีเพียงพูดถึงว่าเซลล์เหล่านี้ลอยและดังนั้นตามเนื้อหาสามารถมีความสูงที่แตกต่างกันก็จะมองเห็นได้ถ้าคุณกำหนดเส้นขอบ: jsfiddle.net/ZdeEH/15
Stano

3

รองรับส่วนท้ายคงที่

ฉันขยายฟังก์ชั่นของนาธานเพื่อรองรับส่วนท้ายคงที่และความสูงสูงสุด นอกจากนี้ฟังก์ชันจะตั้งค่า CSS เองและคุณจะต้องรองรับความกว้างเท่านั้น

การใช้งาน:

ความสูงคงที่:

$('table').scrollableTable({ height: 100 });

ความสูงสูงสุด (หากเบราว์เซอร์รองรับตัวเลือก CSS 'ความสูงสูงสุด'):

$('table').scrollableTable({ maxHeight: 100 });

สคริปต์:

jQuery.fn.scrollableTable = function(options) {

    var $originalTable, $headTable, $bodyTable, $footTable, $scrollableDiv, originalWidths;

    // Prepare the separate parts of the table
    $originalTable = $(this);
    $headTable = $originalTable.clone();

    $headTable.find('tbody').remove();
    $headTable.find('tfoot').remove();

    $bodyTable = $originalTable.clone();
    $bodyTable.find('thead').remove();
    $bodyTable.find('tfoot').remove();

    $footTable = $originalTable.clone();
    $footTable.find('thead').remove();
    $footTable.find('tbody').remove();

    // Grab the original column widths and set them in the separate tables
    originalWidths = $originalTable.find('tr:first td').map(function() {
        return $(this).width();
    });

    $.each([$headTable, $bodyTable, $footTable], function(index, $table) {
        $table.find('tr:first td').each(function(i) {
            $(this).width(originalWidths[i]);
        });
    });

    // The div that makes the body table scroll
    $scrollableDiv = $('<div/>').css({
        'overflow-y': 'scroll'
    });

    if(options.height) {
        $scrollableDiv.css({'height': options.height});
    }
    else if(options.maxHeight) {
        $scrollableDiv.css({'max-height': options.maxHeight});
    }

    // Add the new separate tables and remove the original one
    $headTable.insertAfter($originalTable);
    $bodyTable.insertAfter($headTable);
    $footTable.insertAfter($bodyTable);
    $bodyTable.wrap($scrollableDiv);
    $originalTable.remove();
};

3

ยังไงก็เถอะฉันPosition:Stickyทำงานได้ดีในกรณีของฉัน:

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

th{
    position: sticky;
    top: 0px;
    border: 1px solid black;
    background: #ff5722;
    color: #f5f5f5;
    font-weight: 600;
}
td{
    background: #d3d3d3;
    border: 1px solid black;
    color: #f5f5f5;
    font-weight: 600;
}

div{
  height: 150px
  overflow: auto;
  width: 100%
}
<div>
    <table>
        <thead>
            <tr>
                <th>header 1</th>
                <th>header 2</th>
                <th>header 3</th>
                <th>header 4</th>
                <th>header 5</th>
                <th>header 6</th>
                <th>header 7</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
        </tbody>
    </table>
</div>


1
นี่คือทางออกที่สะอาดที่สุดที่ฉันเคยเห็น caniuseแสดงให้เห็นว่าตั้งแต่วันที่ 5/2/2020 ตำแหน่งที่ไม่ได้ติดตั้งไว้ล่วงหน้า: เหนียวมีการสนับสนุนทั่วโลก 90.06% ดังนั้นวิธีนี้ใช้งานได้ดีกับเบราว์เซอร์สมัยใหม่ทั้งหมด
AlienKevin

2

สอง divs หนึ่งสำหรับส่วนหัวหนึ่งสำหรับข้อมูล ทำให้ data div scrollable และใช้ JavaScript เพื่อกำหนดความกว้างของคอลัมน์ในส่วนหัวให้เหมือนกับความกว้างของข้อมูล ฉันคิดว่าความกว้างคอลัมน์ข้อมูลจำเป็นต้องได้รับการแก้ไขมากกว่าเป็นแบบไดนามิก


3
หากคุณสนใจเกี่ยวกับการเข้าถึงนี่เป็นความล้มเหลว
epascarello

1
กำลังเข้าถึงได้บางทีเราสามารถแทนที่การใช้ div ด้วยสไตล์ใน <thead> และ <tbody> ได้หรือไม่?
Cheekysoft

1

ฉันรู้ว่าคำถามอนุญาต JavaScript แต่นี่เป็นโซลูชัน CSS ที่ฉันใช้จริงซึ่งช่วยให้ตารางขยายได้ในแนวนอน มีการทดสอบกับ Internet Explorer 10 และเบราว์เซอร์ Chrome และ Firefox ล่าสุด ลิงก์ไปยัง jsFiddle อยู่ด้านล่าง

HTML:

Putting some text here to differentiate between the header
aligning with the top of the screen and the header aligning
with the top of one of its ancestor containers.

<div id="positioning-container">
<div id="scroll-container">
    <table>
        <colgroup>
            <col class="col1"></col>
            <col class="col2"></col>
        </colgroup>
        <thead>
            <th class="header-col1"><div>Header 1</div></th>
            <th class="header-col2"><div>Header 2</div></th>
        </thead>
        <tbody>
            <tr><td>Cell 1.1</td><td>Cell 1.2</td></tr>
            <tr><td>Cell 2.1</td><td>Cell 2.2</td></tr>
            <tr><td>Cell 3.1</td><td>Cell 3.2</td></tr>
            <tr><td>Cell 4.1</td><td>Cell 4.2</td></tr>
            <tr><td>Cell 5.1</td><td>Cell 5.2</td></tr>
            <tr><td>Cell 6.1</td><td>Cell 6.2</td></tr>
            <tr><td>Cell 7.1</td><td>Cell 7.2</td></tr>

        </tbody>
    </table>
</div>
</div>

และ CSS:

table{
    border-collapse: collapse;
    table-layout: fixed;
    width: 100%;
}
/* Not required, just helps with alignment for this example */
td, th{
    padding: 0;
    margin: 0;
}

tbody{
    background-color: #ddf;
}

thead {
    /* Keeps the header in place. Don't forget top: 0 */
    position: absolute;
    top: 0;
    background-color: #ddd;

    /* The 17px is to adjust for the scrollbar width.
     * This is a new css value that makes this pure
     * css example possible */
    width: calc(100% - 17px);
    height: 20px;
}

/* Positioning container. Required to position the
 * header since the header uses position:absolute
 * (otherwise it would position at the top of the screen) */
#positioning-container{
    position: relative;
}

/* A container to set the scroll-bar and
 * includes padding to move the table contents
 * down below the header (padding = header height) */
#scroll-container{
    overflow-y: auto;
    padding-top: 20px;
    height: 100px;
}
.header-col1{
    background-color: red;
}

/* Fixed-width header columns need a div to set their width */
.header-col1 div{
    width: 100px;
}

/* Expandable columns need a width set on the th tag */
.header-col2{
    width: 100%;
}
.col1 {
    width: 100px;
}
.col2{
    width: 100%;
}

http://jsfiddle.net/HNHRv/3/


1

สำหรับผู้ที่ลองใช้โซลูชันที่ดีของ Maximilian Hils และไม่ประสบความสำเร็จในการทำงานกับ Internet Explorer ฉันมีปัญหาเดียวกัน (Internet Explorer 11) และพบว่าปัญหาคืออะไร

ใน Internet Explorer 11 สไตล์การแปลง (อย่างน้อยก็มีแปล) <THEAD>ไม่ทำงานบน ฉันแก้ไขมันโดยใช้สไตล์แทนการ<TH>วนซ้ำ ที่ได้ผล รหัส JavaScript ของฉันดูเหมือนว่านี้:

document.getElementById('pnlGridWrap').addEventListener("scroll", function () {
  var translate = "translate(0," + this.scrollTop + "px)";
  var myElements = this.querySelectorAll("th");
  for (var i = 0; i < myElements.length; i++) {
    myElements[i].style.transform=translate;
  }
});

ในกรณีของฉันตารางเป็น GridView ใน ASP.NET ครั้งแรกที่ฉันคิดว่ามันเป็นเพราะมันไม่มี<THEAD>แต่แม้เมื่อฉันบังคับให้มีมันก็ไม่ได้ทำงาน จากนั้นฉันก็พบสิ่งที่ฉันเขียนด้านบน

มันเป็นทางออกที่ดีและเรียบง่าย ใน Chrome มันสมบูรณ์แบบบน Firefox ค่อนข้างกระตุกและบน Internet Explorer ยิ่งกระตุกมากขึ้น แต่โดยรวมแล้วเป็นทางออกที่ดี


0

ฉันหวังว่าฉันจะได้พบโซลูชันของ @ Mark ก่อนหน้านี้ แต่ฉันไปและเขียนของตัวเองก่อนที่ฉันจะเห็นคำถาม SO นี้ ...

Mine เป็นปลั๊กอิน jQuery ที่มีน้ำหนักเบามากซึ่งสนับสนุนส่วนหัวคงที่, ส่วนท้าย, การขยายคอลัมน์ (colspan), การปรับขนาด, การเลื่อนในแนวนอนและจำนวนแถวที่ไม่จำเป็นที่จะแสดงก่อนเริ่มการเลื่อน

jQuery.scrollTableBody (GitHub)

ตราบใดที่คุณมีตารางที่มีความเหมาะสม<thead>, <tbody>และ (อุปกรณ์เสริม) <tfoot>ทั้งหมดที่คุณต้องทำคือ:

$('table').scrollTableBody();

0

ฉันพบวิธีแก้ปัญหานี้ - ย้ายแถวส่วนหัวในตารางด้านบนตารางด้วยข้อมูล:

<html>
<head>
	<title>Fixed header</title>
	<style>
		table td {width:75px;}
	</style>
</head>

<body>
<div style="height:auto; width:350px; overflow:auto">
<table border="1">
<tr>
	<td>header 1</td>
	<td>header 2</td>
	<td>header 3</td>
</tr>
</table>
</div>

<div style="height:50px; width:350px; overflow:auto">
<table border="1">
<tr>
	<td>row 1 col 1</td>
	<td>row 1 col 2</td>
	<td>row 1 col 3</td>		
</tr>
<tr>
	<td>row 2 col 1</td>
	<td>row 2 col 2</td>
	<td>row 2 col 3</td>		
</tr>
<tr>
	<td>row 3 col 1</td>
	<td>row 3 col 2</td>
	<td>row 3 col 3</td>		
</tr>
<tr>
	<td>row 4 col 1</td>
	<td>row 4 col 2</td>
	<td>row 4 col 3</td>		
</tr>
<tr>
	<td>row 5 col 1</td>
	<td>row 5 col 2</td>
	<td>row 5 col 3</td>		
</tr>
<tr>
	<td>row 6 col 1</td>
	<td>row 6 col 2</td>
	<td>row 6 col 3</td>		
</tr>
</table>
</div>


</body>
</html>


ใช้ได้กับตารางเล็ก ๆ แต่ถ้าคุณมีการเลื่อนในแนวนอนวิธีนี้จะไม่ทำงาน
crh225

มันจะไม่ทำงานอย่างถูกต้องเนื่องจากคอลัมน์ตารางจะไม่จัดตำแหน่ง ที่นี่คุณกำลังบังคับให้มีความกว้างสำหรับ td แต่เราต้องไม่ทำ ...
Ziggler

0

โดยการใช้ปลั๊กอิน jQuery StickyTableHeadersกับตารางส่วนหัวคอลัมน์จะติดกับด้านบนของวิวพอร์ตขณะที่คุณเลื่อนลง

ตัวอย่าง:

$(function () {
    $("table").stickyTableHeaders();
});

/*! Copyright (c) 2011 by Jonas Mosbech - https://github.com/jmosbech/StickyTableHeaders
	MIT license info: https://github.com/jmosbech/StickyTableHeaders/blob/master/license.txt */

;
(function ($, window, undefined) {
    'use strict';

    var name = 'stickyTableHeaders',
        id = 0,
        defaults = {
            fixedOffset: 0,
            leftOffset: 0,
            marginTop: 0,
            scrollableArea: window
        };

    function Plugin(el, options) {
        // To avoid scope issues, use 'base' instead of 'this'
        // to reference this class from internal events and functions.
        var base = this;

        // Access to jQuery and DOM versions of element
        base.$el = $(el);
        base.el = el;
        base.id = id++;
        base.$window = $(window);
        base.$document = $(document);

        // Listen for destroyed, call teardown
        base.$el.bind('destroyed',
        $.proxy(base.teardown, base));

        // Cache DOM refs for performance reasons
        base.$clonedHeader = null;
        base.$originalHeader = null;

        // Keep track of state
        base.isSticky = false;
        base.hasBeenSticky = false;
        base.leftOffset = null;
        base.topOffset = null;

        base.init = function () {
            base.$el.each(function () {
                var $this = $(this);

                // remove padding on <table> to fix issue #7
                $this.css('padding', 0);

                base.$originalHeader = $('thead:first', this);
                base.$clonedHeader = base.$originalHeader.clone();
                $this.trigger('clonedHeader.' + name, [base.$clonedHeader]);

                base.$clonedHeader.addClass('tableFloatingHeader');
                base.$clonedHeader.css('display', 'none');

                base.$originalHeader.addClass('tableFloatingHeaderOriginal');

                base.$originalHeader.after(base.$clonedHeader);

                base.$printStyle = $('<style type="text/css" media="print">' +
                    '.tableFloatingHeader{display:none !important;}' +
                    '.tableFloatingHeaderOriginal{position:static !important;}' +
                    '</style>');
                $('head').append(base.$printStyle);
            });

            base.setOptions(options);
            base.updateWidth();
            base.toggleHeaders();
            base.bind();
        };

        base.destroy = function () {
            base.$el.unbind('destroyed', base.teardown);
            base.teardown();
        };

        base.teardown = function () {
            if (base.isSticky) {
                base.$originalHeader.css('position', 'static');
            }
            $.removeData(base.el, 'plugin_' + name);
            base.unbind();

            base.$clonedHeader.remove();
            base.$originalHeader.removeClass('tableFloatingHeaderOriginal');
            base.$originalHeader.css('visibility', 'visible');
            base.$printStyle.remove();

            base.el = null;
            base.$el = null;
        };

        base.bind = function () {
            base.$scrollableArea.on('scroll.' + name, base.toggleHeaders);
            if (!base.isWindowScrolling) {
                base.$window.on('scroll.' + name + base.id, base.setPositionValues);
                base.$window.on('resize.' + name + base.id, base.toggleHeaders);
            }
            base.$scrollableArea.on('resize.' + name, base.toggleHeaders);
            base.$scrollableArea.on('resize.' + name, base.updateWidth);
        };

        base.unbind = function () {
            // unbind window events by specifying handle so we don't remove too much
            base.$scrollableArea.off('.' + name, base.toggleHeaders);
            if (!base.isWindowScrolling) {
                base.$window.off('.' + name + base.id, base.setPositionValues);
                base.$window.off('.' + name + base.id, base.toggleHeaders);
            }
            base.$scrollableArea.off('.' + name, base.updateWidth);
        };

        base.toggleHeaders = function () {
            if (base.$el) {
                base.$el.each(function () {
                    var $this = $(this),
                        newLeft,
                        newTopOffset = base.isWindowScrolling ? (
                        isNaN(base.options.fixedOffset) ? base.options.fixedOffset.outerHeight() : base.options.fixedOffset) : base.$scrollableArea.offset().top + (!isNaN(base.options.fixedOffset) ? base.options.fixedOffset : 0),
                        offset = $this.offset(),

                        scrollTop = base.$scrollableArea.scrollTop() + newTopOffset,
                        scrollLeft = base.$scrollableArea.scrollLeft(),

                        scrolledPastTop = base.isWindowScrolling ? scrollTop > offset.top : newTopOffset > offset.top,
                        notScrolledPastBottom = (base.isWindowScrolling ? scrollTop : 0) < (offset.top + $this.height() - base.$clonedHeader.height() - (base.isWindowScrolling ? 0 : newTopOffset));

                    if (scrolledPastTop && notScrolledPastBottom) {
                        newLeft = offset.left - scrollLeft + base.options.leftOffset;
                        base.$originalHeader.css({
                            'position': 'fixed',
                                'margin-top': base.options.marginTop,
                                'left': newLeft,
                                'z-index': 3 // #18: opacity bug
                        });
                        base.leftOffset = newLeft;
                        base.topOffset = newTopOffset;
                        base.$clonedHeader.css('display', '');
                        if (!base.isSticky) {
                            base.isSticky = true;
                            // make sure the width is correct: the user might have resized the browser while in static mode
                            base.updateWidth();
                        }
                        base.setPositionValues();
                    } else if (base.isSticky) {
                        base.$originalHeader.css('position', 'static');
                        base.$clonedHeader.css('display', 'none');
                        base.isSticky = false;
                        base.resetWidth($('td,th', base.$clonedHeader), $('td,th', base.$originalHeader));
                    }
                });
            }
        };

        base.setPositionValues = function () {
            var winScrollTop = base.$window.scrollTop(),
                winScrollLeft = base.$window.scrollLeft();
            if (!base.isSticky || winScrollTop < 0 || winScrollTop + base.$window.height() > base.$document.height() || winScrollLeft < 0 || winScrollLeft + base.$window.width() > base.$document.width()) {
                return;
            }
            base.$originalHeader.css({
                'top': base.topOffset - (base.isWindowScrolling ? 0 : winScrollTop),
                    'left': base.leftOffset - (base.isWindowScrolling ? 0 : winScrollLeft)
            });
        };

        base.updateWidth = function () {
            if (!base.isSticky) {
                return;
            }
            // Copy cell widths from clone
            if (!base.$originalHeaderCells) {
                base.$originalHeaderCells = $('th,td', base.$originalHeader);
            }
            if (!base.$clonedHeaderCells) {
                base.$clonedHeaderCells = $('th,td', base.$clonedHeader);
            }
            var cellWidths = base.getWidth(base.$clonedHeaderCells);
            base.setWidth(cellWidths, base.$clonedHeaderCells, base.$originalHeaderCells);

            // Copy row width from whole table
            base.$originalHeader.css('width', base.$clonedHeader.width());
        };

        base.getWidth = function ($clonedHeaders) {
            var widths = [];
            $clonedHeaders.each(function (index) {
                var width, $this = $(this);

                if ($this.css('box-sizing') === 'border-box') {
                    width = $this[0].getBoundingClientRect().width; // #39: border-box bug
                } else {
                    var $origTh = $('th', base.$originalHeader);
                    if ($origTh.css('border-collapse') === 'collapse') {
                        if (window.getComputedStyle) {
                            width = parseFloat(window.getComputedStyle(this, null).width);
                        } else {
                            // ie8 only
                            var leftPadding = parseFloat($this.css('padding-left'));
                            var rightPadding = parseFloat($this.css('padding-right'));
                            // Needs more investigation - this is assuming constant border around this cell and it's neighbours.
                            var border = parseFloat($this.css('border-width'));
                            width = $this.outerWidth() - leftPadding - rightPadding - border;
                        }
                    } else {
                        width = $this.width();
                    }
                }

                widths[index] = width;
            });
            return widths;
        };

        base.setWidth = function (widths, $clonedHeaders, $origHeaders) {
            $clonedHeaders.each(function (index) {
                var width = widths[index];
                $origHeaders.eq(index).css({
                    'min-width': width,
                        'max-width': width
                });
            });
        };

        base.resetWidth = function ($clonedHeaders, $origHeaders) {
            $clonedHeaders.each(function (index) {
                var $this = $(this);
                $origHeaders.eq(index).css({
                    'min-width': $this.css('min-width'),
                        'max-width': $this.css('max-width')
                });
            });
        };

        base.setOptions = function (options) {
            base.options = $.extend({}, defaults, options);
            base.$scrollableArea = $(base.options.scrollableArea);
            base.isWindowScrolling = base.$scrollableArea[0] === window;
        };

        base.updateOptions = function (options) {
            base.setOptions(options);
            // scrollableArea might have changed
            base.unbind();
            base.bind();
            base.updateWidth();
            base.toggleHeaders();
        };

        // Run initializer
        base.init();
    }

    // A plugin wrapper around the constructor,
    // preventing against multiple instantiations
    $.fn[name] = function (options) {
        return this.each(function () {
            var instance = $.data(this, 'plugin_' + name);
            if (instance) {
                if (typeof options === 'string') {
                    instance[options].apply(instance);
                } else {
                    instance.updateOptions(options);
                }
            } else if (options !== 'destroy') {
                $.data(this, 'plugin_' + name, new Plugin(this, options));
            }
        });
    };

})(jQuery, window);
body {
    margin: 0 auto;
    padding: 0 20px;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 11px;
    color: #555;
}
table {
    border: 0;
    padding: 0;
    margin: 0 0 20px 0;
    border-collapse: collapse;
}
th {
    padding: 5px;
    /* NOTE: th padding must be set explicitly in order to support IE */
    text-align: right;
    font-weight:bold;
    line-height: 2em;
    color: #FFF;
    background-color: #555;
}
tbody td {
    padding: 10px;
    line-height: 18px;
    border-top: 1px solid #E0E0E0;
}
tbody tr:nth-child(2n) {
    background-color: #F7F7F7;
}
tbody tr:hover {
    background-color: #EEEEEE;
}
td {
    text-align: right;
}
td:first-child, th:first-child {
    text-align: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div style="width:3000px">some really really wide content goes here</div>
<table>
    <thead>
        <tr>
            <th colspan="9">Companies listed on NASDAQ OMX Copenhagen.</th>
        </tr>
        <tr>
            <th>Full name</th>
            <th>CCY</th>
            <th>Last</th>
            <th>+/-</th>
            <th>%</th>
            <th>Bid</th>
            <th>Ask</th>
            <th>Volume</th>
            <th>Turnover</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>A.P. Møller...</td>
            <td>DKK</td>
            <td>33,220.00</td>
            <td>760</td>
            <td>2.34</td>
            <td>33,140.00</td>
            <td>33,220.00</td>
            <td>594</td>
            <td>19,791,910</td>
        </tr>
        <tr>
            <td>A.P. Møller...</td>
            <td>DKK</td>
            <td>34,620.00</td>
            <td>640</td>
            <td>1.88</td>
            <td>34,620.00</td>
            <td>34,700.00</td>
            <td>9,954</td>
            <td>346,530,246</td>
        </tr>
        <tr>
            <td>Carlsberg A</td>
            <td>DKK</td>
            <td>380</td>
            <td>0</td>
            <td>0</td>
            <td>371</td>
            <td>391.5</td>
            <td>6</td>
            <td>2,280</td>
        </tr>
        <tr>
            <td>Carlsberg B</td>
            <td>DKK</td>
            <td>364.4</td>
            <td>8.6</td>
            <td>2.42</td>
            <td>363</td>
            <td>364.4</td>
            <td>636,267</td>
            <td>228,530,601</td>
        </tr>
        <tr>
            <td>Chr. Hansen...</td>
            <td>DKK</td>
            <td>114.5</td>
            <td>-1.6</td>
            <td>-1.38</td>
            <td>114.2</td>
            <td>114.5</td>
            <td>141,822</td>
            <td>16,311,454</td>
        </tr>
        <tr>
            <td>Coloplast B</td>
            <td>DKK</td>
            <td>809.5</td>
            <td>11</td>
            <td>1.38</td>
            <td>809</td>
            <td>809.5</td>
            <td>85,840</td>
            <td>69,363,301</td>
        </tr>
        <tr>
            <td>D/S Norden</td>
            <td>DKK</td>
            <td>155</td>
            <td>-1.5</td>
            <td>-0.96</td>
            <td>155</td>
            <td>155.1</td>
            <td>51,681</td>
            <td>8,037,225</td>
        </tr>
        <tr>
            <td>Danske Bank</td>
            <td>DKK</td>
            <td>69.05</td>
            <td>2.55</td>
            <td>3.83</td>
            <td>69.05</td>
            <td>69.2</td>
            <td>1,723,719</td>
            <td>115,348,068</td>
        </tr>
        <tr>
            <td>DSV</td>
            <td>DKK</td>
            <td>105.4</td>
            <td>0.2</td>
            <td>0.19</td>
            <td>105.2</td>
            <td>105.4</td>
            <td>674,873</td>
            <td>71,575,035</td>
        </tr>
        <tr>
            <td>FLSmidth &amp; Co.</td>
            <td>DKK</td>
            <td>295.8</td>
            <td>-1.8</td>
            <td>-0.6</td>
            <td>295.1</td>
            <td>295.8</td>
            <td>341,263</td>
            <td>100,301,032</td>
        </tr>
        <tr>
            <td>G4S plc</td>
            <td>DKK</td>
            <td>22.53</td>
            <td>0.05</td>
            <td>0.22</td>
            <td>22.53</td>
            <td>22.57</td>
            <td>190,920</td>
            <td>4,338,150</td>
        </tr>
        <tr>
            <td>Jyske Bank</td>
            <td>DKK</td>
            <td>144.2</td>
            <td>1.4</td>
            <td>0.98</td>
            <td>142.8</td>
            <td>144.2</td>
            <td>78,163</td>
            <td>11,104,874</td>
        </tr>
        <tr>
            <td>Københavns ...</td>
            <td>DKK</td>
            <td>1,580.00</td>
            <td>-12</td>
            <td>-0.75</td>
            <td>1,590.00</td>
            <td>1,620.00</td>
            <td>82</td>
            <td>131,110</td>
        </tr>
        <tr>
            <td>Lundbeck</td>
            <td>DKK</td>
            <td>103.4</td>
            <td>-2.5</td>
            <td>-2.36</td>
            <td>103.4</td>
            <td>103.8</td>
            <td>157,162</td>
            <td>16,462,282</td>
        </tr>
        <tr>
            <td>Nordea Bank</td>
            <td>DKK</td>
            <td>43.22</td>
            <td>-0.06</td>
            <td>-0.14</td>
            <td>43.22</td>
            <td>43.25</td>
            <td>167,520</td>
            <td>7,310,143</td>
        </tr>
        <tr>
            <td>Novo Nordisk B</td>
            <td>DKK</td>
            <td>552.5</td>
            <td>-3.5</td>
            <td>-0.63</td>
            <td>550.5</td>
            <td>552.5</td>
            <td>843,533</td>
            <td>463,962,375</td>
        </tr>
        <tr>
            <td>Novozymes B</td>
            <td>DKK</td>
            <td>805.5</td>
            <td>5.5</td>
            <td>0.69</td>
            <td>805</td>
            <td>805.5</td>
            <td>152,188</td>
            <td>121,746,199</td>
        </tr>
        <tr>
            <td>Pandora</td>
            <td>DKK</td>
            <td>39.04</td>
            <td>0.94</td>
            <td>2.47</td>
            <td>38.8</td>
            <td>39.04</td>
            <td>350,965</td>
            <td>13,611,838</td>
        </tr>
        <tr>
            <td>Rockwool In...</td>
            <td>DKK</td>
            <td>492</td>
            <td>0</td>
            <td>0</td>
            <td>482</td>
            <td>492</td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td>Rockwool In...</td>
            <td>DKK</td>
            <td>468</td>
            <td>12</td>
            <td>2.63</td>
            <td>465.2</td>
            <td>468</td>
            <td>9,885</td>
            <td>4,623,850</td>
        </tr>
        <tr>
            <td>Sydbank</td>
            <td>DKK</td>
            <td>95</td>
            <td>0.05</td>
            <td>0.05</td>
            <td>94.7</td>
            <td>95</td>
            <td>103,438</td>
            <td>9,802,899</td>
        </tr>
        <tr>
            <td>TDC</td>
            <td>DKK</td>
            <td>43.6</td>
            <td>0.13</td>
            <td>0.3</td>
            <td>43.5</td>
            <td>43.6</td>
            <td>845,110</td>
            <td>36,785,339</td>
        </tr>
        <tr>
            <td>Topdanmark</td>
            <td>DKK</td>
            <td>854</td>
            <td>13.5</td>
            <td>1.61</td>
            <td>854</td>
            <td>855</td>
            <td>38,679</td>
            <td>32,737,678</td>
        </tr>
        <tr>
            <td>Tryg</td>
            <td>DKK</td>
            <td>290.4</td>
            <td>0.3</td>
            <td>0.1</td>
            <td>290</td>
            <td>290.4</td>
            <td>94,587</td>
            <td>27,537,247</td>
        </tr>
        <tr>
            <td>Vestas Wind...</td>
            <td>DKK</td>
            <td>90.15</td>
            <td>-4.2</td>
            <td>-4.45</td>
            <td>90.1</td>
            <td>90.15</td>
            <td>1,317,313</td>
            <td>121,064,314</td>
        </tr>
        <tr>
            <td>William Dem...</td>
            <td>DKK</td>
            <td>417.6</td>
            <td>0.1</td>
            <td>0.02</td>
            <td>417</td>
            <td>417.6</td>
            <td>64,242</td>
            <td>26,859,554</td>
        </tr>
    </tbody>
</table>
<div style="height: 4000px">lots of content down here...</div>


0

ฉันชอบคำตอบของ Maximillian Hilsแต่ฉันมีปัญหาบางอย่าง:

  1. การแปลงไม่ทำงานใน Edge หรือ IE จนกว่าคุณจะนำไปใช้กับ th
  2. ส่วนหัวจะกะพริบในระหว่างการเลื่อนใน Edge และ IE
  3. ตารางของฉันโหลดโดยใช้ Ajax ดังนั้นฉันจึงต้องการแนบกับเหตุการณ์การเลื่อนหน้าต่างมากกว่าเหตุการณ์เลื่อนของ wrapper

เพื่อกำจัดการสั่นไหวฉันใช้การหมดเวลาเพื่อรอจนกว่าผู้ใช้จะเลื่อนเสร็จแล้วฉันใช้การแปลง - ดังนั้นส่วนหัวไม่สามารถมองเห็นได้ในระหว่างการเลื่อน

ฉันได้เขียนสิ่งนี้โดยใช้ jQuery ข้อดีอย่างหนึ่งของการที่ jQuery นั้นควรจัดการกับคำนำหน้าผู้จำหน่ายสำหรับคุณ

    var isScrolling, lastTop, lastLeft, isLeftHidden, isTopHidden;

    //Scroll events don't bubble https://stackoverflow.com/a/19375645/150342
    //so can't use $(document).on("scroll", ".table-container-fixed", function (e) {
    document.addEventListener('scroll', function (event) {
        var $container = $(event.target);
        if (!$container.hasClass("table-container-fixed"))
            return;    

        //transform needs to be applied to th for Edge and IE
        //in this example I am also fixing the leftmost column
        var $topLeftCell = $container.find('table:first > thead > tr > th:first');
        var $headerCells = $topLeftCell.siblings();
        var $columnCells = $container
           .find('table:first > tbody > tr > td:first-child, ' +
                 'table:first > tfoot > tr > td:first-child');

        //hide the cells while returning otherwise they show on top of the data
        if (!isLeftHidden) {
            var currentLeft = $container.scrollLeft();
            if (currentLeft < lastLeft) {
                //scrolling left
                isLeftHidden = true;
                $topLeftCell.css('visibility', 'hidden');
                $columnCells.css('visibility', 'hidden');
            }
            lastLeft = currentLeft;
        }

        if (!isTopHidden) {
            var currentTop = $container.scrollTop();
            if (currentTop < lastTop) {
                //scrolling up
                isTopHidden = true;
                $topLeftCell.css('visibility', 'hidden');
                $headerCells.css('visibility', 'hidden');
            }
            lastTop = currentTop;
        }

        // Using timeout to delay transform until user stops scrolling
        // Clear timeout while scrolling
        window.clearTimeout(isScrolling);

        // Set a timeout to run after scrolling ends
        isScrolling = setTimeout(function () {
            //move the table cells. 
            var x = $container.scrollLeft();
            var y = $container.scrollTop();

            $topLeftCell.css('transform', 'translate(' + x + 'px, ' + y + 'px)');
            $headerCells.css('transform', 'translateY(' + y + 'px)');
            $columnCells.css('transform', 'translateX(' + x + 'px)');

            isTopHidden = isLeftHidden = false;
            $topLeftCell.css('visibility', 'inherit');
            $headerCells.css('visibility', 'inherit');
            $columnCells.css('visibility', 'inherit');
        }, 100);

    }, true);

ตารางถูกห่อใน div table-container-fixedกับชั้นเรียน

.table-container-fixed{
    overflow: auto;
    height: 400px;
}

ฉันตั้งค่าการยุบเส้นขอบให้แยกออกจากกันเพราะมิฉะนั้นเราจะสูญเสียเส้นขอบระหว่างการแปลและฉันลบเส้นขอบบนโต๊ะเพื่อหยุดเนื้อหาที่ปรากฏเหนือเซลล์ที่มีเส้นขอบอยู่ระหว่างการเลื่อน

.table-container-fixed > table {
   border-collapse: separate;
   border:none;
}

ฉันทำให้thพื้นหลังเป็นสีขาวเพื่อปกปิดเซลล์ด้านล่างและฉันเพิ่มเส้นขอบที่ตรงกับเส้นขอบตาราง - ซึ่งมีการกำหนดสไตล์โดยใช้ Bootstrap และเลื่อนออกจากมุมมอง

 .table-container-fixed > table > thead > tr > th {
        border-top: 1px solid #ddd !important;
        background-color: white;        
        z-index: 10;
        position: relative;/*to make z-index work*/
    }

            .table-container-fixed > table > thead > tr > th:first-child {
                z-index: 20;
            }

.table-container-fixed > table > tbody > tr > td:first-child,
.table-container-fixed > table > tfoot > tr > td:first-child {
    background-color: white;        
    z-index: 10;
    position: relative;
}

0

ใช้ jQuery เวอร์ชันล่าสุดและรวมรหัส JavaScript ต่อไปนี้

$(window).scroll(function(){
  $("id of the div element").offset({top:$(window).scrollTop()});
});

1
ดูเหมือนจะใช้งานไม่ได้ บางทีคุณสามารถชี้แจงสิ่งที่คุณต้องการให้เราทำ?
Chris

1
div อะไร เรากำลังพูดถึงตารางที่นี่
isapir

0

นี่ไม่ใช่ทางออกที่แน่นอนสำหรับแถวส่วนหัวคงที่ แต่ฉันได้สร้างวิธีที่แยบยลในการทำซ้ำแถวส่วนหัวตลอดทั้งตารางแบบยาว แต่ยังคงรักษาความสามารถในการเรียงลำดับ

ตัวเลือกน้อยนี้เรียบร้อยต้องjQuerytablesorterปลั๊กอิน นี่คือวิธีการทำงาน:

HTML

<table class="tablesorter boxlist" id="pmtable">
    <thead class="fixedheader">
        <tr class="boxheadrow">
            <th width="70px" class="header">Job Number</th>
            <th width="10px" class="header">Pri</th>
            <th width="70px" class="header">CLLI</th>
            <th width="35px" class="header">Market</th>
            <th width="35px" class="header">Job Status</th>
            <th width="65px" class="header">Technology</th>
            <th width="95px;" class="header headerSortDown">MEI</th>
            <th width="95px" class="header">TEO Writer</th>
            <th width="75px" class="header">Quote Due</th>
            <th width="100px" class="header">Engineer</th>
            <th width="75px" class="header">ML Due</th>
            <th width="75px" class="header">ML Complete</th>
            <th width="75px" class="header">SPEC Due</th>
            <th width="75px" class="header">SPEC Complete</th>
            <th width="100px" class="header">Install Supervisor</th>
            <th width="75px" class="header">MasTec OJD</th>
            <th width="75px" class="header">Install Start</th>
            <th width="30px" class="header">Install Hours</th>
            <th width="75px" class="header">Revised CRCD</th>
            <th width="75px" class="header">Latest Ship-To-Site</th>
            <th width="30px" class="header">Total Parts</th>
            <th width="30px" class="header">OEM Rcvd</th>
            <th width="30px" class="header">Minor Rcvd</th>
            <th width="30px" class="header">Total Received</th>
            <th width="30px" class="header">% On Site</th>
            <th width="60px" class="header">Actions</th>
        </tr>
    </thead>
        <tbody class="scrollable">
            <tr data-job_id="3548" data-ml_id="" class="odd">
                <td class="c black">FL-8-RG9UP</td>
                <td data-pri="2" class="priority c yellow">M</td>
                <td class="c">FTLDFLOV</td>
                <td class="c">SFL</td>
                <td class="c">NOI</td>
                <td class="c">TRANSPORT</td>
                <td class="c"></td>
                <td class="c">Chris Byrd</td>
                <td class="c">Apr 13, 2013</td>
                <td class="c">Kris Hall</td>
                <td class="c">May 20, 2013</td>
                <td class="c">May 20, 2013</td>
                <td class="c">Jun 5, 2013</td>
                <td class="c">Jun 7, 2013</td>
                <td class="c">Joseph Fitz</td>
                <td class="c">Jun 10, 2013</td>
                <td class="c">TBD</td>
                <td class="c">123</td>
                <td class="c revised_crcd"><input readonly="true" name="revised_crcd" value="Jul 26, 2013" type="text" size="12" class="smInput r_crcd c hasDatepicker" id="dp1377194058616"></td>
                <td class="c">TBD</td>
                <td class="c">N/A</td>
                <td class="c">N/A</td>
                <td class="c">N/A</td>
                <td class="c">N/A</td>
                <td class="c">N/A</td>
                <td class="actions"><span style="float:left;" class="ui-icon ui-icon-folder-open editJob" title="View this job" s="" details'=""></span></td>
            </tr>
            <tr data-job_id="4264" data-ml_id="2959" class="even">
                <td class="c black">MTS13009SF</td>
                <td data-pri="2" class="priority c yellow">M</td>
                <td class="c">OJUSFLTL</td>
                <td class="c">SFL</td>
                <td class="c">NOI</td>
                <td class="c">TRANSPORT</td>
                <td class="c"></td>
                <td class="c">DeMarcus Stewart</td>
                <td class="c">May 22, 2013</td>
                <td class="c">Ryan Alsobrook</td>
                <td class="c">Jun 19, 2013</td>
                <td class="c">Jun 27, 2013</td>
                <td class="c">Jun 19, 2013</td>
                <td class="c">Jul 4, 2013</td>
                <td class="c">Randy Williams</td>
                <td class="c">Jun 21, 2013</td>
                <td class="c">TBD</td>
                <td class="c">95</td>
                <td class="c revised_crcd"><input readonly="true" name="revised_crcd" value="Aug 9, 2013" type="text" size="12" class="smInput r_crcd c hasDatepicker" id="dp1377194058632"></td><td class="c">TBD</td>
                <td class="c">0</td>
                <td class="c">0.00%</td>
                <td class="c">0.00%</td>
                <td class="c">0.00%</td>
                <td class="c">0.00%</td>
                <td class="actions"><span style="float:left;" class="ui-icon ui-icon-folder-open editJob" title="View this job" s="" details'=""></span><input style="float:left;" type="hidden" name="req_ship" class="reqShip hasDatepicker" id="dp1377194058464"><span style="float:left;" class="ui-icon ui-icon-calendar requestShip" title="Schedule this job for shipping"></span><span class="ui-icon ui-icon-info viewOrderInfo" style="float:left;" title="Show material details for this order"></span></td>
            </tr>
            .
            .
            .
            .
            <tr class="boxheadrow repeated-header">
                <th width="70px" class="header">Job Number</th>
                <th width="10px" class="header">Pri</th>
                <th width="70px" class="header">CLLI</th>
                <th width="35px" class="header">Market</th>
                <th width="35px" class="header">Job Status</th>
                <th width="65px" class="header">Technology</th>
                <th width="95px;" class="header">MEI</th>
                <th width="95px" class="header">TEO Writer</th>
                <th width="75px" class="header">Quote Due</th>
                <th width="100px" class="header">Engineer</th>
                <th width="75px" class="header">ML Due</th>
                <th width="75px" class="header">ML Complete</th>
                <th width="75px" class="header">SPEC Due</th>
                <th width="75px" class="header">SPEC Complete</th>
                <th width="100px" class="header">Install Supervisor</th>
                <th width="75px" class="header">MasTec OJD</th>
                <th width="75px" class="header">Install Start</th>
                <th width="30px" class="header">Install Hours</th>
                <th width="75px" class="header">Revised CRCD</th>
                <th width="75px" class="header">Latest Ship-To-Site</th>
                <th width="30px" class="header">Total Parts</th>
                <th width="30px" class="header">OEM Rcvd</th>
                <th width="30px" class="header">Minor Rcvd</th>
                <th width="30px" class="header">Total Received</th>
                <th width="30px" class="header">% On Site</th>
                <th width="60px" class="header">Actions</th>
            </tr>

เห็นได้ชัดว่าตารางของฉันมีจำนวนแถวมากกว่านี้ 193 เป็นค่าที่แน่นอน แต่คุณสามารถดูได้ว่าแถวส่วนหัวซ้ำอยู่ที่ไหน แถวส่วนหัวซ้ำถูกตั้งค่าโดยฟังก์ชั่นนี้:

jQuery

// Clone the original header row and add the "repeated-header" class
var tblHeader = $('tr.boxheadrow').clone().addClass('repeated-header');

// Add the cloned header with the new class every 34th row (or as you see fit)
$('tbody tr:odd:nth-of-type(17n)').after(tblHeader);

// On the 'sortStart' routine, remove all the inserted header rows
$('#pmtable').bind('sortStart', function() {
    $('.repeated-header').remove();
    // On the 'sortEnd' routine, add back all the header row lines.
}).bind('sortEnd', function() {
    $('tbody tr:odd:nth-of-type(17n)').after(tblHeader);
});

0

ผู้คนจำนวนมากดูเหมือนจะมองหาคำตอบนี้ ฉันพบว่ามันฝังอยู่ในคำตอบของคำถามอื่นที่นี่: การซิงค์ความกว้างคอลัมน์ระหว่างตารางในสองเฟรมที่แตกต่างกัน ฯลฯ

จากวิธีการหลายสิบวิธีที่ฉันลองนี่เป็นวิธีเดียวที่ฉันพบว่าทำงานได้อย่างน่าเชื่อถือเพื่อให้คุณมีตารางเลื่อนด้านล่างพร้อมกับส่วนหัวของตารางที่มีความกว้างเท่ากัน

นี่คือวิธีที่ฉันไม่ได้ครั้งแรกที่ผมดีขึ้นเมื่อ jsfiddle ด้านบนเพื่อสร้างฟังก์ชั่นนี้ซึ่งทำงานได้ทั้งบนtdและth(ในกรณีที่เดินทางถึงคนอื่น ๆ ที่ใช้thสำหรับการจัดแต่งทรงผมของแถวส่วนหัวของพวกเขา)

var setHeaderTableWidth= function (headertableid,basetableid) {
            $("#"+headertableid).width($("#"+basetableid).width());
            $("#"+headertableid+" tr th").each(function (i) {
                $(this).width($($("#"+basetableid+" tr:first td")[i]).width());
            });
            $("#" + headertableid + " tr td").each(function (i) {
                $(this).width($($("#" + basetableid + " tr:first td")[i]).width());
            });
        }

ถัดไปคุณต้องสร้างสองตารางหมายเหตุตารางส่วนหัวควรมีส่วนเพิ่มเติมTDเพื่อออกจากห้องในตารางด้านบนสำหรับแถบเลื่อนดังนี้:

 <table id="headertable1" class="input-cells table-striped">
        <thead>
            <tr style="background-color:darkgray;color:white;"><th>header1</th><th>header2</th><th>header3</th><th>header4</th><th>header5</th><th>header6</th><th></th></tr>
        </thead>
     </table>
    <div id="resizeToBottom" style="overflow-y:scroll;overflow-x:hidden;">
        <table id="basetable1" class="input-cells table-striped">
            <tbody >
                <tr>
                    <td>testdata</td>
                    <td>2</td>
                    <td>3</td>
                    <td>4</span></td>
                    <td>55555555555555</td>
                    <td>test</td></tr>
            </tbody>
        </table>
    </div>

จากนั้นทำสิ่งที่ชอบ:

        setHeaderTableWidth('headertable1', 'basetable1');
        $(window).resize(function () {
            setHeaderTableWidth('headertable1', 'basetable1');
        });

นี่เป็นทางออกเดียวที่ฉันพบใน Stack Overflow ที่ทำงานจากคำถามที่คล้ายกันมากมายที่โพสต์ไว้ซึ่งใช้ได้ในทุกกรณีของฉัน

ตัวอย่างเช่นฉันลองปลั๊กอิน jQuery stickytables ซึ่งไม่สามารถใช้งานได้กับ durandal และโครงการ Google Code ที่นี่ https://code.google.com/p/js-scroll-table-header/issues/detail?id=2

โซลูชันอื่น ๆ ที่เกี่ยวข้องกับการโคลนตารางมีประสิทธิภาพต่ำหรือดูดและไม่ทำงานในทุกกรณี

ไม่จำเป็นต้องมีโซลูชันที่ซับซ้อนมากเกินไปเหล่านี้ เพียงทำสองตารางเหมือนตัวอย่างด้านล่างและเรียกใช้ฟังก์ชัน setHeaderTableWidth ตามที่อธิบายไว้ที่นี่และความสำเร็จบูมคุณจะทำ

หากวิธีนี้ใช้ไม่ได้ผลคุณอาจกำลังเล่นกับคุณสมบัติการกำหนดขนาดกล่อง CSS ของคุณและคุณต้องตั้งค่าให้ถูกต้อง มันง่ายที่จะไขเนื้อหา CSS ของคุณโดยไม่ตั้งใจ มีหลายสิ่งที่อาจผิดพลาดได้ดังนั้นควรระวัง / ระมัดระวังสิ่งนั้น วิธีการนี้จะทำงานสำหรับฉัน


0

นี่เป็นวิธีการแก้ปัญหาที่เราได้ทำงานร่วมกับ (เพื่อจัดการกับกรณีขอบและ Internet Explorer รุ่นเก่าในที่สุดเราก็จางหายไปแถบชื่อเรื่องในการเลื่อนแล้วจางหายไปมันกลับเมื่อเลื่อนสิ้นสุด แต่ในเบราว์เซอร์ Firefox และ WebKit วิธีนี้ใช้ได้ผลจริงจะถือว่าการยุบตัวของเส้นขอบ: ยุบ

กุญแจสำคัญในการแก้ปัญหานี้คือว่าเมื่อคุณใช้ชายแดนยุบ , แปลง CSSทำงานในส่วนหัวจึงเป็นเพียงเรื่องของการสกัดกั้นเหตุการณ์เลื่อนและการตั้งค่าการแปลงอย่างถูกต้อง คุณไม่จำเป็นต้องทำสำเนาอะไรเลย พฤติกรรมนี้ถูกนำไปใช้อย่างเหมาะสมในเบราว์เซอร์มันยากที่จะจินตนาการถึงวิธีแก้ปัญหาที่มีน้ำหนักเบากว่า

JSFiddle: http://jsfiddle.net/podperson/tH9VU/2/

มันนำมาใช้เป็นปลั๊กอิน jQuery แบบง่าย ๆ คุณเพียง แต่ทำให้ thead ของคุณเหนียวด้วยการโทรเช่น $ ('thead'). sticky () และพวกมันจะไปไหนมาไหน มันทำงานได้หลายตารางในหน้าและส่วนหัวลงครึ่งหนึ่งของตารางขนาดใหญ่

$.fn.sticky = function(){
    $(this).each( function(){
        var thead = $(this),
            tbody = thead.next('tbody');

        updateHeaderPosition();

        function updateHeaderPosition(){
            if(
                thead.offset().top < $(document).scrollTop()
                && tbody.offset().top + tbody.height() > $(document).scrollTop()
            ){
                var tr = tbody.find('tr').last(),
                    y = tr.offset().top - thead.height() < $(document).scrollTop()
                        ? tr.offset().top - thead.height() - thead.offset().top
                        : $(document).scrollTop() - thead.offset().top;

                thead.find('th').css({
                    'z-index': 100,
                    'transform': 'translateY(' + y + 'px)',
                    '-webkit-transform': 'translateY(' + y + 'px)'
                });
            } else {
                thead.find('th').css({
                    'transform': 'none',
                    '-webkit-transform': 'none'
                });
            }
        }

        // See http://www.quirksmode.org/dom/events/scroll.html
        $(window).on('scroll', updateHeaderPosition);
    });
}

$('thead').sticky();

วิธีแก้ปัญหาที่ดี แต่คุณจะรวมเส้นขอบคอลัมน์ระหว่างคอลัมน์ได้อย่างไร (ทั้งในส่วนหัวคงที่จัดชิดกับข้อมูล td)
user5249203

ฉันไม่แน่ใจว่าฉันเข้าใจปัญหาของคุณ การยุบตัวของขอบไม่ได้ป้องกันคุณจากการใช้เส้นขอบระยะขอบ ฯลฯ มันเพียงลบเมตริกตารางวูดูของสมัยก่อน
podperson

1
เพิ่มborder: 2px solid red;ไปยังthเลื่อนและคุณจะเห็นปัญหา ฉันมากับโซลูชันขั้นพื้นฐานเพิ่มเติมนี้เอง: jsfiddle.net/x6pLcor9/19
calandoa

เพิ่มเส้นขอบมิติเดียวกันลงใน td และไม่มีปัญหา ฉันไม่เห็นประเด็นของคุณ เวอร์ชันของคุณสะอาดกว่าเดิมมากและไม่ได้ใช้ jQuery ดังนั้นวันนี้ฉันจะไปกับอะไรมากกว่านี้ (แม้ว่าตรงไปตรงมาฉันไม่คิดว่าฉันจะใช้โต๊ะเลยวันนี้.)
podperson

0

นี่คือคำตอบที่ดีขึ้นกับคนที่โพสต์โดยแมก Hils

อันนี้ใช้งานได้ใน Internet Explorer 11 โดยไม่มีการกะพริบใด ๆ :

var headerCells = tableWrap.querySelectorAll("thead td");
for (var i = 0; i < headerCells.length; i++) {
    var headerCell = headerCells[i];
    headerCell.style.backgroundColor = "silver";
}
var lastSTop = tableWrap.scrollTop;
tableWrap.addEventListener("scroll", function () {
    var stop = this.scrollTop;
    if (stop < lastSTop) {
        // Resetting the transform for the scrolling up to hide the headers
        for (var i = 0; i < headerCells.length; i++) {
            headerCells[i].style.transitionDelay = "0s";
            headerCells[i].style.transform = "";
        }
    }
    lastSTop = stop;
    var translate = "translate(0," + stop + "px)";
    for (var i = 0; i < headerCells.length; i++) {
        headerCells[i].style.transitionDelay = "0.25s";
        headerCells[i].style.transform = translate;
    }
});

0

ฉันพัฒนาปลั๊กอิน jQuery น้ำหนักเบาอย่างง่ายสำหรับการแปลงตาราง HTML ที่จัดรูปแบบได้ดีเป็นตารางที่เลื่อนได้พร้อมส่วนหัวและคอลัมน์คงที่

ปลั๊กอินทำงานได้ดีเพื่อให้ตรงกับตำแหน่งพิกเซลต่อพิกเซลในส่วนที่แก้ไขกับส่วนที่เลื่อนได้ นอกจากนี้คุณยังสามารถตรึงจำนวนคอลัมน์ที่จะดูได้ตลอดเวลาเมื่อเลื่อนตามแนวนอน

การสาธิต & เอกสาร: http://meetselva.github.io/fixed-table-rows-cols/

ที่เก็บ GitHub: https://github.com/meetselva/fixed-table-rows-cols

ด้านล่างคือการใช้งานตารางง่ายๆที่มีส่วนหัวคงที่

$(<table selector>).fxdHdrCol({
    width:     "100%",
    height:    200,
    colModal: [{width: 30, align: 'center'},
               {width: 70, align: 'center'}, 
               {width: 200, align: 'left'}, 
               {width: 100, align: 'center'}, 
               {width: 70, align: 'center'}, 
               {width: 250, align: 'center'}
              ]
});

อะไรคือสิ่งที่"ดีตาราง HTML" ?
Peter Mortensen

@PeterMortensen ควรมี "รูปแบบ HTML ที่ดี" แก้ไขแล้วขอบคุณ
Selvakumar Arumugam

0
<html>
<head>
    <script src="//cdn.jsdelivr.net/npm/jquery@3.2.1/dist/jquery.min.js"></script>
    <script>
        function stickyTableHead (tableID) {
            var $tmain = $(tableID);
            var $tScroll = $tmain.children("thead")
                .clone()
                .wrapAll('<table id="tScroll" />')
                .parent()
                .addClass($(tableID).attr("class"))
                .css("position", "fixed")
                .css("top", "0")
                .css("display", "none")
                .prependTo("#tMain");

            var pos = $tmain.offset().top + $tmain.find(">thead").height();


            $(document).scroll(function () {
                var dataScroll = $tScroll.data("scroll");
                dataScroll = dataScroll || false;
                if ($(this).scrollTop() >= pos) {
                    if (!dataScroll) {
                        $tScroll
                            .data("scroll", true)
                            .show()
                            .find("th").each(function () {
                                $(this).width($tmain.find(">thead>tr>th").eq($(this).index()).width());
                            });
                    }
                } else {
                    if (dataScroll) {
                        $tScroll
                            .data("scroll", false)
                            .hide()
                        ;
                    }
                }
            });
        }

        $(document).ready(function () {
            stickyTableHead('#tMain');
        });
    </script>
</head>

<body>
    gfgfdgsfgfdgfds<br/>
    gfgfdgsfgfdgfds<br/>
    gfgfdgsfgfdgfds<br/>
    gfgfdgsfgfdgfds<br/>
    gfgfdgsfgfdgfds<br/>
    gfgfdgsfgfdgfds<br/>

    <table id="tMain" >
        <thead>
        <tr>
            <th>1</th> <th>2</th><th>3</th> <th>4</th><th>5</th> <th>6</th><th>7</th> <th>8</th>

        </tr>
        </thead>
        <tbody>
            <tr><td>11111111111111111111111111111111111111111111111111111111</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
        </tbody>
    </table>
</body>
</html>

0

เพิ่มเติมจาก @Daniel Waltrip คำตอบ ตารางที่จำเป็นที่จะต้องแนบกับ div เพื่อที่จะทำงานร่วมกับposition: relative position:stickyดังนั้นฉันต้องการโพสต์โค้ดตัวอย่างที่นี่

CSS

/* Set table width/height as you want.*/
div.freeze-header {
  position: relative;
  max-height: 150px;
  max-width: 400px;
  overflow:auto;
}

/* Use position:sticky to freeze header on top*/
div.freeze-header > table > thead > tr > th {
  position: sticky;
  top: 0;
  background-color:yellow;
}

/* below is just table style decoration.*/
div.freeze-header > table {
  border-collapse: collapse;
}

div.freeze-header > table td {
  border: 1px solid black;
}

HTML

<html>
<body>
  <div>
   other contents ...
  </div>
  <div>
   other contents ...
  </div>
  <div>
   other contents ...
  </div>

  <div class="freeze-header">
    <table>
       <thead>
         <tr>
           <th> header 1 </th>
           <th> header 2 </th>
           <th> header 3 </th>
           <th> header 4 </th>
           <th> header 5 </th>
           <th> header 6 </th>
           <th> header 7 </th>
           <th> header 8 </th>
           <th> header 9 </th>
           <th> header 10 </th>
           <th> header 11 </th>
           <th> header 12 </th>
           <th> header 13 </th>
           <th> header 14 </th>
           <th> header 15 </th>
          </tr>
       </thead>
       <tbody>
         <tr>
           <td> data 1 </td>
           <td> data 2 </td>
           <td> data 3 </td>
           <td> data 4 </td>
           <td> data 5 </td>
           <td> data 6 </td>
           <td> data 7 </td>
           <td> data 8 </td>
           <td> data 9 </td>
           <td> data 10 </td>
           <td> data 11 </td>
           <td> data 12 </td>
           <td> data 13 </td>
           <td> data 14 </td>
           <td> data 15 </td>
          </tr>         
         <tr>
           <td> data 1 </td>
           <td> data 2 </td>
           <td> data 3 </td>
           <td> data 4 </td>
           <td> data 5 </td>
           <td> data 6 </td>
           <td> data 7 </td>
           <td> data 8 </td>
           <td> data 9 </td>
           <td> data 10 </td>
           <td> data 11 </td>
           <td> data 12 </td>
           <td> data 13 </td>
           <td> data 14 </td>
           <td> data 15 </td>
          </tr>         
         <tr>
           <td> data 1 </td>
           <td> data 2 </td>
           <td> data 3 </td>
           <td> data 4 </td>
           <td> data 5 </td>
           <td> data 6 </td>
           <td> data 7 </td>
           <td> data 8 </td>
           <td> data 9 </td>
           <td> data 10 </td>
           <td> data 11 </td>
           <td> data 12 </td>
           <td> data 13 </td>
           <td> data 14 </td>
           <td> data 15 </td>
          </tr>         
         <tr>
           <td> data 1 </td>
           <td> data 2 </td>
           <td> data 3 </td>
           <td> data 4 </td>
           <td> data 5 </td>
           <td> data 6 </td>
           <td> data 7 </td>
           <td> data 8 </td>
           <td> data 9 </td>
           <td> data 10 </td>
           <td> data 11 </td>
           <td> data 12 </td>
           <td> data 13 </td>
           <td> data 14 </td>
           <td> data 15 </td>
          </tr>         
         <tr>
           <td> data 1 </td>
           <td> data 2 </td>
           <td> data 3 </td>
           <td> data 4 </td>
           <td> data 5 </td>
           <td> data 6 </td>
           <td> data 7 </td>
           <td> data 8 </td>
           <td> data 9 </td>
           <td> data 10 </td>
           <td> data 11 </td>
           <td> data 12 </td>
           <td> data 13 </td>
           <td> data 14 </td>
           <td> data 15 </td>
          </tr>         
         <tr>
           <td> data 1 </td>
           <td> data 2 </td>
           <td> data 3 </td>
           <td> data 4 </td>
           <td> data 5 </td>
           <td> data 6 </td>
           <td> data 7 </td>
           <td> data 8 </td>
           <td> data 9 </td>
           <td> data 10 </td>
           <td> data 11 </td>
           <td> data 12 </td>
           <td> data 13 </td>
           <td> data 14 </td>
           <td> data 15 </td>
          </tr>         
         <tr>
           <td> data 1 </td>
           <td> data 2 </td>
           <td> data 3 </td>
           <td> data 4 </td>
           <td> data 5 </td>
           <td> data 6 </td>
           <td> data 7 </td>
           <td> data 8 </td>
           <td> data 9 </td>
           <td> data 10 </td>
           <td> data 11 </td>
           <td> data 12 </td>
           <td> data 13 </td>
           <td> data 14 </td>
           <td> data 15 </td>
          </tr>         
         <tr>
           <td> data 1 </td>
           <td> data 2 </td>
           <td> data 3 </td>
           <td> data 4 </td>
           <td> data 5 </td>
           <td> data 6 </td>
           <td> data 7 </td>
           <td> data 8 </td>
           <td> data 9 </td>
           <td> data 10 </td>
           <td> data 11 </td>
           <td> data 12 </td>
           <td> data 13 </td>
           <td> data 14 </td>
           <td> data 15 </td>
          </tr>         
       </tbody>
    </table>
  </div>
</body>
</html>

การสาธิต

ป้อนคำอธิบายรูปภาพที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.