ขุดลงไปในพื้นที่แสดงผล: กริดลงจนสุด

เผยแพร่แล้ว: 2022-03-10
สรุปอย่างย่อ ↬ ต่อชุดข้อมูลในคุณสมบัติการ display ใน CSS คราวนี้ Rachel Andrew จะดูว่าเกิดอะไรขึ้นเมื่อคุณใช้เส้นตารางเป็นค่าของการแสดงผล พร้อมข้อมูลเพิ่มเติมเกี่ยวกับวิธีที่ sub-grid เปลี่ยนแปลงพฤติกรรมนั้น

วันนี้ เราจะมาดูว่าเกิดอะไรขึ้นเมื่อเราใช้ display: grid และวิธีที่เราอาจใช้ค่า sub-grid ใหม่ของ grid-template-columns และ grid-template-rows เพื่ออนุญาตให้ใช้กริดตลอดจนมาร์กอัปของเรา ซึ่งเกี่ยวเนื่องกัน

บทความนี้เป็นส่วนหนึ่งของชุดข้อมูลที่พิจารณาแง่มุมต่างๆ ของคุณสมบัติการ display CSS และเป็นบทความต่อจากสองบทความแรก:

  1. สองคุณค่าของการ display
  2. การสร้างกล่อง
  3. กริดทุกทางลง

จะเกิดอะไรขึ้นเมื่อเราสร้างคอนเทนเนอร์กริด

เปิด CSS Grid Layout โดยใช้ display: grid หากคุณได้อ่านบทความแรกในชุดนี้ คุณจะรู้ว่าคุณสมบัติค่าเดียวนี้หมายถึงอะไร display: block grid เราได้รับกล่องระดับบล็อกซึ่งกำหนดเป็น คอนเทนเนอร์กริด โดยมีลูกโดยตรงที่เป็นรายการกริดและมีส่วนร่วมในเค้าโครงกริด

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

เพิ่มเติมหลังกระโดด! อ่านต่อด้านล่าง↓

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

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

หากรายการใดในเลย์เอาต์ลอยหรือเคลียร์ คุณสมบัติการ float และ clear จะไม่มีผลเมื่อรายการนั้นกลายเป็นรายการกริด คุณสมบัติการ vertical-align ไม่มีผล และไม่สามารถใช้ ::first-letter และ ::first-line pseudo-elements

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

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

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

ชุดไพ่วางหนึ่งใบไว้ด้านล่างอีกใบในคอลัมน์เดียว
เมื่อเราสร้างคอนเทนเนอร์กริดที่ไม่มีคอลัมน์ เราจะได้กริดคอลัมน์เดียว (ตัวอย่างขนาดใหญ่)

เราสามารถเริ่มสร้างบางสิ่งที่ดูเหมือนกริดให้กับเราได้โดยการให้ค่าคุณสมบัติ grid-template-columns ทรัพย์สินใช้รายการเพลงเป็นมูลค่า ถ้าฉันให้แทร็ก 1fr สามแทร็ก ตอนนี้เราพบว่าตัวเองมีกริดแบบสามคอลัมน์ และการใช้คุณสมบัติ gap ทำให้ฉันมีระยะห่างระหว่างการ์ดเหล่านั้น

ตอนนี้เรามีบางอย่างที่ดูเหมือนกริด:

การ์ดวางในสามคอลัมน์และสองแถว
เรากำหนดแทร็กของคอลัมน์และช่องว่างเพื่อให้ได้เลย์เอาต์กริดที่ชัดเจน (ตัวอย่างขนาดใหญ่)

แต่ละรายการกริดในตัวอย่างของเรามีลูกของตัวเอง การ์ดมีส่วนหัวและส่วนท้าย และพื้นที่สำหรับเนื้อหาหลักของการ์ด รายการย่อยเหล่านี้เป็นรายการกริด แต่รายการย่อยกลับบล็อกและเลย์เอาต์แบบอินไลน์ ส่วนหัว พื้นที่เนื้อหา และส่วนท้ายจะไม่ทำตารางใดๆ ในลักษณะเดียวกัน เนื่องจากเมื่อเราเปลี่ยนค่าของ display เป็น grid ค่านั้นจะไม่สืบทอด แต่มีเพียงรายการย่อยเท่านั้นที่กลายเป็นรายการกริด ลูก ๆ ของพวกเขากลับไปบล็อกเลย์เอาต์

กริดทำรัง

หากการ์ดมีเนื้อหามากกว่าการ์ดอื่นๆ การ์ดในแถวนั้นจะสูงขึ้น ค่าเริ่มต้นของการ align-items สำหรับรายการกริดคือ stretch การ์ดของเรายืดได้เต็มที่ อย่างไรก็ตาม รายการภายในอยู่ในบล็อกปกติและกระแสอินไลน์ ดังนั้นจึงไม่ยืดอย่างน่าอัศจรรย์เพื่อเติมการ์ด (นี่คือเหตุผลที่ในภาพด้านบน คุณจะเห็นว่าการ์ดที่มีเนื้อหาน้อยกว่าจะมีช่องว่างที่ด้านล่าง)

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

See the Pen [display: subgrid is not what we want](https://codepen.io/rachelandrew/pen/PvQzeG) โดย Rachel Andrew

ดูหน้าจอพร้อมปากกา: ตารางย่อยไม่ใช่สิ่งที่เราต้องการโดย Rachel Andrew

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

จัดเรียงส่วนหัวและส่วนท้าย

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

 .cards { display: grid; gap: 20px; grid-template-columns: 1fr 1fr 1fr; } article { display: grid; grid-template-rows: auto 1fr auto; row-gap: 20px; }

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

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

เราไม่มีวิธีแก้ปัญหาที่ดีในเบราว์เซอร์ในปัจจุบัน แต่กำลังดำเนินการอยู่ คุณลักษณะ Sub-grid ของ CSS Grid Layout ระดับ 2 จะเปิดใช้งานรูปแบบที่แน่นอนนี้ คุณจะสามารถสร้างกริดบนพาเรนต์แล้วเลือกแถวและ/หรือคอลัมน์เพื่อใช้กริดนั้น แทนที่จะกำหนดกริดใหม่บนองค์ประกอบ child ซึ่งไม่ขึ้นกับกริดนั้นโดยสมบูรณ์

โปรดทราบว่าตัวอย่างที่ตามมาใช้ได้เฉพาะในขณะที่เขียนใน Firefox Nightly ค่า sub-grid ของ grid-template-columns และ grid-template-rows เป็นคุณลักษณะใหม่และเป็นส่วนหนึ่งของระดับ 2 ของข้อกำหนด CSS Grid หากต้องการลองใช้คุณลักษณะนี้ ให้ดาวน์โหลดสำเนาของ Firefox Nightly

คุณสามารถดูวิธีการทำงานในภาพด้านล่าง ในภาพแรก ฉันได้สร้างแทร็กสามแถวบนพาเรนต์และขยายการ์ดไปทั่ว ด้วย Firefox Grid Inspector ที่ไฮไลต์ตาราง คุณจะเห็นว่าแถวของผู้ปกครองไม่เกี่ยวข้องกับแถวที่เด็กๆ ใช้

รูปภาพของตารางสามคอลัมน์ที่มีแทร็ก Firefox Grid Inspector ซ้อนทับ
การตรวจสอบกริดด้วย Firefox Grid Inspector แสดงว่าองค์ประกอบไม่แสดงในแทร็กของพาเรนต์ (ตัวอย่างขนาดใหญ่)

ถ้า แทนที่จะกำหนดสามแถวในกลุ่มย่อย ฉันใช้ค่า sub-grid สำหรับ grid-template-rows ตอนนี้การ์ดใช้แถวเหล่านั้นบนพาเรนต์ คุณสามารถดูว่าทั้งสองมีการจัดแนวกันอย่างไร ดังนั้นส่วนหัวและส่วนท้ายจึงจัดตำแหน่งด้วยเช่นกัน:

รูปภาพของตารางสามคอลัมน์ องค์ประกอบทั้งหมดภายในการ์ดถูกจัดแนว
การใช้ Sub-grid แต่ละส่วนของการ์ดจะเข้าสู่แทร็กของตัวเอง (ตัวอย่างขนาดใหญ่)

สิ่งที่เรากำลังทำกับ sub-grid ไม่ใช่ค่าใหม่ของ display รายการที่เป็น sub-grid คือคอนเทนเนอร์กริด ตามที่เราได้ตั้งค่า display: grid บนมัน รายการกริดทำงานเหมือนรายการกริดตามปกติ นี่คือเลย์เอาต์กริดปกติ — ไม่ต่างจากกริดที่ซ้อนกันดั้งเดิม ยกเว้นว่า (แทนที่จะเป็นรายการที่มีการปรับขนาดแทร็กของแถว) จะใช้แทร็กของพาเรนต์

 .cards { display: grid; gap: 20px; grid-template-columns: 1fr 1fr 1fr; grid-template-rows: repeat(2,auto 1fr auto); } article { grid-row-end: span 3; display: grid; grid-template-rows: subgrid; }

นี่คือสิ่งที่ดีเกี่ยวกับ sub-grid; ไม่มีอะไรมากให้เรียนรู้ถ้าคุณรู้วิธีใช้เค้าโครงกริดอยู่แล้ว คุณสามารถอ่านรายละเอียดอื่นๆ ได้ในโพสต์ก่อนหน้าของฉันที่ Smashing Magazine, “CSS Grid Level 2: Here Comes Subgrid”

เมื่อวานนี้ ( 23 พฤษภาคม 2019) Sub-grid เข้าสู่ Firefox Nightly ดังนั้นเราจึงมีการใช้งานที่ทดสอบได้ของค่า sub-grid ของ grid-template-columns และ grid-template-rows โปรดหยิบสำเนาของ Nightly และลองทำดู ด้วยสำเนาของ Nightly คุณสามารถดูตัวอย่างการทำงานขั้นสุดท้ายใน CodePen นี้:

ดูหน้าจอพร้อมปากกา: ตารางย่อยไม่ใช่สิ่งที่เราต้องการโดย Rachel Andrew

ดูหน้าจอพร้อมปากกา: ตารางย่อยไม่ใช่สิ่งที่เราต้องการโดย Rachel Andrew

ดูว่าคุณสามารถคิดกรณีการใช้งานอื่นๆ ที่แก้ไขได้ด้วยคุณสมบัติ sub-grid หรือบางทีสิ่งที่คุณคิดว่าขาดหายไป แม้ว่าคุณลักษณะจะพร้อมใช้งานในเบราว์เซอร์ Nightly เท่านั้น แต่นั่นเป็นเวลาที่สามารถทำการเปลี่ยนแปลงข้อมูลจำเพาะได้หากพบปัญหาบางอย่าง ดังนั้น ให้ช่วยเหลือตัวเองในการพัฒนาเว็บในอนาคต และลองใช้คุณลักษณะเช่นนี้ เพื่อที่จะสามารถช่วยสนับสนุนแพลตฟอร์มเว็บและทำให้สิ่งต่างๆ ดีขึ้นได้

หากคุณคิดว่าพบจุดบกพร่องในการใช้งาน Firefox คุณสามารถดูข้อบกพร่องในการใช้งานหลักใน Bugzilla ซึ่งเชื่อมโยงไปยังปัญหาที่เกี่ยวข้องได้ในส่วน ขึ้นอยู่กับ หากคุณไม่เห็นปัญหาของคุณ ให้สร้างกรณีทดสอบที่ลดขนาดให้เรียบง่ายที่สุดเท่าที่จะทำได้และแจ้งข้อบกพร่อง หากคุณคิดว่า sub-grid ควรทำบางสิ่งเพื่อแก้ไขกรณีการใช้งาน และนั่นไม่ใช่รายละเอียดในข้อมูลจำเพาะ คุณสามารถแจ้งปัญหาใน CSS Working Group GitHub เพื่อการปรับปรุงที่อาจเกิดขึ้นได้

What About display: contents ?

หากคุณได้ติดตาม คุณอาจคิดว่า display: contents (ตามที่อธิบายไว้ในบทความก่อนหน้าเกี่ยวกับ display ) อาจแก้ปัญหาที่ sub-grid พยายามแก้ไข นั่นคือการอนุญาตให้เด็กทางอ้อมมีส่วนร่วมในโครงร่างกริด นั่นไม่ใช่กรณี และตัวอย่างการ์ดของเราเป็นวิธีที่สมบูรณ์แบบในการแสดงความแตกต่าง

หากแทนที่จะทำให้การ์ดของเราเป็นเลย์เอาต์กริดด้วย display: grid เราเอากล่องนั้นออกโดยใช้ display: contents เราจะได้รับผลลัพธ์นี้ใน CodePen ถัดไป (ลองลบบรรทัด display: contents ออกจากกฎสำหรับ .card เพื่อดูความแตกต่าง)

ดูหน้าจอพร้อมปากกา: ตารางย่อยไม่ใช่สิ่งที่เราต้องการโดย Rachel Andrew

ดูหน้าจอพร้อมปากกา: ตารางย่อยไม่ใช่สิ่งที่เราต้องการโดย Rachel Andrew

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

การอ่านและตัวอย่างเพิ่มเติม

ฉันได้สร้างตัวอย่างและการสาธิตจำนวนมากเพื่อช่วยให้ทุกคนเข้าใจ sub-grid คุณสามารถทดลองใช้ได้ที่ลิงค์ด้านล่าง:

  • CSS Grid ระดับ 2 ตัวอย่าง
  • CSS Grid ระดับ 2: มาแล้ว Subgrid
  • กริดไปจนสุดทาง (การนำเสนอ)
  • เอกสาร MDN สำหรับ Subgrid