การจัดรูปแบบเซลล์ว่างด้วยเนื้อหาที่สร้างและเค้าโครงกริด CSS
เผยแพร่แล้ว: 2022-03-10Gotcha เค้าโครงกริดทั่วไปคือเมื่อผู้มาใหม่ในวิธีการเลย์เอาต์สงสัยว่าจะจัดสไตล์เซลล์กริดที่ไม่มีเนื้อหาใด ๆ อย่างไร ในข้อกำหนดระดับ 1 ปัจจุบัน ไม่สามารถทำได้เนื่องจากไม่มีวิธีกำหนดเป้าหมายเซลล์กริดที่ว่างเปล่าหรือพื้นที่กริดและนำการจัดรูปแบบไปใช้ ซึ่งหมายความว่าหากต้องการใช้สไตล์ คุณจะต้องแทรกองค์ประกอบ
ในบทความนี้ ผมจะมาดูวิธีการใช้ CSS Generated Content เพื่อให้ได้สไตล์ของเซลล์ว่างโดยไม่ต้องเพิ่มองค์ประกอบว่างที่ซ้ำซาก และแสดงกรณีการใช้งานที่เทคนิคนี้เหมาะสม
มองใกล้ที่BFC
หากคุณเคยสร้างเลย์เอาต์ด้วย CSS คุณอาจรู้ว่า BFC คืออะไร การทำความเข้าใจว่าเหตุใดจึงใช้ได้ผลและวิธีสร้างจึงมีประโยชน์ และสามารถช่วยให้คุณเข้าใจวิธีการทำงานของเลย์เอาต์ใน CSS อ่านบทความที่เกี่ยวข้อง →
ทำไมเราไม่สามารถจัดรูปแบบพื้นที่ว่างได้แล้ว?
ย่อหน้าเริ่มต้นของข้อกำหนดกริดกล่าวว่า
“โมดูล CSS นี้กำหนดระบบเค้าโครงแบบกริดสองมิติ ซึ่งปรับให้เหมาะสมสำหรับการออกแบบส่วนต่อประสานกับผู้ใช้ ในแบบจำลองเค้าโครงกริด ลูกๆ ของคอนเทนเนอร์กริดสามารถวางตำแหน่งลงในสล็อตโดยพลการในกริดเลย์เอาต์ขนาดคงที่หรือยืดหยุ่นที่กำหนดไว้ล่วงหน้า”
วลีสำคัญที่นี่คือ "ลูกของคอนเทนเนอร์กริด" ข้อมูลจำเพาะกำหนดการสร้างกริดบนองค์ประกอบหลัก ซึ่งรายการย่อยสามารถวางตำแหน่งได้ มันไม่ได้กำหนดสไตล์ใดๆ ของกริดนั้น ไม่แม้แต่จะใช้งานบางอย่างเช่นคุณสมบัติ column-rule
ที่เรามีใน Multi-column Layout เราจัดรูปแบบไอเท็มย่อย ไม่ใช่ตัวกริด ซึ่งทำให้เราต้องมีองค์ประกอบบางอย่างเพื่อนำสไตล์นั้นไปใช้กับ
ใช้องค์ประกอบซ้ำซ้อนเป็นตะขอจัดแต่งทรงผม
วิธีหนึ่งในการแทรกบางสิ่งเพื่อจัดรูปแบบคือการแทรกองค์ประกอบที่ซ้ำซ้อนลงในเอกสาร เช่น สแปน หรือ div นักพัฒนามักจะไม่ชอบแนวคิดนี้ แม้ว่าพวกเขาจะได้เพิ่ม "ตัวตัดแถว" ที่ซ้ำซ้อนเพิ่มเติมมาหลายปีแล้ว เพื่อให้ได้เค้าโครงกริดโดยใช้การลอย บางทีองค์ประกอบที่ว่างเปล่าอย่างเห็นได้ชัดนั้นน่ารังเกียจมากกว่าความซ้ำซ้อนที่ซ่อนอยู่ขององค์ประกอบเสื้อคลุม!
องค์ประกอบที่ว่างเปล่าทั้งหมดจะกลายเป็นรายการกริด และสามารถมีพื้นหลังและเส้นขอบเพิ่มได้เช่นเดียวกับองค์ประกอบที่มีเนื้อหา ดังตัวอย่างนี้
ดูองค์ประกอบที่ว่างเปล่าของปากกากลายเป็นรายการกริด โดย Rachel Andrew (@rachelandrew) บน CodePen
Eric Meyer ในบทความ Faux Grid Tracks ในบทความ A List Apart ของเขา สนับสนุนให้ใช้องค์ประกอบ b
เป็นองค์ประกอบที่ซ้ำซ้อนที่คุณเลือก เนื่องจากไม่ได้ให้ความหมายเชิงความหมาย สั้นและค่อนข้างชัดเจนในมาร์กอัปเหมือนเบ็ด
การแทรกองค์ประกอบ div
หรือ b
เพิ่มเติมสองสามรายการไม่น่าจะเป็นอาชญากรรมที่ยิ่งใหญ่ที่สุดต่อมาร์กอัปที่ดีที่คุณเคยกระทำ ดังนั้นฉันจะไม่หลับใหลในการเลือกวิธีการนั้นหากจำเป็น การพัฒนาเว็บมักเกี่ยวข้องกับการเลือกแนวทางที่ไม่เหมาะสมน้อยที่สุดเพื่อให้งานสำเร็จลุล่วงไปจนกว่าจะมีการกำหนดวิธีแก้ปัญหาที่ดีกว่า ฉันชอบที่จะเก็บสไตล์ของฉันไว้ในที่เดียวถ้าเป็นไปได้ อย่างปลอดภัยในสไตล์ชีต หากไม่มีสิ่งใดเลย จะทำให้นำสไตล์กลับมาใช้ใหม่ได้ง่ายขึ้น โดยไม่จำเป็นต้องกังวลเกี่ยวกับมาร์กอัปที่จำเป็นเพิ่มเติม ด้วยเหตุนี้ ฉันจึงมักจะมองหาเนื้อหาที่สร้างขึ้น ซึ่งเป็นสิ่งที่ฉันคุ้นเคยมากจากงานที่ฉันทำการจัดรูปแบบหนังสือด้วย CSS ซึ่งคุณใช้เวลาส่วนใหญ่ในการทำงานกับคุณลักษณะนี้
การใช้เนื้อหาที่สร้างขึ้นเป็นตะขอสำหรับจัดแต่งทรงผม
CSS Generated Content ใช้ ::before
และ ::after
CSS pseudo-classes พร้อมกับคุณสมบัติ content
เพื่อแทรกเนื้อหาบางประเภทลงในเอกสาร แนวคิดในการแทรก เนื้อหา อาจทำให้คุณคิดว่านี่เป็นการแทรกข้อความ และแม้ว่าจะเป็นไปได้ แต่สำหรับวัตถุประสงค์ของเรา เราสนใจที่จะแทรก องค์ประกอบ ว่างเป็นลูกโดยตรงของ Grid Container ของเรา เมื่อใส่องค์ประกอบเข้าไป เราก็สามารถจัดรูปแบบได้
ในตัวอย่างด้านล่าง ฉันมีองค์ประกอบที่มี ซึ่งจะกลายเป็น Grid Container ของฉัน โดยมีองค์ประกอบอื่นซ้อนอยู่ภายใน ลูกโดยตรงคนเดียวนี้จะกลายเป็นรายการกริด ฉันได้กำหนดตารางสามคอลัมน์ ตารางสามแถวบนคอนเทนเนอร์ แล้ววางตำแหน่งรายการเดียวโดยใช้ Grid Lines ดังนั้นมันจึงอยู่ในเซลล์กริดตรงกลาง
<div class="grid"> <div class="item"></div> </div>
.grid { display: grid; grid-template-columns: 100px 100px 100px; grid-template-rows: 100px 100px 100px; grid-gap: 10px; } .grid > * { border: 2px solid rgb(137,153,175); } .item { grid-column: 2; grid-row: 2; }
หากเราดูตัวอย่างนี้โดยใช้ Firefox Grid Inspector เพื่อวาง Grid Lines เราจะเห็นว่าเซลล์ว่างอื่น ๆ ของกริดนั้นมีอยู่อย่างไร อย่างไรก็ตาม ในการเพิ่มพื้นหลังหรือเส้นขอบให้กับเซลล์เหล่านั้น เราจะต้องเพิ่มลูกเพิ่มเติม องค์ประกอบ ซึ่งเป็นสิ่งที่สร้างเนื้อหาเปิดใช้งานได้อย่างแน่นอน

ใน CSS ของฉัน ฉันเพิ่มสตริงว่าง ::before
และ ::after
my Grid Container สิ่งเหล่านี้จะกลายเป็น Grid Item และยืดออกเพื่อเติมคอนเทนเนอร์ทันที จากนั้นฉันก็เพิ่มสไตล์ที่ฉันต้องการสำหรับกล่อง ในกรณีนี้คือการเพิ่มสีพื้นหลัง และจัดตำแหน่งกล่องเหล่านั้นเหมือนกับที่ฉันทำกับรายการกริดทั่วไป
.grid::before { content: ""; background-color: rgb(214,232,182); grid-column: 3; grid-row: 1; } .grid::after { content: ""; background-color: rgb(214,232,182); grid-column: 1; grid-row: 3; }

ในเอกสารนี้เรายังมีองค์ประกอบย่อยเพียงองค์ประกอบเดียว องค์ประกอบการจัดรูปแบบที่ซ้ำซ้อนนั้นอยู่ภายใน CSS ซึ่งดูสมเหตุสมผลอย่างยิ่งเนื่องจากมีไว้เพื่อจุดประสงค์ในการจัดสไตล์เท่านั้น
ข้อจำกัดของแนวทางการสร้างเนื้อหา
ปัญหาที่ชัดเจนของแนวทางนี้จะชัดเจนขึ้นหากคุณตัดสินใจว่าต้องการจัดรูปแบบเซลล์กริดบนขวาและล่างซ้ายด้วย คุณสามารถใช้เนื้อหาที่สร้างขึ้นได้เพียงชิ้นเดียวที่ด้านบนและด้านล่างของคอนเทนเนอร์ ไม่อนุญาตให้ใช้องค์ประกอบ ::before
และ ::after
หลายรายการ วิธีการนี้ใช้ไม่ได้ผล หากคุณต้องการสร้างตารางหมากรุก CSS ด้วยตัวคุณเอง! หากคุณพบว่าคุณจำเป็นต้องจัดรูปแบบเซลล์ว่างเป็นจำนวนมาก สำหรับอนาคตอันใกล้ วิธีการ "ฟิลเลอร์ บี" ที่อธิบายข้างต้นน่าจะเป็นทางออกที่ดีที่สุดของคุณ
วิธีการสร้างเนื้อหาอาจสร้างความสับสนให้กับนักพัฒนาในอนาคตที่ทำงานในโครงการของคุณ เนื่องจากเรากำหนดเป้าหมายคอนเทนเนอร์ หากคุณใช้คลาสนั้นซ้ำที่อื่น มันจะนำเนื้อหาที่สร้างขึ้นมาด้วย สิ่งนี้จะมีประโยชน์หากคุณต้องการนั่นคือสิ่งที่คุณต้องการ ในตัวอย่างถัดไป เราได้เพิ่มเส้นตกแต่งด้านใดด้านหนึ่งของส่วนหัว ซึ่งสมเหตุสมผลที่ทุกอินสแตนซ์ของ h1
จะมีเส้นเหล่านั้น อย่างไรก็ตาม มันจะสับสนมากหากคุณไม่ทราบว่าสิ่งนี้จะเกิดขึ้น! บรรทัดความคิดเห็นเหนือกฎคอนเทนเนอร์จะช่วยได้ที่นี่ ฉันมักจะทำงานในไลบรารีรูปแบบ ซึ่งช่วยให้ส่วนประกอบเหล่านี้เป็นระเบียบเรียบร้อยในที่เดียว ทำให้ชัดเจนยิ่งขึ้นว่าจะเกิดอะไรขึ้นเมื่อใช้คลาสกับองค์ประกอบ
หัวเรื่องแฟนซี
เทคนิคการสร้างเนื้อหาที่ฉันโปรดปรานอย่างหนึ่งคือการจัดรูปแบบหัวเรื่อง ในอดีต ฉันต้องย้อนกลับไปยังรูปแบบส่วนหัวที่จะต้องมีการห่อเพิ่มเติมและแทร็กการกำหนดตำแหน่งที่แน่นอนเพื่อให้บรรลุ เมื่อเนื้อหามาจาก CMS มักจะเป็นไปไม่ได้ที่จะเพิ่ม Wrapper ที่ซ้ำซ้อนเหล่านั้น
ด้วย Grid และเนื้อหาที่สร้างขึ้น เราสามารถเพิ่มบรรทัดด้านใดด้านหนึ่งของส่วนหัวของเราโดยไม่ต้องเพิ่มมาร์กอัปเพิ่มเติม เส้นจะขยายและย่อตามพื้นที่ว่าง และจะถอยกลับไปเป็นส่วนหัวตรงกลางแบบธรรมดาเมื่อไม่มี Grid ในเบราว์เซอร์


มาร์กอัปของเราเป็นแบบง่ายๆ h1
<h1>My heading</h1>
ในกฎสำหรับ h1
ฉันสร้างตารางสามคอลัมน์ ค่าของ grid-template-columns
ให้แทร็ก 1fr
ด้วย auto
และ 1fr
สุดท้าย แทร็ก 1fr
สองแทร็กจะแชร์พื้นที่ว่างที่เหลืออยู่หลังจากที่ส่วนหัวได้ใช้พื้นที่ที่จำเป็นในแทร็กที่มีขนาด auto
ฉันเพิ่มคุณสมบัติ text-align
ด้วยค่า center
ตามลำดับกว่าหัวข้อของฉันถูกป้อนในเบราว์เซอร์ที่ไม่มีกริด
h1 { text-align: center; display: grid; grid-template-columns: 1fr auto 1fr; grid-gap: 20px; }
ตอนนี้เราเพิ่มเนื้อหาที่สร้างขึ้นเพื่อเพิ่มบรรทัดก่อนและหลังข้อความหัวข้อ ฉันรวมกฎเหล่านี้ในการสืบค้นคุณลักษณะ ดังนั้นเราจึงไม่ได้รับเนื้อหาที่สร้างขึ้นแปลก ๆ ในเบราว์เซอร์ที่ไม่มีเลย์เอาต์กริด
ตัวบรรทัดเองเป็นเส้นขอบของรายการที่สร้างขึ้น
@supports (display: grid) { h1:before, h1:after { content: ""; align-self: center; border-top: 1px solid #999; } }
นั่นคือทั้งหมดที่คุณต้องทำ! คุณสามารถใช้เทคนิคเดียวกันนี้เพื่อเพิ่มสไตล์ใดๆ หรือแม้แต่ไอคอนที่ทั้งสองด้านขององค์ประกอบ ด้านบนหรือด้านล่างขององค์ประกอบ การวางรายการของคุณลงในแทร็กแยกกัน คุณทราบดีว่าไม่มีทางที่รายการนั้นจะทับซ้อนข้อความส่วนหัวของคุณ ซึ่งมักจะเป็นปัญหาเมื่อพยายามทำสิ่งนี้ด้วยการวางตำแหน่งที่แน่นอน คุณยังได้รับประโยชน์จากวิธีการจัดเรียงรายการให้ตรงกันในตารางได้อย่างแม่นยำอีกด้วย
ดูตัวอย่างหัวข้อ Pen Generated Content โดย Rachel Andrew (@rachelandrew) บน CodePen
นี่เป็นตัวอย่างที่ดีของการปรับปรุงที่เป็นไปได้โดยใช้เลย์เอาต์กริด ซึ่งคุณสามารถใช้ประโยชน์ได้แม้ว่าคุณจะยังไม่พร้อมที่จะมุ่งหน้าสู่การออกแบบใหม่ครั้งใหญ่โดยใช้กริด มันย้อนกลับไปได้ดีมากในหัวข้อที่ตรงไปตรงมา ผู้ที่มีเบราว์เซอร์ที่รองรับจะได้รับการสัมผัสพิเศษ และทุกคนก็ได้รับเนื้อหา Eric Meyer ใช้วิธีที่คล้ายกัน โดยใช้เนื้อหาที่สร้างขึ้นเพื่อเพิ่มเครื่องหมายคำพูดที่จัดรูปแบบและกำหนดตำแหน่งได้ให้กับองค์ประกอบ blockquote
ด้วยคุณสมบัติเล็กๆ เหล่านี้ ฉันมักจะไม่คิดว่าฉันจะใช้ Grid Layout เมื่อฉันเริ่มคิดหาวิธีนำการออกแบบไปใช้ ฉันก็รู้ว่านี่คือวิธีการเลย์เอาต์ที่จะเลือก ด้วยเหตุผลนี้เอง ฉันจึงสนับสนุนให้ผู้คนอย่าคิดว่า Grid เป็นการจัดวางหน้าเหนือส่วนประกอบ หากคุณทำเช่นนั้น คุณอาจพลาดโอกาสมากมายที่สิ่งนี้สามารถช่วยได้
การเพิ่มพื้นหลังและเส้นขอบให้กับพื้นที่ของการออกแบบของคุณ
เรายังสามารถใช้เนื้อหาที่สร้างขึ้นเพื่อซ้อนรายการ ความจริงก็คือ มากกว่าหนึ่งรายการสามารถครอบครองเซลล์กริดหนึ่งๆ ซึ่งอาจรวมถึงรายการเหล่านั้นที่แทรกด้วยเนื้อหาที่สร้างขึ้น
ในตัวอย่างถัดไป ฉันมีการออกแบบที่มีเนื้อหาสองส่วนและรายการเต็มความกว้าง ด้านหลังเนื้อหาเป็นพื้นหลังซึ่งทำงานอยู่ใต้รายการแบบเต็มความกว้าง

มาร์กอัปมีคอนเทนเนอร์ที่มีส่วนและองค์ประกอบเต็มความกว้างเป็นลูกโดยตรง และฉันกำลังใช้การจัดวางแบบบรรทัดเพื่อวางรายการของฉันลงบนกริด
<article class="grid"> <section class="section1"> <p>…</p> </section> <div class="full-width"> <img src=“placeholder.jpg” alt=“Placeholder”> </div> <section class="section2"> <p>…</p> </section> </article>
.grid { display: grid; grid-template-columns: 1fr 20px 4fr 20px 1fr; grid-template-rows: auto 300px auto; grid-row-gap: 1em; } .section1 { grid-column: 3; grid-row: 1; } .section2 { grid-column: 3; grid-row: 3; } .full-width { grid-column: 1 / -1; grid-row: 2; background-color: rgba(214,232,182,.5); padding: 20px 0; }
นี่ทำให้ฉันมีเลย์เอาต์ที่มีรูปภาพเต็มความกว้างและวางเนื้อหาสองส่วน อย่างไรก็ตาม หากฉันเพิ่มพื้นหลังให้กับส่วนต่างๆ พื้นหลังจะหยุดเหนือ row-gap
ระหว่าง section
และรูปภาพขนาดเต็ม
.section { background-color: rgba(214,232,182,.3); border: 5px solid rgb(214,232,182); }

หากเราลบ grid-row-gap
และใช้ padding เพื่อสร้างช่องว่าง ก็จะไม่เปิดใช้งานเอฟเฟกต์ของพื้นหลังที่ทำงานภายใต้แผงแบบเต็มความกว้าง
นี่คือที่ที่เราสามารถใช้เนื้อหาที่สร้างขึ้น ฉันเพิ่มเนื้อหาที่สร้าง ::before
คอนเทนเนอร์กริด และกำหนดสีพื้นหลัง หากฉันไม่ทำอะไรเลย สิ่งนี้จะวางตำแหน่งเนื้อหาในเซลล์แรกของกริด
.grid::before { content: ""; background-color: rgba(214,232,182,.3); border: 5px solid rgb(214,232,182); }

จากนั้นฉันสามารถจัดตำแหน่งเนื้อหาโดยใช้การวางตำแหน่งตามบรรทัดเพื่อขยายพื้นที่ที่ควรแสดงสีพื้นหลัง
.grid::before { content: ""; background-color: rgba(214,232,182,.3); border: 5px solid rgb(214,232,182); grid-column: 2 / 5; grid-row: 1 / 4; }
คุณสามารถดูตัวอย่างที่สมบูรณ์ได้ใน CodePen นี้
ดูตัวอย่างพื้นหลังเนื้อหาที่สร้างด้วยปากกาโดย Rachel Andrew (@rachelandrew) บน CodePen
การควบคุมกองด้วย z-index
ในตัวอย่างข้างต้น เนื้อหาที่สร้างขึ้นจะถูกแทรกด้วย ::before
ซึ่งหมายความว่าองค์ประกอบอื่นๆ ตามมา ซึ่งอยู่ด้านล่างสุดของสแต็ก และจะแสดงด้านหลังเนื้อหาที่เหลือซึ่งเป็นตำแหน่งที่ฉันต้องการ คุณยังสามารถใช้ z-index
เพื่อควบคุมสแต็กได้อีกด้วย ลองเปลี่ยน ::before
ตัวเลือกเป็น ::after
พื้นหลังของเนื้อหาที่สร้างขึ้นตอนนี้อยู่เหนือทุกสิ่ง ดังที่คุณเห็นได้จากวิธีที่เส้นขอบวิ่งผ่านรูปภาพ เนื่องจากตอนนี้ได้กลายเป็นสิ่งสุดท้ายในคอนเทนเนอร์กริดแล้ว มันถูกทาสีล่าสุดและปรากฏ "อยู่ด้านบน"
ในการเปลี่ยนแปลงนี้ คุณต้องให้องค์ประกอบนี้มีคุณสมบัติ z-index
ต่ำกว่าสิ่งอื่นใด หากไม่มีสิ่งใดมีค่า z-index
สิ่งที่ง่ายที่สุดที่จะทำคือให้เนื้อหาที่สร้างขึ้นของคุณมี z-index
เป็น -1
สิ่งนี้จะทำให้เป็นสิ่งแรกในสแต็ก เนื่องจากเป็นรายการที่มี z-index
ต่ำที่สุด
.grid::after { z-index: -1; content: ""; background-color: rgba(214,232,182,.3); border: 5px solid rgb(214,232,182); grid-column: 2 / 5; grid-row: 1 / 4; }
การเพิ่มพื้นหลังในลักษณะนี้ไม่จำเป็นต้องจำกัดเพียงการวางพื้นหลังไว้ด้านหลังเนื้อหาของคุณเท่านั้น ความสามารถในการใส่บล็อกสีไว้เบื้องหลังการออกแบบของคุณอาจสร้างเอฟเฟกต์ที่น่าสนใจบางอย่างได้
นี่คือสิ่งที่ข้อกำหนดอาจแก้ไขได้ในอนาคตหรือไม่
การเพิ่มพื้นหลังและเส้นขอบทำให้รู้สึกเหมือนขาดคุณสมบัติในข้อกำหนด CSS Grid และเป็นสิ่งที่คณะทำงานได้พูดคุยกับสมาชิกหลายคนในชุมชน (หัวข้อสนทนาอยู่ใน GitHub)
หากคุณมีกรณีการใช้งานที่ไม่สามารถแก้ไขได้ง่ายๆ ด้วยเนื้อหาที่สร้างขึ้น ให้เพิ่มความคิดของคุณลงในชุดข้อความนั้น ความคิดเห็นและกรณีการใช้งานของคุณช่วยแสดงให้เห็นว่านักพัฒนาสนใจฟีเจอร์นี้ และยังช่วยให้มั่นใจว่าข้อเสนอครอบคลุมสิ่งที่คุณต้องทำ
ตัวอย่างเพิ่มเติม ได้โปรด!
หากบทความนี้สนับสนุนให้คุณทดลองใช้เนื้อหาที่สร้างขึ้น หรือหากคุณมีตัวอย่างแล้ว โปรดเพิ่มลงในความคิดเห็น ทุกคนยังใหม่ต่อการใช้กริดในการผลิต ดังนั้นจึงมีมากมาย “ ฉันไม่เคยคิดอย่างนั้น! ” ช่วงเวลาที่จะมีในขณะที่เรารวม Grid กับวิธีการจัดวางอื่น ๆ