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

เผยแพร่: 30 เมษายน 2024, อัปเดตล่าสุด: 13 กุมภาพันธ์ 2026

ทีม Chrome ต้องการเห็นการติดตั้งใช้งานเลย์เอาต์ประเภทเมสันรีบน เว็บ อย่างไรก็ตาม เราคิดว่าการนำไปใช้เป็นส่วนหนึ่งของข้อกำหนด CSS Grid ตามที่เสนอในโพสต์ล่าสุดของ WebKit จะเป็นการตัดสินใจที่ผิดพลาด นอกจากนี้ เรายังรู้สึกว่าโพสต์ของ WebKit โต้แย้งกับเวอร์ชัน ของเลย์เอาต์แบบก้อนอิฐที่ไม่มีใครเสนอ

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

  • ทีม Chrome กระตือรือร้นที่จะปลดบล็อกเลย์เอาต์แบบก้อนอิฐเป็นอย่างมาก เราทราบดีว่านักพัฒนาซอฟต์แวร์ต้องการฟีเจอร์นี้
  • การเพิ่มการจัดวางแบบก่ออิฐลงในข้อกำหนดของกริดเป็นปัญหาด้วยเหตุผลอื่นๆ นอกเหนือจากว่าคุณคิดว่าการจัดวางแบบก่ออิฐเป็นกริดหรือไม่
  • การกำหนดเมสันนรี นอกข้อกำหนดของกริดไม่ได้ป้องกันขนาดแทร็กหลายขนาดสำหรับ เมสันนรี หรือการใช้พร็อพเพอร์ตี้ เช่น การจัดแนวหรือช่องว่าง หรือฟีเจอร์อื่นๆ ที่ใช้ในเลย์เอาต์กริด

ควรใช้การจัดวางแบบก้อนอิฐเป็นส่วนหนึ่งของตารางกริดไหม

ทีม Chrome เชื่อว่าเลย์เอาต์แบบเมสันควรเป็นวิธีการ เลย์เอาต์แยกกัน ซึ่งกำหนดโดยใช้ display: masonry (หรือคีย์เวิร์ดอื่นหากมีการตัดสินใจใช้ชื่อที่ดีกว่า) ในส่วนท้ายของโพสต์นี้ คุณจะเห็นตัวอย่างลักษณะของโค้ด

เราคิดว่าการกำหนดเลย์เอาต์แบบเมสันนารีภายนอกเลย์เอาต์กริดจะดีกว่าด้วยเหตุผล 2 ประการที่เกี่ยวข้อง ได้แก่ ปัญหาด้านประสิทธิภาพของเลย์เอาต์ที่อาจเกิดขึ้น และข้อเท็จจริงที่ว่าทั้งเลย์เอาต์แบบเมสันนารีและกริดมีฟีเจอร์ที่เหมาะกับเลย์เอาต์วิธีหนึ่ง แต่ไม่เหมาะกับอีกวิธีหนึ่ง

ประสิทธิภาพ

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

ดังนั้น หากคุณมีเลย์เอาต์แบบก้อนอิฐที่มีคำจำกัดความของแทร็กเป็น grid-template-columns: 200px auto 200px ซึ่งเป็นสิ่งที่พบบ่อยมากในตาราง คุณจะ เริ่มพบปัญหา ปัญหาเหล่านี้จะเพิ่มขึ้นแบบทวีคูณเมื่อคุณเพิ่ม ตารางย่อย

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

เราจะจัดการกับสิ่งที่ไม่สมเหตุสมผลในแต่ละวิธีการจัดเลย์เอาต์อย่างไร

เมื่อ Flexbox และ Grid กลายเป็นส่วนหนึ่งของ CSS นักพัฒนาซอฟต์แวร์มักรู้สึกว่าองค์ประกอบเหล่านี้ทำงานในลักษณะที่ไม่สอดคล้องกัน ความไม่สอดคล้องที่ผู้ใช้พบเกิดจากสมมติฐานที่ยึดถือมานานเกี่ยวกับวิธีการทำงานของเลย์เอาต์โดยอิงตามเลย์เอาต์ของบล็อก เมื่อเวลาผ่านไป นักพัฒนาแอปเริ่มเข้าใจบริบทการจัดรูปแบบ เมื่อเราเปลี่ยนไปใช้บริบทการจัดรูปแบบกริดหรือ Flex บางสิ่งจะทำงานแตกต่างออกไป เช่น คุณทราบว่าเมื่ออยู่ใน Flexbox จะมีวิธีการจัดแนวบางอย่างที่ไม่พร้อมใช้งาน เนื่องจาก Flexbox เป็นแบบ 1 มิติ

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

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

นอกจากนี้ยังมีรูปแบบที่สมเหตุสมผลในงานก่อสร้าง เช่น 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 รายการ
  • Grid ใช้คุณสมบัติทั้ง 6 รายการของ justify-* และ align-* ได้ แต่ Masonry ใช้เฉพาะชุดย่อย เช่น Flexbox

นอกจากนี้ ยังต้องระบุสิ่งที่เกิดขึ้นในกรณีข้อผิดพลาดใหม่ทั้งหมดที่เกิดจากนักพัฒนาแอปที่ใช้ค่าที่ไม่ถูกต้องใน grid-with-masonry หรือ grid-without-masonry เช่น คุณใช้ grid-template-columns: masonry หรือ grid-template-rows: masonry ได้ แต่จะใช้ทั้ง 2 อย่างพร้อมกันไม่ได้ จะเกิดอะไรขึ้นหากคุณใช้ทั้งสองอย่างพร้อมกัน คุณต้องระบุรายละเอียดเหล่านี้เพื่อให้เบราว์เซอร์ทั้งหมด ทํางานเหมือนกัน

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

ข้อเสนอทางเลือก

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

เลย์เอาต์การก่ออิฐแบบคลาสสิก

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

.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 แยกต่างหาก ซึ่งอาจใช้พร็อพเพอร์ตี้ masonry-track ซึ่งเป็นรูปแบบย่อของ masonry-track-start และ masonry-track-end เนื่องจากคุณมีมิติข้อมูลเพียงมิติเดียวที่จะ ครอบคลุมสิ่งต่างๆ เมื่ออยู่ในเลย์เอาต์แบบเมสันรี

.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 ที่ตรวจสอบโพสต์นี้และพูดคุยจนได้ข้อมูลมาเขียนโพสต์