Tìm hiểu sâu về RenderingNG: Phân đoạn khối LayoutNG

Morten Stenshorne
Morten Stenshorne

Phân mảnh khối là việc chia một hộp cấp khối CSS (chẳng hạn như một phần hoặc đoạn) thành nhiều mảnh khi hộp đó không vừa toàn bộ bên trong một vùng chứa mảnh, được gọi là fragmentainer. Mảnh không phải là một phần tử mà đại diện cho một cột ở bố cục nhiều cột hoặc một trang trong phương tiện được phân trang.

Để việc phân mảnh xảy ra, nội dung cần phải nằm trong ngữ cảnh phân mảnh. Ngữ cảnh phân mảnh thường được thiết lập bởi vùng chứa nhiều cột (nội dung được chia thành các cột) hoặc khi in (nội dung được chia thành các trang). Một đoạn dài có nhiều dòng có thể cần được tách thành nhiều mảnh để các dòng đầu tiên được đặt trong mảnh đầu tiên, còn các dòng còn lại được đặt trong các mảnh tiếp theo.

Một đoạn văn bản được chia thành hai cột.
Trong ví dụ này, một đoạn văn bản được chia thành 2 cột theo bố cục nhiều cột. Mỗi cột là một mảnh, đại diện cho một mảnh của luồng được phân mảnh.

Phân mảnh khối tương tự như một loại phân mảnh phổ biến khác: phân mảnh dòng, hay còn gọi là "gãy dòng". Mọi phần tử cùng dòng chứa nhiều từ (nút văn bản, phần tử <a> bất kỳ, v.v.) và cho phép ngắt dòng đều có thể được chia thành nhiều mảnh. Mỗi mảnh được đặt vào một ô dòng khác. Hộp dòng là phân mảnh cùng dòng tương đương với phân mảnh cho các cột và trang.

Phân mảnh khối LayoutNG

LayoutNGBlockFragmentation là bản viết lại của công cụ phân mảnh cho LayoutNG, ban đầu được phát hành trong Chrome 102. Về cấu trúc dữ liệu, công cụ này đã thay thế nhiều cấu trúc dữ liệu trước NG bằng các mảnh NG được biểu thị trực tiếp trong cây mảnh.

Ví dụ: chúng tôi hiện hỗ trợ giá trị "tránh" cho các thuộc tính CSS "break-before" và "break-after", cho phép tác giả tránh bị ngắt ngay sau tiêu đề. Thường trông không đẹp khi nội dung cuối cùng trên trang là tiêu đề trong khi nội dung của phần đó bắt đầu ở trang tiếp theo. Bạn nên ngắt trước tiêu đề.

Ví dụ về căn chỉnh tiêu đề.
Hình 1. Ví dụ đầu tiên cho thấy một tiêu đề ở cuối trang, ví dụ thứ hai cho thấy tiêu đề ở đầu trang tiếp theo cùng với nội dung liên quan.

Chrome cũng hỗ trợ tràn phân mảnh, để nội dung nguyên khối (được cho là không thể phá vỡ) không bị cắt thành nhiều cột và các hiệu ứng vẽ như đổ bóng và biến đổi được áp dụng chính xác.

Quá trình phân mảnh khối trong LayoutNG hiện đã hoàn tất

Phân mảnh lõi (vùng chứa khối, bao gồm bố cục đường, số thực có độ chính xác đơn và vị trí ngoài luồng) được vận chuyển trong Chrome 102. Phân mảnh linh hoạt và lưới được chuyển vào Chrome 103, còn phân mảnh bảng được chuyển vào Chrome 106. Cuối cùng, tính năng in được xuất bản trong Chrome 108. Phân mảnh khối là tính năng cuối cùng phụ thuộc vào công cụ cũ để thực hiện bố cục.

Kể từ Chrome 108, công cụ cũ không còn được dùng để biểu diễn bố cục nữa.

Ngoài ra, cấu trúc dữ liệu LayoutNG hỗ trợ vẽ và thử nghiệm nhấn, nhưng chúng tôi dựa vào một số cấu trúc dữ liệu cũ cho các API JavaScript đọc thông tin bố cục, chẳng hạn như offsetLeftoffsetTop.

Khi triển khai mọi thứ với NG, bạn có thể triển khai và chuyển các tính năng mới chỉ triển khai LayoutNG (và không có phiên bản công cụ cũ), chẳng hạn như truy vấn vùng chứa CSS, vị trí neo, MathMLbố cục tuỳ chỉnh (Houdini). Đối với các truy vấn về vùng chứa, chúng tôi đã vận chuyển trước một chút, kèm theo cảnh báo cho nhà phát triển rằng tính năng in chưa được hỗ trợ.

Chúng tôi đã vận chuyển phần đầu tiên của LayoutNG vào năm 2019, bao gồm bố cục vùng chứa khối thông thường, bố cục nội tuyến, độ chính xác đơn và vị trí ngoài luồng, nhưng không hỗ trợ linh hoạt, lưới hoặc bảng và hoàn toàn không hỗ trợ phân mảnh khối. Chúng ta sẽ quay lại sử dụng công cụ bố cục cũ cho tính năng linh hoạt, lưới, bảng và mọi thứ liên quan đến việc phân mảnh khối. Điều này đúng ngay cả với các thành phần khối, cùng dòng, nổi và ngoài luồng trong nội dung phân mảnh. Như bạn có thể thấy, việc nâng cấp một công cụ bố cục phức tạp tại chỗ là một bước nhảy rất tinh tế.

Ngoài ra, vào giữa năm 2019, phần lớn chức năng cốt lõi của bố cục phân mảnh khối LayoutNG đã được triển khai (phía sau một lá cờ). Vậy tại sao lại mất nhiều thời gian như vậy để vận chuyển? Câu trả lời ngắn gọn là: phân mảnh phải cùng tồn tại đúng cách với các phần cũ của hệ thống. Bạn không thể xoá hoặc nâng cấp các phần này cho đến khi tất cả phần phụ thuộc được nâng cấp.

Tương tác công cụ cũ

Cấu trúc dữ liệu cũ vẫn chịu trách nhiệm về các API JavaScript đọc thông tin bố cục, vì vậy chúng ta cần ghi lại dữ liệu vào công cụ cũ theo cách mà công cụ đó hiểu được. Trong đó có việc cập nhật chính xác cấu trúc dữ liệu nhiều cột cũ, chẳng hạn như LayoutMultiColumnFlowThread.

Phát hiện và xử lý tính năng dự phòng công cụ cũ

Chúng tôi phải quay lại công cụ bố cục cũ khi có nội dung bên trong chưa thể xử lý được bằng tính năng phân mảnh khối LayoutNG. Tại thời điểm phân mảnh khối LayoutNG cốt lõi, bao gồm linh hoạt, lưới, bảng và bất kỳ nội dung nào được in. Điều này đặc biệt khó khăn vì chúng ta cần phát hiện nhu cầu sử dụng tính năng dự phòng cũ trước khi tạo các đối tượng trong cây bố cục. Ví dụ: chúng tôi cần phát hiện trước khi biết liệu có đối tượng cấp trên của vùng chứa nhiều cột hay không, cũng như trước khi biết được nút DOM nào sẽ trở thành ngữ cảnh định dạng hay không. Đây là vấn đề gà và trứng không có giải pháp hoàn hảo, nhưng miễn là hành vi sai duy nhất là dương tính giả (quay lại phiên bản cũ khi thực sự không cần thiết), thì không sao, vì mọi lỗi trong hành vi bố cục đó đều là lỗi mà Chromium đã có chứ không phải lỗi mới.

Đi bộ quét cây sẵn sàng

Sơn trước là việc chúng ta làm sau khi sắp xếp bố cục, nhưng trước khi tô màu. Thách thức chính là chúng ta vẫn cần di chuyển cây đối tượng bố cục, nhưng hiện tại chúng ta có các mảnh NG. Vậy làm cách nào để xử lý việc này? Chúng ta đi bộ cả đối tượng bố cục và cây mảnh NG cùng một lúc! Điều này khá phức tạp vì việc ánh xạ giữa 2 cây không phải là một việc đơn giản.

Mặc dù cấu trúc cây đối tượng bố cục gần giống với cấu trúc của cây DOM, nhưng cây mảnh là kết quả của bố cục chứ không phải là đầu vào cho bố cục đó. Ngoài việc thực sự phản ánh tác động của bất kỳ sự phân mảnh nào bao gồm phân mảnh cùng dòng (mảnh dòng) và phân mảnh khối (mảnh cột hoặc mảnh trang), cây phân mảnh còn có mối quan hệ mẹ con trực tiếp giữa khối chứa và các phần tử con DOM có mảnh đó làm khối chứa. Ví dụ: trong cây mảnh, một mảnh được tạo bởi phần tử có vị trí tuyệt đối là phần tử con trực tiếp của mảnh khối chứa, ngay cả khi có các nút khác trong chuỗi cấp trên giữa thành phần con cháu có vị trí ngoài luồng và khối chứa tương ứng.

Điều này thậm chí có thể phức tạp hơn khi có một phần tử nằm ngoài luồng được định vị bên trong phân mảnh, vì khi đó các mảnh ngoài luồng trở thành phần tử con trực tiếp của mảnh (chứ không phải con của thứ mà CSS cho là khối chứa). Đây là một vấn đề cần phải được giải quyết để cùng tồn tại với công cụ cũ. Trong tương lai, chúng ta có thể đơn giản hoá mã này vì LayoutNG được thiết kế để hỗ trợ linh hoạt tất cả chế độ bố cục hiện đại.

Các vấn đề với công cụ phân mảnh cũ

Công cụ cũ (được thiết kế ở thời kỳ sơ khai của web) không thực sự có khái niệm phân mảnh, ngay cả khi về mặt kỹ thuật sự phân mảnh cũng tồn tại vào thời điểm đó (để hỗ trợ hoạt động in). Hỗ trợ phân mảnh chỉ là một tính năng được bắt vít ở trên cùng (in) hoặc được trang bị thêm (nhiều cột).

Khi bố trí nội dung có thể phân mảnh, công cụ cũ sắp xếp mọi nội dung thành một dải cao có chiều rộng bằng kích thước cùng dòng của cột hoặc trang, và chiều cao cũng tương đương chiều cao cần thiết để chứa nội dung. Dải cao này không được hiển thị cho trang — hãy xem nó như là kết xuất cho một trang ảo sau đó được sắp xếp lại để hiển thị cuối cùng. Về mặt lý thuyết, cách này tương tự như in toàn bộ bài viết trên báo giấy thành một cột, sau đó sử dụng kéo để cắt thành nhiều cột cho bước thứ hai. (Trước đây, một số tờ báo thực sự sử dụng những kỹ thuật tương tự như vậy!)

Công cụ cũ theo dõi ranh giới của trang hoặc cột ảo trong dải. Việc này cho phép dịch vụ chuyển nội dung không vừa với ranh giới vào trang hoặc cột tiếp theo. Ví dụ: nếu chỉ có nửa trên của dòng phù hợp với những gì mà công cụ cho là trang hiện tại, công cụ sẽ chèn một "thanh phân trang" để đẩy nó xuống vị trí mà công cụ giả định rằng đầu trang tiếp theo. Sau đó, hầu hết công việc phân đoạn thực tế ("cắt bằng kéo và đặt") diễn ra sau bố cục trong khi tô màu và tô màu, bằng cách cắt các cột thành các phần cao. Điều này khiến một số việc về cơ bản là không thể, chẳng hạn như áp dụng phép biến đổi và vị trí tương đối sau phân mảnh (đây là yêu cầu của thông số kỹ thuật). Hơn nữa, mặc dù công cụ cũ hỗ trợ tính năng phân mảnh bảng, nhưng hoàn toàn không hỗ trợ tính năng phân mảnh linh hoạt hoặc phân mảnh lưới.

Dưới đây là hình minh hoạ cách bố cục 3 cột được thể hiện bên trong công cụ cũ, trước khi sử dụng kéo, vị trí và keo (chúng ta có chiều cao cụ thể để chỉ vừa 4 dòng, nhưng có một chút không gian ở dưới cùng):

Biểu diễn nội bộ dưới dạng một cột với các thanh phân trang trong đó nội dung bị ngắt và biểu diễn trên màn hình dưới dạng ba cột

Vì công cụ bố cục cũ không thực sự phân mảnh nội dung trong quá trình bố cục, nên có nhiều cấu phần phần mềm lạ, chẳng hạn như vị trí tương đối và các biến đổi được áp dụng không chính xác, và bóng hộp bị cắt bớt ở các cạnh cột.

Dưới đây là một ví dụ về bóng văn bản:

Công cụ cũ không xử lý tốt việc này:

Bóng văn bản được cắt bớt được đặt vào cột thứ hai.

Bạn có thấy cách bóng văn bản trên dòng trong cột đầu tiên bị cắt bớt và được đặt ở đầu cột thứ hai không? Nguyên nhân là do công cụ bố cục cũ không hiểu được sự phân mảnh.

Mã sẽ có dạng như sau:

Hai cột văn bản với bóng hiển thị chính xác.

Tiếp theo, hãy làm cho chủ đề phức tạp hơn một chút bằng cách biến đổi và đổ bóng. Hãy lưu ý cách trong công cụ cũ, việc cắt đoạn không chính xác và tràn cột. Đó là do theo thông số kỹ thuật, phép biến đổi nên được áp dụng như một hiệu ứng hậu bố cục, sau phân mảnh. Với tính năng phân mảnh LayoutNG, cả hai đều hoạt động chính xác. Điều này làm tăng khả năng tương tác với Firefox, trình duyệt đã hỗ trợ phân mảnh tốt trong một khoảng thời gian với hầu hết các thử nghiệm trong lĩnh vực này cũng vượt qua đó.

Các hộp bị ngắt không chính xác trên hai cột.

Công cụ cũ cũng gặp vấn đề với nội dung nguyên khối cao. Nội dung nguyên khối nếu không đủ điều kiện để chia thành nhiều mảnh. Các phần tử có chức năng cuộn tràn là một khối nguyên khối vì người dùng sẽ không thực hiện thao tác cuộn trong một vùng không phải hình chữ nhật. Hộp dòng và hình ảnh là các ví dụ khác về nội dung nguyên khối. Ví dụ:

Nếu đoạn nội dung nguyên khối quá cao để vừa trong một cột, công cụ cũ sẽ cắt phần nội dung đó một cách tàn bạo (dẫn đến hành vi rất "thú vị" khi cố gắng cuộn vùng chứa có thể cuộn):

Thay vì để dòng này tràn cột đầu tiên (như với tính năng phân mảnh khối LayoutNG):

ALT_TEXT_HERE

Công cụ cũ hỗ trợ các điểm chèn bắt buộc. Ví dụ: <div style="break-before:page;"> sẽ chèn dấu ngắt trang trước DIV. Tuy nhiên, tính năng này chỉ hỗ trợ hạn chế để tìm các điểm ngắt không bắt buộc tối ưu. Định dạng này có hỗ trợ break-inside:avoidtrẻ em mồ côi và người góa chồng, nhưng không có hỗ trợ để tránh ngắt giữa các khối, ví dụ như được yêu cầu qua break-before:avoid. Hãy xem xét ví dụ sau:

Văn bản được chia thành hai cột.

Ở đây, phần tử #multicol có chỗ cho 5 dòng trong mỗi cột (vì chiều cao của cột là 100 px và chiều cao của dòng là 20 px), do đó, tất cả #firstchild có thể vừa với cột đầu tiên. Tuy nhiên, #secondchild đồng cấp của nó có break-before:tránh, nghĩa là nội dung muốn không xảy ra ngắt giữa chúng. Vì giá trị của widows là 2 nên chúng ta cần đẩy 2 dòng #firstchild sang cột thứ hai để tuân thủ tất cả các yêu cầu tránh điểm chèn quảng cáo. Chromium là công cụ trình duyệt đầu tiên hỗ trợ đầy đủ tổ hợp tính năng này.

Cách hoạt động của quá trình phân mảnh NG

Công cụ bố cục NG thường sắp xếp tài liệu bằng cách truyền tải theo chiều sâu cây hộp CSS trước tiên. Khi tất cả các phần tử con của một nút được bố trí, bố cục của nút đó có thể được hoàn tất bằng cách tạo ra một NGPhysicalFragment và quay lại thuật toán bố cục mẹ. Thuật toán đó sẽ thêm mảnh đó vào danh sách các mảnh con. Sau khi tất cả các mảnh con hoàn tất, thuật toán sẽ tạo một mảnh cho chính nó mà có tất cả các mảnh con ở bên trong. Phương thức này sẽ tạo một cây mảnh cho toàn bộ tài liệu. Đây là một đơn giản hoá quá mức tuy nhiên: chẳng hạn, các phần tử được định vị ngoài luồng sẽ phải tạo bong bóng từ vị trí chúng tồn tại trong cây DOM đến khối chứa của chúng trước khi chúng có thể được bố trí. Tôi sẽ bỏ qua chi tiết nâng cao này vì lý do đơn giản.

Cùng với hộp CSS, LayoutNG cung cấp một không gian ràng buộc cho thuật toán bố cục. Việc này cung cấp cho thuật toán những thông tin như không gian có sẵn cho bố cục, ngữ cảnh định dạng mới có được thiết lập hay không và kết quả thu gọn lề trung gian từ nội dung trước đó. Không gian ràng buộc cũng biết kích thước khối được bố trí của trình phân mảnh và độ lệch khối hiện tại vào đó. Cột này cho biết nơi ngắt.

Khi có phân mảnh khối, bố cục của các thành phần con phải dừng tại một điểm ngắt. Lý do dẫn đến lỗi bao gồm do hết không gian trong trang hoặc cột hoặc do bị ngắt. Sau đó, chúng ta tạo các mảnh cho các nút mà chúng ta đã truy cập và trả về tận cùng thư mục gốc của ngữ cảnh phân mảnh (vùng chứa nhiều cột hoặc trong trường hợp đang in, là gốc của tài liệu). Sau đó, ở gốc ngữ cảnh phân mảnh, chúng ta chuẩn bị cho một trình phân mảnh mới và tiếp tục xuống cây, tiếp tục tại nơi chúng ta đã dừng lại trước khi nghỉ.

Cấu trúc dữ liệu quan trọng dùng để cung cấp phương tiện tiếp tục bố cục sau khi nghỉ có tên là NGBlockBreakToken. Tệp này chứa tất cả thông tin cần thiết để tiếp tục bố cục chính xác trong mảnh tiếp theo. Một NGBlockBreakToken được liên kết với một nút và nút này tạo thành cây NGBlockBreakToken, do đó, mỗi nút cần được tiếp tục đều được biểu thị. Một NGBlockBreakToken được đính kèm vào NGPhysicalBoxFragment được tạo cho các nút bị hỏng bên trong. Mã ngắt được truyền đến các thành phần mẹ, tạo thành một cây mã thông báo ngắt. Nếu chúng ta cần ngắt trước một nút (thay vì bên trong nút đó), sẽ không có mảnh nào được tạo, nhưng nút mẹ vẫn cần tạo mã ngắt "ngắt trước" cho nút này để chúng ta có thể bắt đầu sắp xếp bố cục khi đến cùng một vị trí trong cây nút ở trình phân mảnh tiếp theo.

Ngắt được chèn khi chúng ta hết không gian phân mảnh (một ngắt không bắt buộc) hoặc khi yêu cầu ngắt bắt buộc.

Có các quy tắc trong quy cách về cách chèn nghỉ không bắt buộc tối ưu và việc chỉ chèn chính xác vào điểm chèn không phải lúc nào cũng là việc nên làm. Ví dụ: có nhiều thuộc tính CSS như break-before ảnh hưởng đến việc lựa chọn vị trí chèn quảng cáo.

Trong quy trình bố cục, để triển khai chính xác phần thông số kỹ thuật không bắt buộc chèn, chúng ta cần theo dõi các điểm ngắt có thể phù hợp. Bản ghi này có nghĩa là chúng ta có thể quay lại và sử dụng điểm ngắt tốt nhất có thể cuối cùng được tìm thấy, nếu chúng ta hết dung lượng tại thời điểm vi phạm yêu cầu tránh ngắt (ví dụ: break-before:avoid hoặc orphans:7). Mỗi điểm ngắt có thể có được cho một điểm, từ "chỉ thực hiện việc này như một phương án cuối cùng" cho đến "nơi hoàn hảo để ngắt", với một số giá trị ở giữa. Nếu vị trí ngắt được ghi là "hoàn hảo", điều đó có nghĩa là không có quy tắc phá vỡ nào sẽ bị vi phạm nếu chúng ta phá vỡ ở đó (và nếu chúng ta nhận được điểm số này chính xác tại thời điểm chúng ta hết không gian, thì không cần phải nhìn lại để tìm ra điều gì khác tốt hơn). Nếu điểm số là "khu nghỉ cuối cùng", điểm ngắt thậm chí không phải là một điểm hợp lệ, nhưng chúng ta vẫn có thể phá vỡ đó nếu không tìm thấy bất kỳ điều gì tốt hơn, để tránh tràn phân mảnh.

Điểm ngắt hợp lệ thường chỉ xảy ra giữa các điểm ngắt đồng cấp (hộp dòng hoặc khối) và không xảy ra, ví dụ: giữa nhà xuất bản mẹ và con đầu tiên của nó (điểm ngắt lớp C là một ngoại lệ, nhưng chúng ta không cần thảo luận về các điểm ngắt đó ở đây). Ví dụ: một điểm ngắt hợp lệ trước một khối đồng cấp có break-before:avoid, nhưng nằm ở giữa "hoàn hảo" và "kết hợp sau cùng".

Trong quá trình bố cục, chúng ta theo dõi điểm ngắt tốt nhất từ trước đến nay trong một cấu trúc có tên là NGEarlyBreak. Điểm chèn sớm có thể là điểm ngắt ở trước hoặc bên trong nút khối, hoặc trước một dòng (dòng vùng chứa khối hoặc đường linh hoạt). Chúng ta có thể tạo một chuỗi hoặc đường dẫn của các đối tượng NGEarlyBreak, trong trường hợp điểm ngắt tốt nhất nằm đâu đó sâu bên trong thứ gì đó mà chúng ta đã đi qua trước đó tại thời điểm hết không gian. Ví dụ:

Trong trường hợp này, chúng ta sẽ hết dung lượng ngay trước #second nhưng lại có "break-before:tránh", các thành phần này nhận được điểm ngắt vị trí là "tránh ngắt quảng cáo vi phạm". Khi đó, chúng ta sẽ có một chuỗi NGEarlyBreak " bên trong #outer > bên trong #middle > bên trong #inner > trước "dòng 3"", với sự "hoàn hảo", vì vậy chúng ta không muốn ngắt kết nối ở đó. Vì vậy, chúng ta cần quay lại và chạy lại bố cục từ đầu #outer (và lần này vượt qua NGEarlyBreak mà chúng ta tìm thấy), để có thể ngắt trước "dòng 3" trong #inner. (Chúng ta ngắt trước "dòng 3" để 4 dòng còn lại kết thúc trong mảnh tiếp theo và để tôn vinh widows:4.)

Thuật toán này được thiết kế để luôn ngắt ở điểm ngắt tốt nhất có thể (như được xác định trong thông số kỹ thuật) bằng cách bỏ các quy tắc theo đúng thứ tự, nếu không phải tất cả các điểm đó đều được đáp ứng. Lưu ý rằng chúng ta chỉ phải bố cục lại tối đa một lần cho mỗi luồng phân mảnh. Tại thời điểm chúng ta ở lượt bố cục thứ hai, vị trí ngắt tốt nhất đã được chuyển cho các thuật toán bố cục. Đây là vị trí ngắt được phát hiện trong lượt bố cục đầu tiên và được cung cấp dưới dạng một phần của đầu ra bố cục trong vòng đó. Ở lượt bố cục thứ hai, chúng ta sẽ không bố trí cho đến khi hết dung lượng – trên thực tế, chúng ta sẽ không hết dung lượng (điều này thực sự sẽ là lỗi), vì chúng ta đã được cung cấp một vị trí siêu hấp dẫn (tuyệt vời như có thể) để chèn giờ nghỉ sớm, nhằm tránh vi phạm bất kỳ quy tắc phá vỡ nào một cách không cần thiết. Chúng tôi chỉ bố trí đến điểm đó và dừng lại.

Xin lưu ý rằng đôi khi, chúng ta cần vi phạm một số yêu cầu tránh ngắt, nếu việc đó giúp tránh tràn mảnh. Ví dụ:

Ở đây, chúng ta hết dung lượng ngay trước #second, nhưng có "break-before:tránh". Như ví dụ gần đây nhất, cụm từ này được dịch thành "tránh ngắt đoạn vi phạm", Chúng tôi cũng có NGEarlyBreak với nội dung "góa phụ và trẻ mồ côi vi phạm" (bên trong #first > trước "dòng 2"), nhưng tình trạng này vẫn chưa hoàn hảo, nhưng hiệu quả hơn so với "tránh vi phạm". Vì vậy, chúng ta sẽ ngắt trước "dòng 2", vi phạm yêu cầu của trẻ mồ côi / góa phụ. Quy cách này xử lý vấn đề này trong phiên bản 4.4. Unforced Breaks (điểm ngắt không thực thi), trong đó quy tắc này xác định những quy tắc có thể gây lỗi bị bỏ qua trước tiên nếu chúng ta không có đủ điểm ngắt để tránh tràn mảnh.

Kết luận

Mục tiêu chức năng của dự án phân mảnh khối LayoutNG là cung cấp cách triển khai hỗ trợ kiến trúc LayoutNG cho mọi thứ mà công cụ cũ hỗ trợ, đồng thời ít sử dụng nhất có thể các bản sửa lỗi khác, ngoài các bản sửa lỗi. Ngoại lệ chính là hỗ trợ tránh ngắt tốt hơn (ví dụ: break-before:avoid), vì đây là một phần cốt lõi của công cụ phân mảnh, vì vậy phải có trong đó ngay từ đầu, vì thêm nó sau này sẽ có nghĩa là một lần viết lại khác.

Hiện tại, quá trình phân mảnh khối LayoutNG đã hoàn tất, chúng ta có thể bắt đầu thêm chức năng mới, chẳng hạn như hỗ trợ các kích thước trang hỗn hợp khi in, hộp lề @page khi in, box-decoration-break:clone, v.v. Và cũng giống như LayoutNG nói chung, chúng tôi hy vọng tỷ lệ lỗi và gánh nặng bảo trì của hệ thống mới sẽ thấp hơn đáng kể theo thời gian.

Xác nhận

  • Una Kravets để chụp "ảnh chụp màn hình thủ công" thật đẹp.
  • Chris Harrelson hiệu đính, phản hồi và gợi ý.
  • Philip Jägenstedt để nghe phản hồi và đề xuất.
  • Rachel Andrew là người chỉnh sửa và hình minh hoạ đầu tiên về nhiều cột.