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

การแยกบล็อกนั้นคล้ายกับการแยกประเภทอื่นๆ ที่รู้จักกันดีอย่างการแยกบรรทัด หรือที่เรียกว่า "การแบ่งบรรทัด" องค์ประกอบในบรรทัดที่มีมากกว่า 1 คำ (โหนดข้อความ องค์ประกอบ <a>
ฯลฯ) และอนุญาตให้มีการแบ่งบรรทัดอาจแบ่งออกเป็นหลายส่วน แต่ละส่วนจะวางไว้ในกล่องบรรทัดที่แตกต่างกัน กล่องบรรทัดคือการแยกย่อหน้าย่อยในบรรทัด ซึ่งเทียบเท่ากับ fragmentainer สำหรับคอลัมน์และหน้าเว็บ
การแยกส่วนบล็อก LayoutNG
LayoutNGBlockFragmentation เป็นการเขียนเครื่องมือแยกส่วนสำหรับ LayoutNG ขึ้นใหม่ ซึ่งเปิดตัวครั้งแรกใน Chrome 102 ในแง่ของโครงสร้างข้อมูล รูปแบบนี้แทนที่โครงสร้างข้อมูลก่อน NG หลายรายการด้วยข้อมูลโค้ด NG ที่แสดงในต้นไม้ข้อมูลโค้ดโดยตรง
ตัวอย่างเช่น ตอนนี้เรารองรับค่า "avoid" สำหรับพร็อพเพอร์ตี้ CSS ของ "break-before" และ "break-after" ซึ่งช่วยให้ผู้เขียนหลีกเลี่ยงการแบ่งบรรทัดหลังส่วนหัวได้ หน้าเว็บมักจะดูไม่สมเหตุสมผลเมื่อสิ่งสุดท้ายในหน้าคือส่วนหัว ขณะที่เนื้อหาของส่วนนั้นเริ่มต้นในหน้าถัดไป คุณควรแบ่งบรรทัดก่อนส่วนหัว

นอกจากนี้ Chrome ยังรองรับการแยกส่วนเกินด้วย เพื่อไม่ให้ระบบตัดเนื้อหาแบบโมโนลิธิก (ควรจะเป็นเนื้อหาที่แบ่งไม่ได้) ออกเป็นหลายคอลัมน์ และใช้เอฟเฟกต์การวาด เช่น เงาและการแปลง ได้อย่างถูกต้อง
การแยกบล็อกใน LayoutNG เสร็จสมบูรณ์แล้ว
การแยกส่วนหลัก (คอนเทนเนอร์บล็อก ซึ่งรวมถึงเลย์เอาต์บรรทัด องค์ประกอบลอย และการจัดตำแหน่งนอกโฟลว์) ที่มาพร้อมกับ Chrome 102 การแยกส่วน Flex และตารางมีให้บริการใน Chrome 103 และการแยกส่วนตารางมีให้บริการใน Chrome 106 สุดท้ายคือการพิมพ์ที่มาพร้อมกับ Chrome 108 การแยกบล็อกเป็นชิ้นๆ เป็นฟีเจอร์สุดท้ายที่อาศัยเครื่องมือรุ่นเดิมในการจัดวาง
ตั้งแต่ Chrome 108 เป็นต้นไป ระบบจะไม่ใช้เครื่องมือเดิมในการจัดวางอีกต่อไป
นอกจากนี้ โครงสร้างข้อมูล LayoutNG ยังรองรับการวาดภาพและการทดสอบ Hit แต่เรายังใช้โครงสร้างข้อมูลเดิมบางอย่างสําหรับ JavaScript API ที่อ่านข้อมูลเลย์เอาต์ เช่น offsetLeft
และ offsetTop
การจัดวางทุกอย่างด้วย NG จะช่วยให้คุณติดตั้งใช้งานและเผยแพร่ฟีเจอร์ใหม่ๆ ที่มีเฉพาะการติดตั้งใช้งาน LayoutNG (และไม่มีการติดตั้งใช้งานของเครื่องมือรุ่นเดิม) เช่น CSS Container Query, การวางตำแหน่งจุดยึด, MathML และเลย์เอาต์ที่กำหนดเอง (Houdini) ได้ สำหรับคำค้นหาคอนเทนเนอร์ เราได้เปิดตัวไปก่อนเล็กน้อยพร้อมคำเตือนให้นักพัฒนาแอปทราบว่ายังไม่รองรับการพิมพ์
เราได้เปิดตัว LayoutNG ภาคแรกในปี 2019 ซึ่งประกอบด้วยเลย์เอาต์คอนเทนเนอร์บล็อกปกติ เลย์เอาต์ในบรรทัด การวางลอย และการวางตำแหน่งนอกโฟลว์ แต่ไม่รองรับ Flex, ตาราง หรือตาราง และไม่มีการรองรับการแยกบล็อก เราจะกลับไปใช้เครื่องมือการจัดวางเดิมสำหรับ Flex, ตาราง และอื่นๆ ที่เกี่ยวข้องกับการแยกบล็อก การดำเนินการนี้ใช้ได้กับองค์ประกอบแบบบล็อก แทรกในบรรทัด ลอย และอยู่นอกลำดับภายในเนื้อหาที่กระจัดกระจายด้วย ดังที่คุณเห็น การอัปเกรดเครื่องมือวางเลย์เอาต์ที่ซับซ้อนเช่นนี้ในเวอร์ชันปัจจุบันเป็นงานที่ละเอียดอ่อนมาก
นอกจากนี้ ภายในกลางปี 2019 เราได้ติดตั้งใช้งานฟังก์ชันหลักส่วนใหญ่ของเลย์เอาต์การแยกบล็อก LayoutNG แล้ว (อยู่เบื้องหลัง Flag) แล้วทำไมการจัดส่งจึงใช้เวลานานขนาดนี้ คำตอบสั้นๆ คือ การแยกส่วนต้องอยู่ร่วมกับส่วนต่างๆ เดิมของระบบอย่างถูกต้อง ซึ่งจะนําออกหรืออัปเกรดไม่ได้จนกว่าจะมีการอัปเกรดทรัพยากร Dependencies ทั้งหมด
การโต้ตอบของเครื่องมือรุ่นเดิม
โครงสร้างข้อมูลเดิมยังคงรับผิดชอบ JavaScript API ที่อ่านข้อมูลเลย์เอาต์ ดังนั้นเราจึงต้องเขียนข้อมูลกลับไปยังเครื่องมือเดิมในลักษณะที่เครื่องมือเข้าใจ ซึ่งรวมถึงการอัปเดตโครงสร้างข้อมูลหลายคอลัมน์เดิมอย่างถูกต้อง เช่น LayoutMultiColumnFlowThread
การตรวจหาและการจัดการเครื่องยนต์สำรองเดิม
เราต้องใช้เครื่องมือวางเลย์เอาต์เดิมเมื่อเนื้อหาภายในยังไม่ได้รับการจัดการโดยการจัดกลุ่มบล็อก LayoutNG ขณะจัดส่งการแยกส่วนบล็อก LayoutNG หลัก ซึ่งรวมถึง Flex, ตาราง, ตาราง และทุกอย่างที่พิมพ์ การดำเนินการนี้ค่อนข้างยุ่งยากเนื่องจากเราต้องตรวจหาความจำเป็นในการใช้การแสดงผลสำรองเดิมก่อนที่จะสร้างออบเจ็กต์ในลําดับชั้นเลย์เอาต์ ตัวอย่างเช่น เราต้องตรวจหาก่อนเพื่อดูว่ามีคอนเทนเนอร์บรรทัดแรกแบบหลายคอลัมน์หรือไม่ และก่อนที่จะทราบว่าโหนด DOM ใดจะกลายเป็นบริบทการจัดรูปแบบหรือไม่ ปัญหานี้คล้ายกับปัญหาไก่กับไข่ที่ไม่มีวิธีแก้ปัญหาที่สมบูรณ์แบบ แต่ตราบใดที่ลักษณะการทำงานที่ไม่ถูกต้องเพียงอย่างเดียวคือผลบวกลวง (กลับไปใช้รูปแบบเดิมเมื่อไม่จําเป็นจริงๆ) ก็ไม่เป็นไร เนื่องจากข้อบกพร่องในลักษณะการทํางานของเลย์เอาต์นั้นคือข้อบกพร่องที่ Chromium มีอยู่แล้ว ไม่ใช่ข้อบกพร่องใหม่
ทางเดินชมต้นไม้ก่อนทาสี
การเตรียมก่อนทาสีเป็นสิ่งที่เราทำหลังจากเลย์เอาต์ แต่ก่อนทาสี ปัญหาหลักคือเรายังคงต้องเดินต้นไม้ออบเจ็กต์เลย์เอาต์ แต่ตอนนี้เรามี NG แฟรกเมนต์แล้ว เราจะจัดการกับปัญหานี้อย่างไร เราจะเรียกใช้ทั้งออบเจ็กต์เลย์เอาต์และต้นไม้ของข้อมูลโค้ด NG พร้อมกัน ซึ่งค่อนข้างซับซ้อนเนื่องจากการแมประหว่าง 2 ต้นไม้นั้นไม่ใช่เรื่องง่าย
แม้ว่าโครงสร้างต้นไม้ออบเจ็กต์เลย์เอาต์จะคล้ายกับโครงสร้างต้นไม้ DOM แต่ต้นไม้เศษเป็นส่วนเอาต์พุตของเลย์เอาต์ ไม่ใช่อินพุตของเลย์เอาต์ นอกจากแสดงถึงผลของการแยกส่วนต่างๆ ซึ่งรวมถึงการแยกส่วนในบรรทัด (ข้อมูลโค้ดบรรทัด) และการแยกส่วนบล็อก (ข้อมูลโค้ดคอลัมน์หรือหน้าเว็บ) แล้ว ต้นไม้ข้อมูลโค้ดยังแสดงความสัมพันธ์แบบพ่อแม่-ลูกโดยตรงระหว่างบล็อกที่บรรจุกับ DOM สืบทอดที่มีข้อมูลโค้ดนั้นเป็นบล็อกที่บรรจุ ตัวอย่างเช่น ในต้นไม้ของข้อมูลโค้ดที่ติดทั่วเว็บไซต์ ข้อมูลโค้ดที่สร้างขึ้นโดยองค์ประกอบที่มีการวางตำแหน่งแบบสัมบูรณ์จะเป็นข้อมูลโค้ดย่อยโดยตรงของข้อมูลโค้ดบล็อกที่บรรจุ แม้ว่าจะมีโหนดอื่นๆ ในเชนลำดับชั้นระหว่างข้อมูลโค้ดที่วางตำแหน่งไว้นอกกระแสกับบล็อกที่บรรจุก็ตาม
ปัญหาอาจซับซ้อนยิ่งขึ้นเมื่อมีองค์ประกอบที่มีตำแหน่งอยู่นอกโฟลว์ภายในการแยกส่วน เนื่องจากจะทำให้กลุ่มที่อยู่นอกโฟลว์กลายเป็นองค์ประกอบย่อยโดยตรงของ div ที่ใช้แยกส่วน (และไม่ใช่องค์ประกอบย่อยของสิ่งที่ CSS คิดว่าเป็นบล็อกที่บรรจุ) ปัญหานี้จำเป็นต้องได้รับการแก้ไขเพื่อให้ทำงานร่วมกับเครื่องมือเดิมได้ ในอนาคต เราน่าจะทำให้โค้ดนี้เข้าใจง่ายขึ้นได้ เนื่องจาก LayoutNG ออกแบบมาเพื่อรองรับโหมดเลย์เอาต์สมัยใหม่ทั้งหมดอย่างยืดหยุ่น
ปัญหาเกี่ยวกับเครื่องมือการแยกส่วนเดิม
เครื่องมือรุ่นเดิมที่ออกแบบมาในยุคแรกๆ ของเว็บไม่มีแนวคิดเรื่องการแยกส่วน แม้ว่าในเชิงเทคนิคแล้วจะมีอยู่แล้วในยุคนั้น (เพื่อรองรับการพิมพ์) การรองรับการแยกส่วนเป็นเพียงสิ่งที่เพิ่มเข้ามา (การพิมพ์) หรือติดตั้งเพิ่ม (หลายคอลัมน์)
เมื่อวางเลย์เอาต์เนื้อหาที่แบ่งออกเป็นส่วนๆ เครื่องมือรุ่นเดิมจะวางเลย์เอาต์ทุกอย่างเป็นแถบแนวตั้งที่มีความกว้างเท่ากับขนาดในบรรทัดของคอลัมน์หรือหน้าเว็บ และความสูงเท่ากับความสูงที่จำเป็นในการบรรจุเนื้อหา แถบแนวตั้งนี้จะไม่แสดงผลในหน้าเว็บ คุณสามารถจินตนาการได้ว่าเป็นการแสดงผลในหน้าเสมือนจริงซึ่งจะจัดเรียงใหม่เพื่อการแสดงผลขั้นสุดท้าย แนวคิดนี้คล้ายกับการพิมพ์บทความหนังสือพิมพ์ทั้งฉบับลงในคอลัมน์เดียว แล้วใช้กรรไกรตัดเป็นหลายส่วนในขั้นตอนที่ 2 (สมัยก่อน หนังสือพิมพ์บางฉบับใช้เทคนิคที่คล้ายกับเทคนิคนี้จริงๆ)
เครื่องมือเดิมจะติดตามขอบเขตหน้าเว็บหรือคอลัมน์สมมติในแถบ ซึ่งช่วยให้ระบบสามารถเลื่อนเนื้อหาที่เกินขอบเขตไปยังหน้าหรือคอลัมน์ถัดไปได้ ตัวอย่างเช่น หากมีเพียงครึ่งบนของบรรทัดเท่านั้นที่พอดีกับสิ่งที่เครื่องมือคิดว่าเป็นหน้าปัจจุบัน เครื่องมือจะแทรก "แถบแบ่งหน้า" เพื่อดันเนื้อหาลงไปยังตำแหน่งที่เครื่องมือคิดว่าเป็นด้านบนของหน้าถัดไป จากนั้นการแบ่งเนื้อหาออกเป็นส่วนๆ จริงส่วนใหญ่ ("การตัดด้วยกรรไกรและการวาง") จะเกิดขึ้นหลังจากเลย์เอาต์ในช่วงก่อนการวาดภาพและวาดภาพ โดยการตัดแถบเนื้อหาแนวตั้งออกเป็นหน้าหรือคอลัมน์ (โดยการตัดและแปลบางส่วน) ซึ่งทำให้การดำเนินการบางอย่างเป็นไปไม่ได้ เช่น การใช้การเปลี่ยนรูปแบบและการวางตำแหน่งแบบสัมพัทธ์หลังจากการแยกส่วน (ตามที่ข้อกำหนดระบุไว้) นอกจากนี้ แม้ว่าเครื่องยนต์เดิมจะรองรับการแยกตารางบางส่วน แต่ก็ไม่รองรับการแยก Flex หรือตารางกริดเลย
ต่อไปนี้คือภาพแสดงวิธีที่เลย์เอาต์ 3 คอลัมน์แสดงภายในในเครื่องมือรุ่นเดิม ก่อนที่จะใช้กรรไกร การวาง และกาว (เรากำหนดความสูงไว้เพื่อให้มีเพียง 4 บรรทัดเท่านั้นที่พอดี แต่จะมีพื้นที่เหลืออยู่ด้านล่าง)

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

คุณเห็นไหมว่าระบบตัดเงาข้อความจากบรรทัดในคอลัมน์แรกออก และวางไว้ที่ด้านบนของคอลัมน์ที่ 2 แทน เนื่องจากเครื่องมือวางเลย์เอาต์เดิมไม่เข้าใจการแยกส่วน
ซึ่งควรมีลักษณะดังนี้
ต่อไปเราจะเพิ่มความซับซ้อนขึ้นด้วยการใช้การแปลงและ box-shadow โปรดสังเกตว่าในเครื่องมือรุ่นเดิมมีการตัดที่ไม่ถูกต้องและการเลอะของคอลัมน์ นั่นเป็นเพราะตามข้อกำหนดแล้ว การเปลี่ยนรูปแบบควรใช้กับเอฟเฟกต์หลังการจัดวางและหลังการแยกส่วน เมื่อใช้การแยกส่วน LayoutNG ทั้ง 2 รายการจะทํางานได้อย่างถูกต้อง ซึ่งจะช่วยเพิ่มการทำงานร่วมกันกับ Firefox ที่รองรับการแยกส่วนมาอย่างยาวนานและผ่านการทดสอบส่วนใหญ่ในพื้นที่นี้ด้วย
เครื่องมือเดิมยังมีปัญหากับเนื้อหาแบบโมโนลิธิคสูงด้วย เนื้อหาเป็นเนื้อหาแบบโมโนลิธิกหากไม่มีสิทธิ์แบ่งออกเป็นหลายส่วน องค์ประกอบที่มีการเลื่อนแบบแสดงผลเกินจะมีลักษณะเป็นชิ้นเดียว เนื่องจากผู้ใช้จะเลื่อนในบริเวณที่ไม่ใช่สี่เหลี่ยมผืนผ้าไม่ได้ กล่องบรรทัดและรูปภาพเป็นตัวอย่างอื่นๆ ของเนื้อหาแบบโมโนลิธิก เช่น
หากเนื้อหาแบบโมโนลิธิคสูงเกินกว่าที่จะใส่ในคอลัมน์ได้ เครื่องมือรุ่นเดิมจะตัดเนื้อหานั้นอย่างรุนแรง (ซึ่งทําให้ลักษณะการทํางาน "น่าสนใจ" มากเมื่อพยายามเลื่อนคอนเทนเนอร์ที่เลื่อนได้)
แทนที่จะปล่อยให้ข้อมูลแสดงเกินคอลัมน์แรก (เช่นเดียวกับการแยกส่วนบล็อก LayoutNG)
เครื่องมือรุ่นเดิมรองรับช่วงพักแบบบังคับ เช่น <div style="break-before:page;">
จะแทรกตัวแบ่งหน้าก่อน DIV แต่รองรับการค้นหาการแบ่งแบบไม่บังคับที่เหมาะสมเพียงบางส่วนเท่านั้น รองรับ break-inside:avoid
และบรรทัดแรกและบรรทัดสุดท้าย แต่ไม่รองรับการหลีกเลี่ยงการแบ่งบรรทัดระหว่างบล็อก เช่น หากขอผ่าน break-before:avoid
ลองดูตัวอย่างนี้
ในที่นี้ องค์ประกอบ #multicol
มีที่ว่างสำหรับ 5 บรรทัดในแต่ละคอลัมน์ (เนื่องจากมีความสูง 100 พิกเซลและบรรทัดสูง 20 พิกเซล) ดังนั้น #firstchild
ทั้งหมดจึงพอดีกับคอลัมน์แรก แต่รายการพี่น้อง #secondchild
มี break-before:avoid ซึ่งหมายความว่าเนื้อหาไม่ต้องการให้มีช่วงพักระหว่างรายการ เนื่องจากค่าของ widows
คือ 2 เราจึงต้องส่ง #firstchild
2 บรรทัดไปยังคอลัมน์ที่ 2 เพื่อดำเนินการตามคำขอหลีกเลี่ยงช่วงพักทั้งหมด Chromium เป็นเครื่องมือเบราว์เซอร์แรกที่รองรับการผสมผสานฟีเจอร์นี้อย่างเต็มรูปแบบ
วิธีการทำงานของการแยก NG
โดยทั่วไปแล้ว เครื่องมือจัดวาง NG จะวางเลย์เอาต์เอกสารโดยการไปยังส่วนต่างๆ ของต้นไม้กล่อง CSS ตามลําดับชั้น เมื่อวางตำแหน่งโหนดที่สืบทอดทั้งหมดแล้ว เลย์เอาต์ของโหนดนั้นจะเสร็จสมบูรณ์โดยการสร้าง NGPhysicalFragment และกลับไปที่อัลกอริทึมเลย์เอาต์หลัก อัลกอริทึมดังกล่าวจะเพิ่มข้อมูลโค้ดนั้นลงในรายการข้อมูลโค้ดย่อย และเมื่อสร้างข้อมูลโค้ดย่อยทั้งหมดแล้ว ก็จะสร้างข้อมูลโค้ดสําหรับตัวเองโดยรวมข้อมูลโค้ดย่อยทั้งหมดไว้ด้วย วิธีนี้จะสร้างต้นไม้ของข้อมูลโค้ดสำหรับทั้งเอกสาร อย่างไรก็ตาม นี่เป็นวิธีที่เข้าใจง่ายเกินไป เช่น องค์ประกอบที่มีตำแหน่งอยู่นอกโฟลว์จะต้องส่งผ่านจากตำแหน่งที่แสดงในต้นไม้ DOM ไปยังบล็อกที่บรรจุไว้ก่อนจึงจะวางเลย์เอาต์ได้ เราจะไม่พูดถึงรายละเอียดขั้นสูงนี้เพื่อความเรียบง่าย
นอกจากกล่อง CSS เองแล้ว LayoutNG ยังจัดสรรพื้นที่ข้อจำกัดให้กับอัลกอริทึมการจัดวางด้วย ซึ่งจะระบุข้อมูลแก่อัลกอริทึม เช่น พื้นที่ว่างสำหรับเลย์เอาต์ การสร้างบริบทการจัดรูปแบบใหม่หรือไม่ และผลลัพธ์ของการยุบระยะขอบกลางจากเนื้อหาก่อนหน้า พื้นที่ข้อจำกัดจะทราบขนาดบล็อกที่วางไว้ของเครื่องมือแยกส่วน และระยะห่างของออฟเซ็ตบล็อกปัจจุบันในนั้นด้วย ซึ่งระบุตำแหน่งที่จะหยุด
เมื่อมีการแยกบล็อก เลย์เอาต์ของรายการที่สืบทอดต้องหยุดที่ช่วงพัก สาเหตุของการแบ่งบรรทัด ได้แก่ พื้นที่ในหน้าหรือคอลัมน์ไม่เพียงพอ หรือมีการบังคับให้แบ่งบรรทัด จากนั้นเราจะสร้างข้อมูลโค้ดที่ตัดตอนมาสำหรับโหนดที่เราเข้าชม และแสดงผลทั้งหมดจนถึงรูทบริบทการแยกส่วน (คอนเทนเนอร์หลายคอลัมน์ หรือรูทเอกสารในกรณีของการแสดงผล) จากนั้นที่รูทบริบทการแยกส่วน เราจะเตรียมตัวสำหรับตัวแยกส่วนใหม่ และลงไปที่ต้นไม้อีกครั้ง โดยกลับมาทำงานต่อจากจุดที่เราหยุดไว้ก่อนช่วงพัก
โครงสร้างข้อมูลที่สําคัญสําหรับระบุวิธีกลับมาแสดงเลย์เอาต์ต่อหลังจากหยุดพักเรียกว่า NGBlockBreakToken ซึ่งจะมีข้อมูลทั้งหมดที่จําเป็นต่อการจัดวางต่ออย่างถูกต้องใน Continuation รายการถัดไป NGBlockBreakToken จะเชื่อมโยงกับโหนด และสร้างเป็นต้นไม้ NGBlockBreakToken เพื่อให้แสดงโหนดแต่ละโหนดที่ต้องกลับมาทำงานต่อ NGBlockBreakToken จะแนบอยู่กับ NGPhysicalBoxFragment ที่สร้างขึ้นสำหรับโหนดที่ตัดภายใน ระบบจะส่งต่อโทเค็นการหยุดไปยังรายการหลัก ซึ่งจะสร้างเป็นต้นไม้ของโทเค็นการหยุด หากเราต้องแบ่งหน้าก่อนโหนด (แทนที่จะแบ่งหน้าภายในโหนด) ระบบจะไม่สร้างข้อมูลโค้ด แต่โหนดหลักยังคงต้องสร้างโทเค็นการแบ่งหน้า "break-before" สำหรับโหนด เพื่อให้เราเริ่มวางเลย์เอาต์ได้เมื่อไปถึงตําแหน่งเดียวกันในต้นไม้โหนดในรายการข้อมูลโค้ดถัดไป
ระบบจะแทรกช่วงพักเมื่อพื้นที่โฆษณาในโฆษณาแบบเป็นกลุ่มเหลือน้อย (ช่วงพักที่ไม่บังคับ) หรือเมื่อมีการขอช่วงพักแบบบังคับ
ข้อกำหนดมีกฎสำหรับการแบ่งบรรทัดที่เหมาะสมที่สุด และการวางการแบ่งบรรทัดตรงที่พื้นที่ไม่เพียงพอนั้นไม่ใช่วิธีที่เหมาะสมเสมอไป เช่น มีพร็อพเพอร์ตี้ CSS ต่างๆ เช่น break-before
ที่ส่งผลต่อการเลือกตำแหน่งการแบ่งบรรทัด
ในระหว่างการจัดวาง เราจำเป็นต้องติดตามจุดพักที่เหมาะสมเพื่อใช้ส่วนข้อกำหนดการหยุดพักที่ไม่บังคับอย่างถูกต้อง ระเบียนนี้หมายความว่าเราสามารถย้อนกลับไปใช้จุดหยุดพักที่ดีที่สุดที่พบล่าสุดได้ หากพื้นที่โฆษณาหมดลง ณ จุดที่เราละเมิดคําขอหลีกเลี่ยงช่วงพัก (เช่น break-before:avoid
หรือ orphans:7
) โดยแต่ละจุดหยุดพักที่เป็นไปได้จะได้รับคะแนนตั้งแต่ "ใช้ในกรณีที่ไม่มีทางเลือกอื่น" ไปจนถึง "จุดพักที่เหมาะที่สุด" โดยมีค่าบางส่วนอยู่ตรงกลาง หากตำแหน่งหยุดพักได้คะแนนเป็น "ยอดเยี่ยม" หมายความว่าจะไม่มีกฎการหยุดพักใดๆ ที่ถูกละเมิดหากเราหยุดพักที่จุดนั้น (และหากได้คะแนนนี้ตรงจุดที่เรามีพื้นที่ไม่เพียงพอแล้ว ก็ไม่จำเป็นต้องมองหาจุดอื่นที่ดีกว่า) หากคะแนนเป็น "ทางเลือกสุดท้าย" แสดงว่าจุดหยุดพักนั้นไม่ถูกต้อง แต่เราอาจยังหยุดพักที่จุดนั้นหากไม่พบจุดที่ดีกว่า เพื่อหลีกเลี่ยงการประมวลผลที่มากเกินไป
โดยปกติแล้ว จุดพักที่ถูกต้องจะเกิดขึ้นระหว่างองค์ประกอบพี่น้อง (กล่องบรรทัดหรือบล็อก) เท่านั้น และจะไม่เกิดขึ้นระหว่างองค์ประกอบหลักกับองค์ประกอบย่อยแรก (จุดพักระดับ C จะเป็นข้อยกเว้น แต่เราไม่จำเป็นต้องพูดถึงจุดพักเหล่านั้นที่นี่) ตัวอย่างเช่น มีจุดหยุดพักที่ถูกต้องก่อนบล็อกพี่น้องที่มี break-before:avoid แต่อยู่ในช่วงระหว่าง "สมบูรณ์แบบ" กับ "ทางเลือกสุดท้าย"
ในระหว่างการจัดวาง เราจะติดตามจุดพักที่ดีที่สุดที่พบจนถึงตอนนี้ในโครงสร้างที่เรียกว่า NGEarlyBreak การหยุดกลางคันก่อนเวลาอันควรคือจุดหยุดพักที่เป็นไปได้ก่อนหรือภายในโหนดบล็อก หรือก่อนบรรทัด (บรรทัดคอนเทนเนอร์บล็อกหรือบรรทัด Flex) เราอาจสร้างเชนหรือเส้นทางของออบเจ็กต์ NGEarlyBreak ในกรณีที่จุดหยุดพักที่ดีที่สุดอยู่ลึกเข้าไปในสิ่งที่เราเคยผ่านมาก่อนหน้านี้เมื่อพื้นที่ไม่เพียงพอ เช่น
ในกรณีนี้ เรามีเนื้อที่ไม่เพียงพอก่อน #second
แต่มี "break-before:avoid" ซึ่งได้คะแนนตำแหน่งการหยุดพักเป็น "ละเมิดการหลีกเลี่ยงการหยุดพัก" เมื่อถึงจุดนั้น เราจะมีเชน NGEarlyBreak ของ "inside #outer
> inside #middle
> inside #inner
> before "line 3"' พร้อม "perfect" เราจึงควรหยุดพักที่นั่น ดังนั้นเราต้องกลับไปและเรียกใช้เลย์เอาต์อีกครั้งตั้งแต่ต้นของ #outer (และครั้งนี้ให้ส่ง NGEarlyBreak ที่พบ) เพื่อให้เราหยุดก่อน "บรรทัดที่ 3" ใน #inner ได้ (เราแบ่งบรรทัดก่อน "บรรทัด 3" เพื่อให้บรรทัดที่เหลือ 4 บรรทัดไปอยู่ในตัวแบ่งกลุ่มถัดไป และเพื่อรักษา widows:4
)
อัลกอริทึมออกแบบมาเพื่อแบ่งกลุ่มที่จุดพักที่ดีที่สุดเสมอตามที่ระบุไว้ในข้อมูลจำเพาะ โดยวางกฎตามลําดับที่ถูกต้อง หากไม่สามารถใช้กฎทั้งหมดได้ โปรดทราบว่าเราจะต้องจัดเรียงใหม่เพียงครั้งเดียวต่อขั้นตอนการแยกส่วน เมื่อเราอยู่ในรอบที่ 2 ของการจัดวาง ระบบจะส่งตำแหน่งการแบ่งที่ดีที่สุดไปยังอัลกอริทึมการจัดวางแล้ว ซึ่งเป็นตำแหน่งการแบ่งที่ค้นพบในรอบที่ 1 ของการจัดวาง และระบุไว้เป็นส่วนหนึ่งของเอาต์พุตการจัดวางในรอบนั้น ในการจัดวางครั้งที่ 2 เราจะไม่จัดวางจนกว่าพื้นที่จะหมด จริงๆ แล้วเราไม่ได้คาดหวังว่าพื้นที่จะหมด (เพราะนั่นจะเป็นข้อผิดพลาด) เนื่องจากเรามีพื้นที่ที่ยอดเยี่ยม (ยอดเยี่ยมที่สุดเท่าที่มี) ในการแทรกการแบ่งบรรทัดก่อนถึงจุดสิ้นสุดเพื่อหลีกเลี่ยงการละเมิดกฎการแบ่งบรรทัดโดยไม่จำเป็น เราจึงอธิบายถึงจุดนั้นและหยุดพัก
ด้วยเหตุนี้ เราจึงจำเป็นต้องละเมิดคำขอหลีกเลี่ยงช่วงพักโฆษณาบางรายการในบางครั้ง หากจะช่วยหลีกเลี่ยงการประมวลผลโฆษณาแบบเศษส่วนมากเกินไป เช่น
ในกรณีนี้ พื้นที่ไม่เพียงพอก่อน #second
แต่มี "break-before:avoid" ซึ่งแปลว่า "ละเมิดการหลีกเลี่ยงช่วงพัก" เช่นเดียวกับตัวอย่างสุดท้าย นอกจากนี้ เรายังมี NGEarlyBreak ที่มี "การละเมิดบรรทัดแรกและบรรทัดสุดท้าย" (ภายใน #first
> ก่อน "บรรทัด 2") ซึ่งยังคงไม่สมบูรณ์แบบ แต่ดีกว่า "การละเมิดการหลีกเลี่ยงการแบ่งบรรทัด" ดังนั้นเราจะแบ่งบรรทัดก่อน "บรรทัดที่ 2" ซึ่งละเมิดคําขอบรรทัดแรก / บรรทัดสุดท้าย ข้อกำหนดจะกล่าวถึงเรื่องนี้ใน 4.4 การแบ่งที่ไม่บังคับ ซึ่งจะกำหนดว่าระบบจะละเว้นกฎการแบ่งบรรทัดใดก่อนหากเรามีจุดหยุดพักไม่เพียงพอที่จะหลีกเลี่ยงการแยกออกเป็นหลายส่วนมากเกินไป
บทสรุป
เป้าหมายด้านฟังก์ชันการทำงานของโปรเจ็กต์การแยกส่วนบล็อก LayoutNG คือเพื่อให้การติดตั้งใช้งานที่รองรับสถาปัตยกรรม LayoutNG ของทุกอย่างที่เครื่องมือเดิมรองรับ และดำเนินการอื่นๆ น้อยที่สุดเท่าที่จะเป็นไปได้ นอกเหนือจากการแก้ไขข้อบกพร่อง ข้อยกเว้นหลักคือการรองรับการหลีกเลี่ยงช่วงพักที่ดียิ่งขึ้น (เช่น break-before:avoid
) เนื่องจากเป็นหัวใจหลักของเครื่องมือการแยกส่วน จึงต้องรวมไว้ตั้งแต่ต้น เนื่องจากการเพิ่มในภายหลังจะหมายถึงการเขียนใหม่อีกครั้ง
ตอนนี้การแยกส่วนบล็อก LayoutNG เสร็จแล้ว เราจึงเริ่มเพิ่มฟังก์ชันการทำงานใหม่ๆ ได้ เช่น การรองรับขนาดหน้าเว็บแบบผสมเมื่อพิมพ์ @page
กล่องระยะขอบเมื่อพิมพ์ box-decoration-break:clone
และอื่นๆ และเช่นเดียวกับ LayoutNG โดยทั่วไป เราคาดว่าอัตราข้อบกพร่องและภาระการบำรุงรักษาของระบบใหม่จะลดลงอย่างมากเมื่อเวลาผ่านไป
ขอขอบคุณ
- Una Kravets สำหรับ "ภาพหน้าจอที่วาดด้วยมือ" ที่ยอดเยี่ยม
- Chris Harrelson สำหรับการตรวจทาน ความคิดเห็น และคำแนะนำ
- Philip Jägenstedt สำหรับความคิดเห็นและคำแนะนำ
- Rachel Andrew สำหรับการดูแลแก้ไขและรูปภาพตัวอย่างแบบหลายคอลัมน์แรก