ข้อเสนอทางเลือกสำหรับการก่ออิฐ CSS

ทีม 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 ที่ตรวจสอบโพสต์นี้และการสนทนาที่นำมาสู่โพสต์นี้