12 คะแนน โดย GN⁺ 2025-11-27 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • CSS Subgrid คือฟีเจอร์ที่ก้าวข้ามข้อจำกัดของ Grid แบบเดิม ทำให้สามารถ ขยาย โครงสร้างกริดของพาเรนต์ลงไปถึงองค์ประกอบ DOM ชั้นล่างได้
  • เดิมทีมีเพียง ลูกโดยตรงเท่านั้น ที่เข้าร่วมในกริดได้ แต่เมื่อใช้ subgrid แม้แต่โครงสร้างแบบซ้อนอย่าง <ul> และ <li> ก็สามารถจัดวางอยู่ใน เซลล์กริดเดียวกัน ได้
  • ช่วยแก้ปัญหา ความไม่สมดุลระหว่างองค์ประกอบพี่น้อง ที่เกิดจากความยาวคอนเทนต์ต่างกัน และรองรับการสร้างเลย์เอาต์ที่ให้การ์ดหรือเซกชันแต่ละส่วน ตอบสนองแบบไดนามิก
  • อย่างไรก็ตาม ยังมีข้อควรระวัง เช่น ปัญหาการจองแถว, การรีเซ็ตเลขเส้นกริด, และ ความเข้ากันไม่ได้กับ fluid grid ที่อิง auto-fill
  • เบราว์เซอร์หลักส่วนใหญ่รองรับแล้ว และสามารถ นำมาใช้แบบค่อยเป็นค่อยไป ได้ จึงเป็นเทคโนโลยีที่จะช่วยเพิ่ม ความยืดหยุ่นในการออกแบบ UI อย่างมากในอนาคต

แนวคิดพื้นฐานของ Subgrid

  • CSS Grid ในช่วงแรกให้เฉพาะ องค์ประกอบลูกโดยตรงเท่านั้น ที่เข้าร่วมในเลย์เอาต์ได้
    • ตัวอย่างเช่น ใน UI พอร์ตโฟลิโอ รูปภาพ <li> ภายใน <ul> จะถูกรวมอยู่ในเซลล์เดียวโดยปริยาย
  • หากใช้ grid-template-rows: subgrid และ grid-template-columns: subgrid จะเป็นการ สืบทอดนิยามแถวและคอลัมน์ ของกริดพาเรนต์
    • ทำให้ <li> แต่ละตัวถูกจัดวางลงในเซลล์ของกริดพาเรนต์ได้โดยตรง พร้อมคงไว้ทั้ง โครงสร้าง HTML เชิงความหมายและการจัดแนวเชิงภาพ
  • แม้จะทำผลลัพธ์แบบเดียวกันได้ด้วย Flexbox และ Grid แบบซ้อน แต่ subgrid ให้แนวทางที่กระชับกว่า เพราะ ใช้โครงสร้างกริดเดียวร่วมกัน

ความเป็นไปได้ใหม่ของเลย์เอาต์

  • ในตัวอย่างการ์ดพอร์ตโฟลิโอ <article> แต่ละใบมี กริด 2 คอลัมน์ สำหรับวางรูปภาพและข้อความ
    • หน่วย fr มีความยืดหยุ่น แต่เพราะแต่ละการ์ดคำนวณแยกกัน จึงเกิด ความกว้างคอลัมน์ไม่สมดุล
  • เมื่อใช้ grid-template-columns: subgrid คอลัมน์ของกริดพาเรนต์จะถูก แชร์ร่วมกันโดยทุกการ์ด
    • เมื่อคอนเทนต์เปลี่ยน เช่น ความยาวของชื่อเรื่อง กริดทั้งชุดจะปรับใหม่อัตโนมัติ
  • วิธีนี้ทำให้สร้าง เลย์เอาต์ที่องค์ประกอบพี่น้องรับรู้กันและกัน ได้
    • ตัวอย่าง: หากย่อชื่อ “Infinite Supercomputer” สัดส่วนรูปภาพและข้อความของการ์ดทั้งหมดจะปรับทันที

ข้อควรระวังเมื่อใช้ Subgrid (Gotchas)

การจองพื้นที่แถว

  • การแชร์คอลัมน์นั้นเข้าใจง่าย แต่เมื่อ แชร์แถว จำเป็นต้องมี การจองแถวอย่างชัดเจน
    • ตัวอย่าง: ในการ์ดตารางราคา หากต้องการให้รายการใน <ul> แต่ละชุดเรียงตรงกันในแถวเดียวกัน ต้องกำหนดจำนวนแถวด้วย grid-row: span N
  • โดยปกติ subgrid จะ กินพื้นที่เพียงเซลล์เดียว ดังนั้นหากต้องการใช้หลายแถว ต้อง ขยายพื้นที่กริดของพาเรนต์ ก่อน

หมายเลขกริดในกริดซ้อน

  • subgrid จะ สืบทอดเทมเพลตแถวและคอลัมน์ จากพาเรนต์ แต่ หมายเลขเส้นกริดจะถูกรีเซ็ตใหม่
    • ตัวอย่าง: แม้จะสืบทอดเส้นที่ 2 ถึง 5 ของพาเรนต์ ภายในก็จะถูกนับใหม่เป็น 1 ถึง 4
    • แต่ละกริดมีดัชนีของตัวเอง ดังนั้น เลขเส้นกริดจึงทำงานเป็นดัชนีสัมพัทธ์ ไม่ใช่ ID แบบเฉพาะตัว

ใช้ร่วมกับ fluid grid ไม่ได้

  • fluid grid ในรูปแบบ repeat(auto-fill, minmax()) ไม่สามารถใช้ร่วมกับ subgrid ได้
    • subgrid ต้องมี จำนวนคอลัมน์ที่กำหนดแน่นอน และไม่รองรับ auto-fill หรือ auto-fit
    • ผู้เขียนระบุอย่างชัดเจนว่ายังไม่พบวิธีแก้สำหรับการใช้คู่กันแบบนี้

การรองรับเบราว์เซอร์รุ่นเก่า

  • แม้เบราว์เซอร์หลักจะรองรับตั้งแต่หลังปี 2023 แต่ อัตราการรองรับยังไม่ถึง 90%
  • สามารถใช้เงื่อนไข @supports not (grid-template-columns: subgrid) เพื่อ จัดเตรียมเลย์เอาต์ทางเลือก ได้
    • ตัวอย่าง: เสนอ fallback ที่จัดรูปภาพและข้อความเป็น สแต็กแนวตั้ง

กรณีใช้งานจริงและบทสรุป

  • เว็บไซต์นักพัฒนาของ Stripe (stripe.dev) จัดทั้งหน้าเป็นกริดขนาดใหญ่หนึ่งชุด และใช้ subgrid หลายชั้น เพื่อจัดวางรายละเอียดอย่างประณีต
  • subgrid มีประโยชน์ไม่ใช่แค่กับเลย์เอาต์ขนาดใหญ่ แต่ยังใช้ได้ดีในการ ปรับ UI ขนาดเล็ก
  • สามารถ ค่อย ๆ นำมาใช้ ได้โดยไม่จำเป็นต้องรื้อโครงสร้างทั้งโปรเจกต์ใหม่
  • เป็นเครื่องมือที่ช่วยเพิ่ม ความยืดหยุ่นรูปแบบใหม่ให้กับเลย์เอาต์ CSS และน่าลองนำไปใช้งานเชิงทดลองอย่างมาก

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

 
GN⁺ 2025-11-27
ความคิดเห็นบน Hacker News
  • ฟีเจอร์ Subgrid เจ๋งมาก แต่ในตัวอย่างง่าย ๆ แรกนั้นใช้ ul { display: contents } เพื่อให้ลูก ๆ เข้าไปมีส่วนร่วมกับ grid layout ได้เหมือนกัน
    ถ้าไม่ได้จำเป็นต้องใช้ฟีเจอร์ subgrid วิธีนี้จะ มีประสิทธิภาพ กว่า

    • สำหรับตัวอย่างนั้นก็จริง แต่โดยทั่วไป display: contents จะลบองค์ประกอบ UL ออกจากเลย์เอาต์ไปเลย
      เลยไม่สามารถใส่สไตล์หรือรับ UI events ที่องค์ประกอบนั้นได้
      ถ้าอยากใช้ UL เป็นพื้นที่ไฮไลต์หรือส่วนที่เลื่อนได้ subgrid จะมีประโยชน์กว่ามาก
    • ในตัวอย่างที่สอง ถ้าอยากให้ความกว้างของรูปภาพคงที่ ก็ควรใช้หน่วยอื่นแทน fr และใช้ fr กับข้อความเพื่อให้เติมพื้นที่ที่เหลือ
  • ตอนก่อนหน้านี้เคยทำ UI เปรียบเทียบราคา แล้วลำบากมากเพราะไม่มี subgrid
    การวางสองตารางไว้ข้างกันแล้วทำให้แถวตรงกันนั้น เป็นไปไม่ได้เลย
    จะแก้ด้วยความสูงคงที่หรือคำนวณด้วย JS ก็ได้ แต่ในโครงสร้างคอมโพเนนต์ React มันไม่มีประสิทธิภาพมาก

  • เคยคิดว่า container queries น่าจะเป็นทางออกที่ดีกว่าไหม
    แต่ถ้าต้องการรักษาความสอดคล้องของทั้งกริด subgrid อาจเหมาะกว่า
    อ้างอิง ตัวอย่างบน CodePen จะเข้าใจได้ง่าย

    • Container queries ไม่ได้แก้ปัญหาการตอบสนองต่อขนาดของ sibling elements
      แถมพอใช้ container ก็จะเกิด stacking context ใหม่ขึ้นมา ซึ่งไม่สะดวก
      น่าเสียดายที่ใช้ subgrid กับ container ร่วมกันไม่ได้ ถ้าลูกอ้างอิงขนาดของ subgrid ได้ก็น่าจะแรงมาก
  • ทำให้นึกว่า “สุดท้ายเราก็กลับไปใช้เลย์เอาต์แบบ <table> กันแล้วเหรอ?”

    • จะว่าใช่ก็ใช่ จะว่าไม่ใช่ก็ไม่ใช่ เมื่อก่อน <table> เป็น แฮ็ก สำหรับแก้ปัญหา แต่มีข้อจำกัดทั้งเรื่องการเข้าถึงและทางเทคนิคเยอะ
      ระบบ Grid เป็นเครื่องมือสำหรับการจัดวางเชิงภาพ ไม่เหมือนตารางที่ใช้แสดงโครงสร้างข้อมูล
      ตอนนี้กริดกลายเป็นมาตรฐานไปแล้ว ก็อยากให้เลิกเอาไปเทียบกับตารางเสียที
    • เมื่อ 25 ปีก่อน เรนเดอร์ตารางจากฝั่งเซิร์ฟเวอร์อัตโนมัติเพื่อทำเลย์เอาต์ ซึ่งตอนนั้นมัน ทำงานง่ายมาก
      แต่ไม่ได้คำนึงถึง responsive หรือ accessibility เลย สุดท้ายก็เหมือนเราประดิษฐ์ตารางขึ้นมาใหม่
    • ปัญหาของ <table> คือมันเป็นโครงสร้างที่ใช้อธิบายเนื้อหา ไม่ใช่ว่า ตัวกริดมีปัญหา
    • ผมเองก็ได้ยินคำว่า “ตารางมีไว้สำหรับข้อมูลแบบตาราง” มานานกว่า 20 ปีแล้ว
      สุดท้าย CSS ก็แค่เอาความสามารถนั้นกลับมาทำใหม่ในรูปแบบที่ดีกว่า
  • หนึ่งใน grid bug ที่เคยเจอคือ ถ้ากำหนดขนาดของ <img> เป็นเปอร์เซ็นต์ ขนาดเซลล์จะเพี้ยนไปตามขนาดต้นฉบับของรูป
    เกิดทั้งใน Firefox และ Chromium และบั๊กที่เกี่ยวข้องอยู่ที่ Mozilla Bug 1857365

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

    • ถ้าจะให้ดีควรมีวิธีจัดแนวองค์ประกอบได้แม้จะมี parent คนละตัว
      หรือไม่ก็ให้ flex container หนึ่ง เลียนแบบการกระจายตัว ของอีกคอนเทนเนอร์ได้ก็คงดี
      แต่ถ้าทำแบบนั้น DX อาจซับซ้อนขึ้นมาก
  • สงสัยว่าทำไมในตัวอย่างโค้ดถึงมีสไตล์ทั้งในไฟล์ HTML และ CSS
    ดูแค่ CSS ของตัวอย่าง subgrid แรกแล้วใช้เวลาหาอยู่นานว่า UL ถูกใส่สไตล์อะไรไว้บ้าง

  • ทำให้นึกว่า “สุดท้ายก็กลับมาที่ grid อีกแล้วเหรอ?”
    สมัย HTML ก่อนหน้านี้ก็เคยทำอะไรคล้าย ๆ กัน

    • แต่ grid ตอนนี้ทำให้ responsive design ง่ายขึ้นมาก
    • แน่นอนว่าผลข้างเคียงก็คือ ตอนจัดสไตล์แล้ว บั๊กเยอะขึ้น เหมือนกัน 😅
  • บล็อกโพสต์ของ Josh น่าทึ่งเสมอ
    ทั้งความชัดเจนของเนื้อหา เซนส์ด้านดีไซน์ และเว็บไซต์แบบอินเทอร์แอ็กทีฟ ล้วนยอดเยี่ยม

    • ผมก็สมัคร mailing list ของเขาไว้เหมือนกัน และตั้งตารอบทความใหม่ทุกครั้ง
  • โดยส่วนตัวผมยังรู้สึกว่า grid ใช้งานยากอยู่ดี
    ไวยากรณ์มันแปลก ๆ และความรู้สึกเรื่องเลย์เอาต์ก็ยังไม่ค่อยเข้ามือ Flexbox เข้าใจง่ายและยืดหยุ่นกว่ามาก

    • สองเทคโนโลยีนี้มีแนวทางแก้ปัญหาคนละแบบ
      Flexbox ควบคุมขนาดโดยยึดตามเนื้อหา ส่วน Grid ควบคุมโดยยึด คอนเทนเนอร์เป็นศูนย์กลาง
    • ผมเองก็ลองกลับไปใช้ grid เป็นระยะ แต่ก็ยังรู้สึกว่ามันขาดความสามารถที่อยากได้อยู่
      เนื้อหาไม่จัดเข้าหากันอัตโนมัติในหลายแกน และต้องวางทุกอย่างด้วยมือทั้งหมด
      อาจเป็นเพราะผมยังไม่เข้าใจแก่นของ grid ดีพอ หรือไม่ก็ไม่เหมาะกับลักษณะงานที่ทำ
    • ตอนทำ responsive design ก็ยังรู้สึกว่า flexbox ง่ายกว่า grid มาก