ทีม Chrome ต้องการเห็นการใช้เลย์เอาต์ประเภทภาพต่อกันบนเว็บ อย่างไรก็ตาม เราคิดว่าการนำไปใช้เป็นส่วนหนึ่งของข้อกำหนด CSS Grid ตามที่เสนอไว้ในโพสต์ล่าสุดของ WebKit นั้นไม่ถูกต้อง นอกจากนี้ เรายังรู้สึกว่าโพสต์ของ WebKit โต้แย้งกับเวอร์ชันของ Masonry ที่ไม่มีใครเสนอ
ดังนั้น โพสต์นี้มีจุดประสงค์เพื่ออธิบายว่าเหตุใดทีม Chrome จึงมีข้อกังวลเกี่ยวกับการใช้การจัดเรียงแบบอิฐในข้อกำหนดการจัดวางตาราง CSS และชี้แจงว่าข้อเสนอทางเลือกช่วยให้ทำสิ่งใดได้บ้าง โดยสรุป
- ทีม Chrome ต้องการเลิกบล็อกการแสดงภาพแบบเรียงต่อกันอย่างมาก เราทราบดีว่านี่เป็นสิ่งที่นักพัฒนาแอปต้องการ
- การเพิ่มการจัดเรียงแบบก่ออิฐในข้อกำหนดของตารางกริดเป็นปัญหาเนื่องจากเหตุผลอื่นๆ นอกเหนือจากการที่คุณคิดว่าการจัดเรียงแบบก่ออิฐเป็นตารางกริดหรือไม่
- การกําหนดภาพต่อกันนอกข้อกําหนดของตารางกริดไม่ได้ป้องกันไม่ให้มีแทร็กหลายขนาดสําหรับภาพต่อกัน หรือการใช้พร็อพเพอร์ตี้ เช่น การจัดแนวหรือช่องว่าง หรือฟีเจอร์อื่นๆ ที่ใช้ในเลย์เอาต์ตารางกริด
การแสดงภาพแบบเรียงต่อกันควรเป็นส่วนหนึ่งของตารางกริดไหม
ทีม Chrome เชื่อว่าการแสดงภาพแบบเรียงต่อกันควรเป็นวิธีการแสดงเลย์เอาต์แยกต่างหาก ซึ่งกำหนดโดยใช้ display: masonry
(หรือคีย์เวิร์ดอื่นหากมีชื่อที่ดีกว่า) คุณจะดูตัวอย่างลักษณะของโค้ดได้ในโพสต์นี้
มีเหตุผล 2 ข้อที่เกี่ยวข้องซึ่งทำให้เรารู้สึกว่าการเรียงแบบก่ออิฐควรกำหนดไว้นอกเลย์เอาต์ตารางกริด นั่นคือ ปัญหาด้านประสิทธิภาพของเลย์เอาต์ที่อาจเกิดขึ้น และข้อเท็จจริงที่ว่าทั้งการเรียงแบบก่ออิฐและตารางกริดมีฟีเจอร์ที่เหมาะกับเลย์เอาต์แบบหนึ่งแต่ไม่เหมาะกับอีกแบบหนึ่ง
ประสิทธิภาพ
ตารางกริดและการจัดเรียงแบบเรียงต่อกันจะตรงข้ามกันในแง่วิธีที่เบราว์เซอร์จัดการกับขนาดและตำแหน่ง เมื่อวางเลย์เอาต์ตารางกริด ระบบจะวางรายการทั้งหมดไว้ก่อนเลย์เอาต์ และเบราว์เซอร์จะทราบสิ่งที่อยู่ในแต่ละแทร็กอย่างละเอียด ซึ่งช่วยให้มีการปรับขนาดตามค่าเริ่มต้นที่ซับซ้อนซึ่งมีประโยชน์มากในตารางกริด เมื่อใช้การจัดเรียงแบบเรียงต่อกัน ระบบจะวางรายการตามเลย์เอาต์ และเบราว์เซอร์จะไม่ทราบว่าแต่ละแทร็กมีจำนวนรายการเท่าใด ปัญหานี้จะไม่เกิดขึ้นกับแทร็กขนาดตามจริงทั้งหมดหรือแทร็กขนาดคงที่ทั้งหมด แต่จะเกิดขึ้นหากคุณผสมแทร็กขนาดคงที่กับแทร็กขนาดตามจริง เบราว์เซอร์จึงต้องดำเนินการขั้นตอนก่อนการจัดวางเพื่อวางองค์ประกอบทุกรายการในทุกวิธีที่เป็นไปได้เพื่อรับการวัดผล ซึ่งกริดขนาดใหญ่จะทำให้เกิดปัญหาด้านประสิทธิภาพการจัดวาง
ดังนั้น หากคุณมีเลย์เอาต์แบบเรียงต่อกันที่มีการกำหนดแทร็กเป็น grid-template-columns: 200px auto 200px
ซึ่งเป็นเรื่องปกติมากในตารางกริด คุณจะเริ่มพบปัญหา ปัญหาเหล่านี้จะทวีความรุนแรงขึ้นเมื่อคุณเพิ่มตารางย่อย
มีการโต้แย้งว่าคนส่วนใหญ่จะไม่พบปัญหานี้ แต่เราทราบดีว่าผู้คนมีตารางเวลาขนาดใหญ่มาก เราไม่ต้องการให้อุปกรณ์มีขีดจำกัดในการใช้งานเมื่อมีแนวทางอื่น
เราจะทำอย่างไรกับสิ่งที่ไม่เหมาะสมในวิธีการจัดวางแต่ละวิธี
เมื่อ Flexbox และตารางกริดกลายเป็นส่วนหนึ่งของ CSS นักพัฒนาซอฟต์แวร์มักรู้สึกว่าองค์ประกอบเหล่านี้ทำงานอย่างไม่สอดคล้องกัน ความไม่สอดคล้องที่ผู้ใช้พบนั้นเกิดจากคําสมมติที่ยึดถือมาอย่างยาวนานเกี่ยวกับวิธีการทำงานของเลย์เอาต์ โดยอิงตามเลย์เอาต์บล็อก เมื่อเวลาผ่านไป นักพัฒนาแอปเริ่มเข้าใจบริบทการจัดรูปแบบ เมื่อเราเปลี่ยนไปใช้บริบทการจัดรูปแบบตารางกริดหรือ Flex สิ่งต่างๆ จะทำงานแตกต่างกัน เช่น คุณทราบว่าเมื่อใช้ Flexbox คุณจะใช้งานวิธีการจัดวางได้เพียงบางวิธีเท่านั้น เนื่องจาก Flexbox เป็นองค์ประกอบแบบ 1 มิติ
การรวมการจัดเรียงแบบเรียงต่อกันเป็นตารางกริดจะทำลายความเชื่อมโยงที่ชัดเจนนี้ระหว่างบริบทการจัดรูปแบบกับความพร้อมใช้งานของสิ่งต่างๆ เช่น พร็อพเพอร์ตี้การจัดแนว ซึ่งกำหนดไว้ในข้อกำหนดการจัดแนวกล่องตามบริบทการจัดรูปแบบ
หากเราตัดสินใจที่จะจัดการปัญหาด้านประสิทธิภาพที่ระบุไว้ก่อนหน้านี้ด้วยการทำให้การกำหนดแทร็กแบบผสมผสานระหว่างแทร็กแบบมีข้อมูลในตัวและแทร็กแบบคงที่ผิดกฎหมายในโฆษณาแบบเรียงต่อกัน คุณจะต้องทราบว่ารูปแบบที่พบได้ทั่วไปมากสำหรับเลย์เอาต์ตารางกริดจะใช้กับโฆษณาแบบเรียงต่อกันไม่ได้
นอกจากนี้ยังมีรูปแบบที่เหมาะกับงานก่อสร้าง เช่น grid-template-columns: repeat(auto-fill, max-content)
เนื่องจากคุณไม่มีข้อจำกัดแบบข้าม แต่ต้องยังคงใช้งานไม่ได้ในตารางกริด ต่อไปนี้คือรายการพร็อพเพอร์ตี้ที่เราคาดว่าจะทํางานต่างจากเดิมหรือมีค่าที่ถูกต้องแตกต่างกัน
grid-template-areas
: ในการจัดเรียงแบบก่ออิฐ คุณระบุได้เฉพาะแถวแรกในทิศทางที่ไม่ใช่การจัดเรียงแบบก่ออิฐgrid-template
: ตัวย่อจะต้องคำนึงถึงความแตกต่างทั้งหมด- ติดตามค่าการปรับขนาดสำหรับ
grid-template-columns
และgrid-template-rows
เนื่องจากค่าทางกฎหมายแตกต่างกัน grid-auto-flow
ไม่มีผลกับภาพต่อกันและmasonry-auto-flow
ไม่มีผลกับตารางกริด การผสานจะทำให้เกิดปัญหาเกี่ยวกับสิ่งต่างๆ ที่ไม่ถูกต้องเนื่องจากวิธีการเลย์เอาต์ที่คุณใช้อยู่- ตารางกริดมีพร็อพเพอร์ตี้ตําแหน่ง 4 รายการ (
grid-column-start
และอื่นๆ) ส่วนโฆษณาสื่อกลางแบบเรียงต่อกันมีเพียง 2 รายการ - ตารางกริดสามารถใช้พร็อพเพอร์ตี้
justify-*
และalign-*
ทั้ง 6 รายการ แต่ Masonry ใช้เฉพาะชุดย่อย เช่น Flexbox
นอกจากนี้ จะต้องมีข้อกำหนดให้ระบุสิ่งที่จะเกิดขึ้นในทุกกรณีข้อผิดพลาดใหม่ซึ่งเกิดจากนักพัฒนาแอปใช้ค่าที่ไม่ถูกต้องใน grid-with-masonry หรือ grid-without-masonry ตัวอย่างเช่น คุณใช้ grid-template-columns: masonry
หรือ grid-template-rows: masonry
ได้ แต่ใช้ทั้ง 2 อย่างพร้อมกันไม่ได้ จะเกิดอะไรขึ้นหากคุณใช้ทั้ง 2 อย่างพร้อมกัน
คุณต้องระบุรายละเอียดเหล่านี้เพื่อให้เบราว์เซอร์ทั้งหมดทําสิ่งเดียวกัน
ทั้งหมดนี้มีความซับซ้อนจากมุมมองข้อกำหนดเฉพาะ ทั้งในปัจจุบันและอนาคต เราต้องตรวจสอบว่าทุกอย่างคำนึงถึงการจัดเรียงแบบเรียงต่อกัน และดูว่าใช้งานได้หรือไม่ และสร้างความสับสนต่อมุมมองของนักพัฒนาแอปด้วย เหตุใดคุณจึงต้องจำไว้ว่าแม้จะใช้ display: grid
แต่บางสิ่งก็ใช้ไม่ได้เนื่องจากมีการใช้ Masonry
ข้อเสนอทางเลือก
ดังที่ได้กล่าวไปแล้ว ทีม Chrome ต้องการกำหนดรูปแบบการวางเรียงนอกเหนือข้อกำหนดของตารางกริด แต่ไม่ได้หมายความว่าจะต้องจำกัดรูปแบบเป็นวิธีการที่เรียบง่ายมากซึ่งมีขนาดคอลัมน์เหมือนกัน เดโมทั้งหมดในโพสต์ WebKit จะยังคงใช้งานได้
เลย์เอาต์แบบก่ออิฐแบบคลาสสิก
เมื่อพูดถึงการจัดเรียงแบบก่ออิฐ ผู้คนส่วนใหญ่จะนึกถึงเลย์เอาต์ที่มีคอลัมน์หลายคอลัมน์ที่มีขนาดเท่าๆ กัน ซึ่งจะกำหนดโดยใช้ CSS ต่อไปนี้ ซึ่งต้องใช้โค้ดที่มีบรรทัดน้อยกว่าเวอร์ชันที่รวมกลุ่มตารางกริดที่เทียบเท่า
.masonry {
display: masonry;
masonry-template-tracks: repeat(auto-fill, minmax(14rem, 1fr));
gap: 1rem;
}
ใช้การปรับขนาดแทร็กประเภทตารางกริดสำหรับความกว้างของคอลัมน์ที่แตกต่างกัน
นอกเหนือจากปัญหาที่กล่าวถึงก่อนหน้านี้เกี่ยวกับการผสมผสานขนาดแทร็กแบบกำหนดเองและแบบคงที่ คุณสามารถใช้ขนาดแทร็กทั้งหมดที่ต้องการจากตารางกริด เช่น ตัวอย่างจากบล็อกโพสต์ของ WebKit ซึ่งเป็นรูปแบบของคอลัมน์แคบและกว้างที่ซ้ำกัน
.masonry {
display: masonry;
masonry-template-tracks: repeat(auto-fill, minmax(8rem, 1fr) minmax(16rem, 2fr)) minmax(8rem, 1fr);
gap: 1rem;
}
การปรับขนาดแทร็กเพิ่มเติมสำหรับการก่ออิฐ
มีตัวเลือกการปรับขนาดแทร็กเพิ่มเติมที่เราไม่อนุญาตในตารางกริดเนื่องจากตารางกริดเป็นวิธีการจัดวางแบบ 2 มิติ ฟีเจอร์เหล่านี้มีประโยชน์ในการแสดงผลแบบเรียงต่อกัน แต่อาจทำให้เกิดความสับสนหากใช้งานในตารางกริดไม่ได้
การเติมแทร็กขนาด max-content
โดยอัตโนมัติ
.masonry {
display: masonry;
masonry-template-tracks: repeat(auto-fill, max-content);
gap: 1rem;
}
แทร็กขนาด auto
ที่ระบบจะเติมโดยอัตโนมัติ ซึ่งจะสร้างแทร็กขนาดเดียวกันโดยระบบจะปรับขนาดให้พอดีกับแทร็กที่มีขนาดใหญ่ที่สุด
.masonry {
display: masonry;
masonry-template-tracks: repeat(auto-fill, auto);
gap: 1rem;
}
อนุญาตให้เนื้อหาขยายไปตามคอลัมน์ และวางรายการในเลย์เอาต์แบบเรียงต่อกัน
คุณไม่จำเป็นต้องกำหนดให้เนื้อหาครอบคลุมหลายคอลัมน์ในข้อกำหนดของการจัดเรียงแบบเรียงต่อกันแยกต่างหาก ซึ่งอาจใช้พร็อพเพอร์ตี้ masonry-track
ซึ่งเป็นตัวย่อของ masonry-track-start
และ masonry-track-end
เนื่องจากคุณมีมิติข้อมูลเพียง 1 รายการที่จะใช้แสดงข้อมูลในเลย์เอาต์แบบเรียงต่อกัน
.masonry {
display: masonry;
masonry-template-tracks: repeat(auto-fill, auto);
}
.span-2 {
masonry-track: span 2; /* spans two columns */
}
.placed {
masonry-track: 2 / 5; /* covers tracks 2, 3, and 4 */
}
โครงสร้างย่อยหรือกริดย่อยที่ใช้รางโครงสร้างย่อย
ซึ่งอาจรองรับได้โดยใช้ข้อกำหนดการเรียงภาพแบบแยกต่างหาก โดยมีข้อจํากัดอีกครั้งว่าไม่อนุญาตให้ใช้แทร็กแบบผสมที่มีขนาดตามจริงและแบบคงที่ จะต้องกําหนดลักษณะของข้อมูลดังกล่าว เราไม่เห็นเหตุผลว่าทำไมวิธีนี้จะไม่ได้ผล
บทสรุป
เราต้องการทำให้ข้อกำหนดสามารถใช้งานได้ร่วมกัน อย่างไรก็ตาม เราต้องการดำเนินการในลักษณะที่ใช้งานได้ดีทั้งในตอนนี้และในอนาคต รวมถึงนักพัฒนาแอปสามารถเชื่อถือได้ วิธีเดียวที่จะจัดการกับปัญหาด้านประสิทธิภาพที่ระบุไว้คือการทําให้ปัญหาที่ 2 ซึ่งก็คือการมีส่วนของตารางที่ผิดกฎหมายในการจัดเรียงอิฐยิ่งแย่ลง เราคิดว่านั่นไม่ใช่วิธีแก้ปัญหาที่ดี โดยเฉพาะเมื่อคุณมีฟีเจอร์ตารางกริดทั้งหมดที่ต้องการได้ พร้อมกับแยกสิ่งต่างๆ ออกจากกันอย่างชัดเจน
หากมีความคิดเห็น โปรดเข้าร่วมการสนทนาในปัญหา 9041
ขอขอบคุณ Bramus, Tab Atkins-Bittner, Una Kravets, Ian Kilpatrick และ Chris Harrelson ที่ตรวจสอบโพสต์นี้และการสนทนาที่นำมาสู่โพสต์นี้