4 คะแนน โดย GN⁺ 2024-02-25 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • ตารางที่มีหลายแถว เมื่อเลื่อนลงไปเรื่อย ๆ จะยิ่งลืมได้ง่ายว่าคอลัมน์แต่ละคอลัมน์หมายถึงอะไร ทำให้อ่านข้อมูลไม่สะดวก
  • เพียงเพิ่ม position: sticky; และ top: 0; ให้กับ thead ก็สามารถทำให้ หัวตารางตรึงอยู่กับที่ ได้
  • sticky มีการรองรับจากเบราว์เซอร์ทั่วโลกประมาณ 96% จึงไม่ถือว่าใกล้เคียงกับฟีเจอร์ทดลอง
  • แม้ตอนดูแถวด้านล่าง เช่น รายการที่ 300 ชื่อคอลัมน์ก็ยังคงแสดงอยู่ ทำให้ ประสบการณ์การสำรวจตาราง ดีขึ้น
  • การใช้งานมีขนาดเล็กแต่ให้ผลมาก จึงเหมาะที่จะนำไปใช้เป็นการปรับปรุงการใช้งานพื้นฐานสำหรับเว็บเพจที่มีตารางยาว

ปัญหาหัวตารางหายไปในตารางยาว

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

ใช้ sticky กับ thead

  • วิธีแก้คือเพิ่มคุณสมบัติ CSS สองรายการให้กับ thead
position: sticky;
top: 0;
  • เมื่อใช้ position: sticky ร่วมกับ top: 0 จะสามารถ ตรึง หัวตารางไว้ที่ด้านบนของหน้าจอขณะเลื่อนได้
  • sticky มี อัตราการรองรับทั่วโลกประมาณ 96% จึงใช้ได้ในเบราว์เซอร์จำนวนมาก
  • สามารถตรวจสอบการทำงานจริงได้ที่ ตัวอย่าง CodePen

1 ความคิดเห็น

 
GN⁺ 2024-02-25
ความเห็นจาก Hacker News
  • ถ้าเป็น sticky header แกนเดียวก็พอรับได้ แต่ยังคงรอวันที่ CSS รองรับทั้งสองแกนพร้อมกันอยู่: https://github.com/w3c/csswg-drafts/issues/8286

    • งานสัญญาที่ต้องทำให้ทั้งคอลัมน์และเฮดเดอร์ติดค้างไว้เป็นหนึ่งในงานที่ยากที่สุดที่เคยเจอ ถ้าเป็นตารางมาตรฐานก็ง่าย แต่รอบนี้เป็น ตารางไดนามิกจาก third-party ของ VueJS ที่ซับซ้อนและใช้ CSS-as-JS ที่ถูก generate ขึ้นมา เลยเสียเวลาไปมากแค่กับการไล่ว่า CSS กับ JS มาจากไหน สุดท้ายต้อง override ทั้งฟังก์ชันคลาสใน JS และ CSS ที่ generate ออกมา รู้สึกผิดกับลูกค้าที่ใช้เวลานานเกินไป และทำให้เลือกไลบรารีในโค้ดเบส Vue/React อย่างระวังมากขึ้น ตารางเป็นองค์ประกอบพื้นฐานของ HTML อยู่แล้ว แต่ไม่เข้าใจว่าทำไมงานง่าย ๆ งานเดียวถึงต้องพึ่ง JS class ซ้อนสามชั้นกับ CSS ที่ import มาจาก JSON ด้วย
    • น่าจะตามดู issue ต้นทางที่ก่อให้เกิด issue นี้มา 8 ปีแล้ว และมันเป็นส่วนของสเปก CSS ที่น่าหงุดหงิดที่สุด บางครั้งก็แค่ต้องการ data table ขนาดใหญ่ ที่ตรึงด้านบนไว้และใช้ overflow-x: auto ได้ด้วย แต่กลับเหมือนโดนบังคับให้เลือกได้แค่อย่างใดอย่างหนึ่ง
  • สารภาพเลยว่าต่อให้แทบไม่มีความรู้ CSS ก็ยังทำเว็บแอปที่พอใช้งานได้อยู่ ช่วงนี้เพิ่งพยายามตรึงเฮดเดอร์ของตารางสัตว์ประหลาดขนาดประมาณ 20,000 แถว: https://www.datasciencemeta.com/rpackages ตอนแรกหวังว่าจะมีอะไรอย่าง class="table table-header-sticky" อยู่ในคลาสตารางของ Bootstrap แต่ไม่มี ลองปรับตาม Stack Overflow, GPT และตัวอย่างจาก CodePen อยู่ราว 20 นาที ก็ยังมีผลข้างเคียงแปลก ๆ แต่ CodePen ในบทความนี้ทำงานได้ใน 2 นาที และตอนนี้กำลัง deploy ขึ้น production อยู่

  • การตรึงหัวตารางดูเหมือนจะง่ายด้วย position: sticky; แค่บรรทัดเดียว แต่พอเริ่มใส่อะไรเพิ่มเข้าไปในเนื้อหาตารางก็ซับซ้อนขึ้นทันที เคยเพิ่มฟีเจอร์ในตารางที่มี sticky header ให้จำ index ของแถวแรกที่ผู้ใช้มองเห็นตอนเลื่อนดูเนื้อหาแล้วออกจากหน้า จากนั้นค่อย restore กลับมาเมื่อกลับเข้าเพจ แต่ผลลัพธ์มักจะเลื่อนลงไปประมาณหนึ่งแถวเสมอ ที่แท้แถวที่ 5 อยู่บนสุดของตารางจริง แต่ thead มาซ้อนทับไว้จนแถวที่ 6 ดูเหมือนเป็นแถวแรกที่มองเห็น เลยแก้ด้วยการชดเชยตำแหน่ง scroll ตามความสูงของ thead แต่บางครั้งก็ยังคลาดไปไม่กี่พิกเซล และเพราะเป็นตารางใหญ่เลยต้องทำ lazy loading ใน scroll event พร้อมใช้ automatic table layout แบบปกติ ทำให้เซลล์ใน header มีการตัดบรรทัดและความสูงรวมของ header เปลี่ยนไป สุดท้ายเลยต้องผูก ResizeObserver กับ thead เพื่อปรับตำแหน่ง scroll แบบไดนามิกเมื่อความสูงเปลี่ยน [1] https://developer.mozilla.org/en-US/docs/Web/API/ResizeObser...

  • ตอนทำสิ่งนี้ ถ้าต้องการให้ เส้นขอบ ของ header ติดค้างไปด้วย ก็สามารถจัดการด้วย table thead:before และ table thead:after โดยใส่ position: absolute, width: 100%, top: 0/bottom: 0, และ border-top/border-bottom

  • อยากให้หัวตารางทำงานแบบนี้โดยอัตโนมัติอยู่แล้ว ถ้านักพัฒนาตั้งใจใช้แท็กที่เกี่ยวข้องและลงแรงเพิ่มขนาดนั้น ส่วนใหญ่ก็น่าจะหมายถึงอยากได้พฤติกรรมแบบนี้อยู่แล้ว

    • แค่ติดตั้งปลั๊กอินเบราว์เซอร์ที่โหลด stylesheet แบบกำหนดเอง ได้กับทุกหน้า แต่ทุกวันนี้มีเว็บเพิ่มขึ้นเรื่อย ๆ ที่ไม่ได้ทำตารางด้วย อีกแล้ว แต่ใช้ 500 อันกับ `` ซ้อนกัน 45 ชั้นในแต่ละอันแทน ดังนั้นคงใช้ไม่ได้กับเว็บพวกนั้น
    • การเปลี่ยนแบบนี้ดูมีโอกาสสูงที่จะทำให้บางอย่างพังในแบบที่คาดไม่ถึง เหตุผลหลักน่าจะเป็นเพราะก่อนมี CSS Grid เว็บไซต์จำนวนมากใช้ตารางทำ layout แบบกริด ถ้าเฮดเดอร์ติดค้าง layout พวกนั้นอาจพังได้ หนึ่งในความล้มเหลวใหญ่ของ semantic HTML คือการที่ตารางถูกมองเป็น “วิธีแสดงข้อมูลแบบตาราง” น้อยกว่าเป็น “กริดขององค์ประกอบอะไรก็ได้”
  • บน command line ก็ส่ง header ไป stderr และส่งเนื้อหาไป stdout ได้ ถ้าไม่ทำแบบนั้น ผลของ heights | sort -k2 -nr จะออกมาเป็น George 186, Wally 173, NAME HEIGHT แต่ถ้าให้ header เลี่ยง stdout ก็จะกลายเป็น NAME HEIGHT, George 186, Wally 173

    • heights | (sed -u 1q; sort -k2 -nr) ทำงานได้ถูกต้อง ที่มา: https://stackoverflow.com/a/56151840
    • ถ้าเป็นกรณีเขียนลงไฟล์ก็ต้องพยายามมากขึ้นอีกหน่อยและต้อง เข้าใจ shell มากขึ้นด้วย นี่เป็นข้อจำกัดถาวรของโมเดลแบบข้อความ in-band เท่านั้น แต่การเอา STDERR มาใช้ผิดวัตถุประสงค์แบบนี้ดูจะทำให้งงมากกว่าช่วย ถ้า heights เป็นไฟล์ ก็ทำแบบ % head -1 heights ; sed 1,1d heights | sort -k2 -nr ได้ และถ้า heights เป็น executable ที่รันซ้ำสองครั้งมีต้นทุนสูง ก็ทำแบบ % heights > /tmp/heights ; head -1 /tmp/heights ; sed 1,1d /tmp/heights | sort -k2 -nr ได้ จะ pipe เข้า awk ก็ได้เหมือนกัน ทางเลือกอื่นอาจสะดวกน้อยกว่าแต่ก็น่าประหลาดใจน้อยกว่า และยังทำงานได้แม้ผู้เขียน executable จะคิดอีกแบบ
    • ในกรณีนี้อะไรดีกว่ากัน ระหว่างส่ง header ไป stderr หรือพิมพ์ header เฉพาะตอนที่ stdout เป็น TTY?
  • เรื่องนี้เคยใช้ไม่ได้มานาน Chrome เคยปิด position: sticky บนองค์ประกอบ thead และ tr: https://issues.chromium.org/issues/41303743 จำได้ว่าตารางรองรับบนเบราว์เซอร์เกือบทั้งหมดเป็นสีเขียวหมด แต่บนตารางของ Chrome กลับใช้ไม่ได้จริง

    • น่าแปลกที่ตอนนี้มันง่ายขนาดนี้แล้ว ตอนที่เคยต้องใช้จริง ๆ หากอยากให้มันทำงานได้ทุกเบราว์เซอร์ ต้องยัดของจุกจิกสารพัดลงไปใน HTML กับ CSS แต่ก็ไม่ได้แปลกใจมาก เพราะการพัฒนาเว็บก็มักเป็นแบบนั้นอยู่แล้ว
  • บางคนอาจอยากพูดว่า “ขอร้องล่ะ อย่าทำเลย” มากกว่า: https://news.ycombinator.com/item?id=32998091

    • ถ้าเป็นเว็บเพจทั่วไปก็เห็นด้วยเต็มที่ หลายครั้งฉันลบ องค์ประกอบแบบ fixed ด้วย uBlock Origin เพราะเร็วกว่านั่งเขียนสไตล์ Stylus และสไตล์กลางที่ใช้ทั้งไซต์ก็ใช้ได้ผลดีพอสมควร แต่ต้นฉบับพูดถึง data table ที่มีคอลัมน์ header แบบติดค้าง ดังนั้นข้อเสนอนี้จริง ๆ แล้วมีประโยชน์มาก
    • นั่นพูดถึง fixed header ของทั้งหน้าเว็บ ซึ่งต่างจากกรณีตารางโดยสิ้นเชิง เวลาดูตารางที่มีคอลัมน์ตัวเลขสักสิบสองคอลัมน์ แล้วเลื่อนลงนิดเดียวก็ไม่รู้แล้วว่าคอลัมน์ไหนคืออะไร มันแย่มากจริง ๆ
    • แล้วคุณสมบัติ sticky มันแย่ตรงไหน?
  • ใน CodePen จะดูดีกว่าถ้าชดเชย top ตามขนาดเส้นขอบ เช่นใช้ -1px แทน 0 เพื่อหลีกเลี่ยงไม่ให้เนื้อหาตารางโผล่ผ่านขึ้นมาเหนือ header เปรียบเทียบ: https://codepen.io/bradleytaunt/pen/bGZyJBj เวอร์ชันแก้ไข: https://codepen.io/alokmenghrajani/pen/ExMBQow

  • มีคนเสนอว่าแทนที่จะใช้ sticky header ให้ใช้ ความสูง viewport แบบจำกัด เพื่อให้ header มองเห็นอยู่เสมอ ทำได้แบบ DataGridXL(https://datagridxl.com) อนึ่ง ฉันเป็นคนสร้างมันเอง

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