Szczegółowa analiza renderowania: fragmentacja bloków LayoutNG

Fragmentacja blokowa w UkładNG została zakończona. Z tego artykułu dowiesz się, jak to działa i dlaczego jest ważne.

Morten Stenshorne
Morten Stenshorne

Nazywam się Morten Stenshorne i jestem inżynierem układu w zespole renderowania Blink w Google. Zajmuję się tworzeniem silników przeglądarek od początku XXI wieku. Dobrze się bawię, pomagając w przechodzeniu testu Acid2 w silniku Presto (Opera 12 i starszych) oraz analizowaniu wstecznie innych przeglądarek w celu poprawienia układu tabel w Presto. Spędziłem więcej lat, niż chcę przyznać, że chciałem się przyznać do fragmentacji blokowej, a w szczególności do obsługi multicol w Presto, WebKit i Blink. Przez ostatnie kilka lat w Google koncentrowałem się głównie na prowadzeniu pracy związanej z dodawaniem obsługi fragmentacji bloków w narzędziu LayoutNG. Dołącz do mnie w tej szczegółowej prezentacji o implementacji podziału bloków, ponieważ być może to ostatni raz, gdy wdrażam taki podział. :)

Co to jest fragmentacja bloków?

Fragmentacja blokowa polega na podzieleniu pola na poziomie bloku CSS (np. sekcji lub akapitu) na wiele fragmentów, gdy nie mieści się ono w całości wewnątrz jednego kontenera fragmentów nazywanego fragmentainerem. Fragmentator nie jest elementem, ale reprezentuje kolumnę w układzie wielokolumnowym lub stronę w multimediach z podziałem na strony. Aby doszło do fragmentacji, treść musi być umieszczona w kontekście fragmentacji. Kontekst fragmentacji jest najczęściej ustalany przez kontener wielokolumnowy (treść zostanie podzielona na kolumny) lub podczas drukowania (treść zostanie podzielona na strony). Długi akapit z wieloma wierszami może wymagać podziału na wiele fragmentów, tak aby pierwsze wiersze znajdowały się w pierwszym fragmencie, a pozostałe – w kolejnych.

Akapit tekstu podzielony na 2 kolumny.
W tym przykładzie akapit został podzielony na 2 kolumny przy użyciu układu wielokolumnowego. Każda kolumna jest elementem podziału, który reprezentuje fragment podzielonego przepływu.

Fragmentacja blokowa jest analogicznie do innego dobrze znanego typu fragmentacji, czyli fragmentacji wierszy (nazywanego „rozbiciem wiersza”). Każdy element w tekście składający się z więcej niż jednego słowa (dowolny węzeł tekstowy, dowolny element <a> itd.) umożliwiający podziały wierszy może zostać podzielony na kilka fragmentów. Każdy fragment jest umieszczany w innym polu wiersza. Pole wiersza to śródtekstowa fragmentacja odpowiadająca obiektowi fragmentainer dla kolumn i stron.

Czym jest fragmentacja bloków UkładNG?

UkładNGBlockFragmentation to nowa wersja mechanizmu fragmentacji na potrzeby Układu. Po wielu latach pracy pierwsze części zostały ostatecznie udostępnione w Chrome 102 wcześniej w tym roku. Rozwiązano długotrwałe problemy, które w zasadzie nie były możliwe do rozwiązania w „starszej” wersji wyszukiwarki. Pod względem struktur danych zastępuje wiele struktur danych sprzed NG fragmentami NG reprezentowanymi bezpośrednio w drzewie fragmentów.

Na przykład obsługujemy na przykład wartość „unikaj” dla właściwości CSS „break-before” i „break-after”, która pozwala autorom uniknąć przerw bezpośrednio po nagłówku. Zasadniczo nie wygląda to dobrze, jeśli ostatnią rzeczą, jaką umieszcza się na stronie, jest nagłówek, podczas gdy zawartość sekcji rozpoczyna się na następnej stronie. Lepiej jest rozbić go przed nagłówkiem. Przykład znajdziesz na ilustracji poniżej.

W pierwszym przykładzie widoczny jest nagłówek u dołu strony, a w drugim – na górze następnej strony – wraz z powiązaną treścią.

Chrome w wersji 102 obsługuje również nadmiar fragmentacji, dzięki czemu monolityczne treści (uważane za nierozbijanie) nie są dzielone na wiele kolumn, a efekty wyrenderowania, takie jak cienie i przekształcenia, są stosowane prawidłowo.

Fragmentacja blokowania w UkładNG została zakończona

W momencie tworzenia tego tekstu zakończyliśmy obsługę podziału na fragmenty bloków w standardzie LayoutNG. Podział rdzeni (kontenery blokowe, w tym układ liniowy, elementy swobodne i pozycjonowanie poza przepływem) wprowadzone w Chrome 102. W Chrome 103 udostępnimy funkcje Flex i fragmentacji tabel, a w Chrome 106 – fragmentację tabel. Na koniec drukowanie w Chrome 108. Blokowanie fragmentacji było ostatnią funkcją, która opierała się na starszej wersji mechanizmu obsługi układu. Oznacza to, że od Chrome 108 starsza wersja mechanizmu nie będzie już używana do tworzenia układu.

Oprócz rzeczywistego układu treści struktury danych UkładNG obsługują malowanie i testowanie trafień, ale nadal polegamy na starszych strukturach danych na potrzeby interfejsów API JavaScript, które odczytują informacje o układzie, np. offsetLeft i offsetTop.

Ułożenie wszystkiego za pomocą NG pozwala wdrażać i wysyłać nowe funkcje, które mają wyłącznie implementacje UkładNG (i nie mają starszych odpowiedników w wyszukiwarce), takich jak zapytania kontenera CSS, pozycjonowanie zakotwiczenia, MathML i układ niestandardowy (Houdini). W przypadku zapytań dotyczących kontenerów została ona wysłana z wyprzedzeniem, informując deweloperów, że drukowanie nie jest jeszcze obsługiwane.

W 2019 roku opublikowaliśmy pierwszą część interfejsu LayoutNG – zwykły układ kontenera blokowego, układ wbudowany, elementy swobodne i pozycjonowanie poza przepływem, ale nie obsługujemy funkcji Flex, siatki i tabel ani w ogóle nie obsługujemy fragmentacji bloków. Na potrzeby funkcji Flex, siatki, tabel i innych elementów, które obejmowały fragmentację bloków, warto wrócić do starszego mechanizmu układów. Tak było nawet w przypadku elementów blokowych, śródtekstowych, pływających i nieprzesuniętych w pofragmentowanych treściach. Jak widać, uaktualnienie tak złożonego mechanizmu układu w miejscu, w którym używany jest taki układ, jest bardzo delikatnym taniem.

Wydaje mi się, że w połowie 2019 roku większość podstawowych funkcji układu fragmentacji blokowej LayoutNG został już wdrożony (za flagą). Dlaczego jej wysyłka trwała tak długo? Krótka odpowiedź brzmi: fragmentacja musi współistnieć z różnymi starszymi częściami systemu, których nie można usunąć ani uaktualnić, dopóki nie uaktualnione zostaną wszystkie zależności. W przypadku długiej odpowiedzi zapoznaj się z tymi informacjami.

Interakcja ze starszą wersją wyszukiwarki

Starsze struktury danych nadal zajmują się interfejsami API JavaScript, które odczytują informacje o układzie. Dlatego musimy zapisywać dane w starszym mechanizmie w sposób, który będzie zrozumiały. Obejmuje to prawidłową aktualizację starszych wielokolumnowych struktur danych, takich jak LayoutMultiColumnFlowThread.

Wykrywanie kreacji zastępczych starszego typu i ich obsługa

Gdy w obiekcie znajdowała się zawartość, której nie można jeszcze obsłużyć przez fragmentację bloków LayoutNG, musieliśmy wrócić do starszego mechanizmu układu. W momencie wysyłki podstawowej bloków Układu (wiosna 2022 r.) fragment ten obejmował funkcje Flex, siatki, stoły i wszystkie drukowane. Było to szczególnie trudne, ponieważ przed utworzeniem obiektów w drzewie układu trzeba było wykryć konieczność stosowania starszych wersji kreacji zastępczych. Trzeba było na przykład wykryć, czy istnieje wielokolumnowy przodek kontenera, lub zanim wiedzieliśmy, które węzły DOM staną się kontekstem formatowania. To jajko-kurczak, którego nie ma idealnego rozwiązania, ale jeśli jego jedynym błędem jest występowanie fałszywych trafień (powrót do starszej wersji, gdy nie jest potrzebna), to nic złego, ponieważ wszelkie błędy w tym układzie stron to te, które występują już w Chromium, a nie nowe.

Spacer po drzewie

Wstępne malowanie to coś, co robimy po układzie, ale przed malowaniem. Głównym problemem jest to, że nadal musimy przejść drzewo obiektów układu, ale mamy teraz fragmenty NG. Jak sobie z tym poradzić? Spacerujemy jednocześnie po obiekcie układu i drzewach fragmentów NG. To dość skomplikowane, ponieważ odwzorowanie dwóch drzew nie jest proste. Chociaż struktura drzewa obiektów szablonu bardzo przypomina drzewo DOM, drzewo fragmentów jest wyjścią układu, a nie jego danymi wejściowych. Oprócz rzeczywistego odzwierciedlenia efektu fragmentacji, w tym fragmentacji wbudowanej (fragmenty wierszy) i fragmentacji blokowej (fragmenty kolumn lub stron), drzewo fragmentów ma również bezpośrednią relację nadrzędny-podrzędny między blokiem zawierającym a elementami podrzędnymi DOM, które mają ten fragment jako blok zawierający. Na przykład w drzewie fragmentów fragment wygenerowany przez element znajdujący się bez końca jest bezpośrednim elementem podrzędnym jego fragmentu blokowego, nawet jeśli w łańcuchu elementów nadrzędnych między elementem podrzędnym umiejscowionym poza przepływem a jego blokiem znajdują się inne węzły w łańcuchu nadrzędnym.

Sytuację komplikuje się jeszcze bardziej, gdy wewnątrz fragmentacji występuje element, który nie mieści się w przepływie, ponieważ wtedy takie fragmenty stają się bezpośrednimi elementami podrzędnymi fragmentainera (a nie są podrzędne wobec tego, co CSS uważa za blok zawierający). Niestety ten problem wymagał rozwiązania, aby możliwe było współistnienie ze starszym mechanizmem bez zbyt wielu problemów. W przyszłości chcemy uprościć ten kod, ponieważ LayoutNG został zaprojektowany z myślą o elastycznej obsłudze wszystkich nowoczesnych trybów układu.

Problemy ze starszym mechanizmem fragmentacji

W starszym mechanizmie, zaprojektowany we wcześniejszej epoce internetu, nie ma koncepcji fragmentacji, nawet jeśli w tamtych czasach również fragmentacja istniała (z myślą o obsłudze drukowania). Obsługa fragmentacji była czymś, co można było przymocować u góry (drukowanie) lub zmodernizować (wielokolumnowe).

Układaąc treści podzielone na fragmenty, starszy mechanizm układa wszystko w wysokim pasku, którego szerokość odpowiada rozmiarowi wbudowanej kolumny lub strony, a wysokość jest wystarczająca do zmieszczenia zawartości. Ten wysoki pasek nie jest renderowany na stronie – można go traktować jako renderowanie na stronie wirtualnej, której kolejność jest potem ponownie wyświetlana. Jest to podobne do drukowania całego artykułu w papierowej gazecie w jednej kolumnie, a następnie pocięcia go nożyczkami na kilka części. (Kiedyś nawet niektóre gazety używały podobnych technik!)

Starsza wersja wyszukiwarki śledzi urojoną granicę strony lub kolumny na pasku. Pozwala to na przesuwanie treści, które nie mieszczą się w granicach, do następnej strony lub kolumny. Jeśli na przykład tylko górna połowa wiersza zmieści się w bieżącej stronie w wyszukiwarce, zostanie wstawiona „rozpiętość podziału na strony”, która przesunie ją w dół do pozycji, w której wyszukiwarka zakłada, że górna jest górna strona. Następnie większość operacji podziału (tzw. „cięcie nożyczkami i umiejscowieniem”) jest wykonywana po ułożeniu elementów w trakcie wstępnego renderowania i malowania stron (na przykład przy wstępnym ładowaniu i malowaniu elementów). Sprawiało to, że kilka rzeczy było w zasadzie niemożliwe, takich jak zastosowanie przekształceń i względne pozycjonowanie po fragmentacji (czego wymaga specyfikacja). Co więcej, chociaż starszy mechanizm obsługuje fragmentację tabel, w ogóle nie obsługujemy funkcji Flex i fragmentacji siatki.

Oto ilustracja przedstawiająca wewnętrzny układ 3-kolumnowy w starszej wersji wyszukiwarki przed użyciem nożyczek, miejsca docelowego i kleju (ustaliliśmy wysokość określoną, więc mieszczą się tylko 4 linie, ale u dołu jest trochę miejsca):

Wewnętrzna prezentacja w postaci jednej kolumny z rozdzielaniem treści na strony w miejscu podziału treści oraz prezentacja na ekranie w 3 kolumnach.

Ponieważ starszy mechanizm układów nie fragmentuje treści podczas układu, występuje wiele dziwnych artefaktów, takich jak nieprawidłowe pozycjonowanie, nieprawidłowo stosowane przekształcenia oraz przycinanie cieni ramki przy krawędziach kolumn.

Oto prosty przykład z użyciem parametru „text-shadow”:

Starszy mechanizm nie obsługuje tej funkcji:

Cienie obciętego tekstu umieszczane w drugiej kolumnie.

Czy widzisz, że cień tekstu z wiersza w pierwszej kolumnie jest obcinany i umieszczony u góry drugiej kolumny? Dzieje się tak, ponieważ starszy mechanizm układów nie rozpoznaje fragmentacji.

Powinien on wyglądać tak (a w przypadku NG):

Dwie kolumny tekstu z prawidłowym wyświetlaniem cieni.

Teraz uprościmy to zadanie z wykorzystaniem przekształceń i cieni. Zwróć uwagę, że w starszej wersji silnika występuje nieprawidłowe przycinanie i spuszczanie kolumn. Dzieje się tak, ponieważ przekształcenia są zgodnie ze specyfikacją, która powinna być stosowana jako efekt postuowy lub pofragmentacji. Przy fragmentacji UkładNG oba działają poprawnie. Zwiększa to interoperacyjność z przeglądarką Firefox, która przez jakiś czas była dobrze obsługiwana przy fragmentacji, a większość testów w tym obszarze również przechodzi tam działalność.

Pola są nieprawidłowo podzielone na 2 kolumny.

Starszy mechanizm napotkał też problemy z wysoką treścią monolityczną. Treści są monolityczne, jeśli nie kwalifikują się do podziału na kilka fragmentów. Elementy z przewijaniem rozszerzonym są monolityczne, ponieważ użytkownicy nie mają sensu przewijać go do obszaru, który nie jest prostokątny. Pola liniowe i obrazy są innymi przykładami treści monolitycznych. Oto przykład:

Jeśli element monolityczny jest zbyt wysoki i nie mieści się w kolumnie, starszy mechanizm brutalnie go pokroi (co prowadzi do bardzo „ciekawego” działania podczas przewijania kontenera z możliwością przewijania):

Zamiast wykraczać poza pierwszą kolumnę (jak ma to miejsce w przypadku fragmentacji bloków UkładNG):

ALT_TEXT_HERE

Starsza wersja silnika obsługuje wymuszone przerwy. Na przykład funkcja <div style="break-before:page;"> wstawia podział strony przed DIV. Ma jednak ograniczoną obsługę znajdowania optymalnych niewymuszonych przerw. Obsługuje break-inside:avoid oraz sierocinie i wdowy, ale nie obsługuje unikania przerw między blokami, jeśli na przykład zażądano ich za pomocą break-before:avoid. Przeanalizuj ten przykład:

Tekst podzielony na 2 kolumny.

W tym przykładzie element #multicol ma miejsce na 5 wierszy w każdej kolumnie (ponieważ ma 100 pikseli wysokości, a wysokość wiersza 20 pikseli), więc wszystkie elementy #firstchild zmieściły się w pierwszej kolumnie. Jednak jego odpowiednik #secondchild ma metodę przerwania przed:uniknięciem, która oznacza, że treść nie chce, aby pomiędzy nimi doszło do przerwy. Ponieważ wartość widows wynosi 2, do drugiej kolumny muszą zostać przeniesione 2 wiersze po #firstchild, by uwzględnić wszystkie żądania unikania przerw. Chromium to pierwszy mechanizm przeglądarki, który w pełni obsługuje tę kombinację funkcji.

Jak działa fragmentacja NG

Mechanizm układu NG zazwyczaj układa dokument, przemierzając najpierw głębokość drzewa ramki CSS. Po ustaleniu wszystkich elementów potomnych węzła można dokończyć układ tego węzła, tworząc element NGPhysicalFragment i powracając do algorytmu układu nadrzędnego. Algorytm ten dodaje fragment do swojej listy fragmentów podrzędnych i, po ukończeniu wszystkich elementów podrzędnych, generuje fragment dla siebie ze wszystkimi swoimi fragmentami podrzędnymi. Ta metoda tworzy drzewo fragmentów dla całego dokumentu. Jest to jednak nadmierne uproszczenie: na przykład ułożone nieprzepływne elementy będą musiały zebrać się z miejsca w drzewie DOM, zanim zostaną ułożone. Te zaawansowane szczegóły pomijamy dla uproszczenia.

Wraz z polem CSS oraz LayoutNG zapewnia miejsce na ograniczenia dla algorytmu układu. Dzięki temu algorytm otrzyma takie informacje jak dostępne miejsce na układ, informacje o tym, czy został utworzony nowy kontekst formatowania, oraz wyniki zwijania marginesów pośrednich z poprzedniej treści. Przestrzeń ograniczenia zna również rozmiar blokowej części rozciągnięcia oraz obecne przesunięcie bryły do niej. Ten wskaźnik pokazuje, gdzie mamy uderzyć.

Jeśli występuje fragmentacja bloków, układ elementów podrzędnych musi się zatrzymać na przerwie. Przyczyną takiego stanu rzeczy jest brak miejsca na stronie lub kolumnie albo wymuszone przerwanie. Następnie tworzymy fragmenty dla odwiedzonych węzłów i wracamy aż do poziomu głównego kontekstu fragmentacji (kontenera wielokolumnowego lub, w przypadku drukowania, do katalogu głównego dokumentu). Następnie na poziomie głównym kontekstu fragmentacji przygotowujemy się na nowy mechanizm fragmentacji i z powrotem wracamy do drzewa, wracając do miejsca, w którym przerwano przed przerwą.

Kluczową strukturę danych zapewniającą sposoby wznawiania układu po przerwie nazywamy NGBlockBreakToken. Zawiera on wszystkie informacje potrzebne do poprawnego wznowienia układu w następnym elemencie fragmentacji. NGBlockBreakToken jest powiązany z węzłem i tworzy drzewo NGBlockBreakToken, tak aby każdy węzeł, który należy wznowić, jest reprezentowany. Obiekt NGBlockBreakToken jest dołączony do obiektu NGPhysicalBoxFragment wygenerowanego dla węzłów, które włamują się do niego. Tokeny przerw są przekazywane do elementów nadrzędnych, tworząc drzewo tokenów przerw. Jeśli trzeba będzie rozbić węzeł przed węzłem (a nie wewnątrz niego), fragment nie zostanie utworzony, ale w węźle nadrzędnym trzeba utworzyć token przerwania „break-before” dla węzła, aby można było rozpocząć jego układ, gdy znajdziemy się w tym samym miejscu w drzewie węzłów w następnym elemencie typu fragmentaner.

Przerwy są wstawiane, gdy zabraknie nam przestrzeni fragmentarycznej (niewymuszona przerwa) lub gdy zostanie zażądana wymuszona przerwa.

Specyfikacja zawiera reguły optymalnego niewymuszonego przerwania, a wstawienie przerwy w miejscu, w którym zabraknie miejsca, nie zawsze jest właściwym rozwiązaniem. Na przykład różne właściwości CSS, takie jak break-before, które wpływają na wybór miejsca przerwania. Dlatego w układzie, aby prawidłowo wdrożyć sekcję specyfikacji niewymuszonych przerw, musimy monitorować możliwe punkty przerwania. Ten rekord oznacza, że możemy użyć ostatniego znalezionego punktu przerwania, jeśli zabraknie nam miejsca w momencie, w którym moglibyśmy naruszyć żądania unikania przerw (np. break-before:avoid lub orphans:7). Każdy możliwy punkt przerwania jest przyznawany punktacją z zakresu od „rób to w ostateczności” do „idealnego miejsca do łamania”. Jeśli miejsce przerwy zostanie ocenione jako „idealne”, nie spowoduje to naruszenia żadnych zasad (i jeśli uzyskamy wynik dokładnie w momencie, w którym zabraknie miejsca, nie ma potrzeby szukania czegoś lepszego). Jeśli wynik to „last-resort”, punkt przerwania nie jest nawet prawidłowy, ale nadal możemy go zepsuć, jeśli nie uda się nam znaleźć niczego lepszego, aby uniknąć nadmiaru fragmentacji.

Prawidłowe punkty przerwania występują zazwyczaj tylko między elementami równorzędnymi (polami liniowymi lub blokami), a nie na przykład między elementem nadrzędnym a pierwszym elementem podrzędnym (wyjątkiem są punkty przerwania klasy C, ale nie musimy ich omawiać w tym miejscu). Istnieje istniejący prawidłowy punkt przerwania, np. przed elementem równorzędnym bloku z parametrem break-before:avoid, ale znajduje się gdzieś pomiędzy „idealnymi” a „last-resort”.

Podczas układu śledzimy najlepszy jak dotąd punkt przerwania w strukturze NGEarlyBreak. Wczesny punkt przerwania to możliwy punkt przerwania przed węzłem blokowym, w jego wnętrzu lub przed linią (czyli blokową linią kontenera lub linią elastyczną). Możemy tworzyć łańcuch lub ścieżkę obiektów NGEarlyBreak, na wypadek, gdyby najlepszy punkt przerwania znajdował się gdzieś głęboko w czymś, co przebyliśmy wcześniej, gdy skończyło się miejsce. Oto przykład:

W tym przypadku kończymy miejsce tuż przed właściwością #second, ale atrybut „break-before:avoid” może otrzymać ocenę „naruszenie zasad unikania przerwy na reklamę”. W tym momencie mamy łańcuch NGEarlyBreak „wewnątrz #outer > wewnątrz #middle > wewnątrz #inner > przed „linią 3” z tekstem „idealny”, więc wolimy go przerwać. Musimy więc wrócić i ponownie uruchomić układ od początku #outer (tym razem minie NGEarlyBreak, którą znaleźliśmy), by zrobić przerwę przed „linią 3” w #inner. (Dzielimy go przed „linią 3”, tak aby pozostałe 4 wiersze znalazły się w następnym elemencie „fragmentator” (w celu uwzględnienia funkcji widows:4).

Algorytm został tak zaprojektowany, aby zawsze działał w najlepszym możliwym punkcie przerwania (zgodnie z definicją w spec) przez upuszczanie reguł we właściwej kolejności, jeśli nie wszystkie są spełnione. Pamiętaj, że w każdym przepływie fragmentacji wystarczy przełożyć układ tylko raz. W momencie, gdy mamy 2 przebieg układu, najlepsza lokalizacja przerwy została już przekazana algorytmom układu, czyli miejsce przerwy wykrytej w pierwszym karnecie układu i udostępnione w ramach danych wyjściowych układu w tej rundzie. W drugim przypadku układu nie będzie omawiać, dopóki nie skończy się miejsce – w rzeczywistości nie zabraknie nam miejsca (w rzeczywistości to byłby błąd), bo zapewniliśmy wyjątkowo urocze (choć równie słodkie, jak to było dostępne) miejsce, w którym można wstawić wczesną przerwę, aby uniknąć niepotrzebnego naruszania zasad. Po prostu przejdziemy do tego punktu i przejdziemy dalej.

W związku z tym czasami musimy naruszać niektóre z prośby o unikanie przerw w działaniu, jeśli pomaga to uniknąć nadmiaru obiektów fragmentainera. Przykład:

W tym miejscu kończy się miejsce tuż przed #second, ale występuje w nim atrybut „break-before:void”. Tak jak w ostatnim przykładzie, jest to przetłumaczone jako „naruszenie zasad unikania przerwy na reklamę”. Mamy też test NGEarlyBreak z opisem „naruszenie zasad dotyczących sieroci i wdów” (wewnątrz #first > przed „linią 2”). Wciąż nie jest on doskonały, ale lepszy niż „naruszenie zasad unikania przerw”. Oznacza to, że usuniemy go przed „linią 2”, co narusza żądanie osieroconych / wdów. Specyfikacja odpowiada temu w sekcji 4.4. Niewymuszone przerwy, w których określa się, które reguły naruszające zasady są ignorowane jako pierwsze, jeśli nie ma wystarczającej liczby punktów przerwania, by uniknąć nadmiaru fragmentacji.

Podsumowanie

Głównym celem funkcjonalnym w ramach projektu fragmentacji bloków UkładNG jest udostępnienie implementacji obsługującej architekturę LayoutNG wszystko, co obsługuje starszy mechanizm, oraz jak najwięcej innych poprawek z wyjątkiem poprawek błędów. Głównym wyjątkiem jest lepsza obsługa unikania przerw (np. break-before:avoid), ponieważ jest to główna część mechanizmu fragmentacji, więc trzeba było ją uwzględnić od początku, ponieważ dodanie jej później oznaczałoby kolejne przeredagowanie.

Teraz gdy fragmentacja bloku UkładNG jest zakończona, możemy zacząć dodawać nowe funkcje, takie jak obsługa różnych rozmiarów stron podczas drukowania, korzystanie z @page pól na marginesie podczas drukowania czy box-decoration-break:clone. Podobnie jak w przypadku LayoutNG – oczekujemy, że liczba błędów i nakład pracy związany z utrzymaniem nowego systemu będą z czasem znacznie mniejsze.

Dziękujemy za uwagę!

Podziękowania