Łamanie pudełek za pomocą fragmentacji CSS
Opublikowany: 2022-03-10W tym artykule przedstawię specyfikację fragmentacji CSS. Być może nigdy o tym nie słyszałeś, jednak jeśli kiedykolwiek stworzyłeś arkusz stylów drukowania i chciałeś kontrolować, gdzie zawartość łamie się między stronami lub układ wielokolumnowy i chciałeś zapobiec łamaniu się figury między kolumnami, natknąłeś się na to.
Uważam, że dość często problemy zgłaszane przez ludzi z multicol są tak naprawdę problemami z obsługą fragmentacji przez przeglądarki. Po krótkim omówieniu właściwości zawartych w tej specyfikacji wyjaśnię bieżący stan obsługi przeglądarek i kilka rzeczy, które możesz zrobić, aby działały tak dobrze, jak w projektach multicol i print.
Co to jest fragmentacja?
Fragmentacja w CSS opisuje proces, w którym zawartość zostaje podzielona na różne pola. Obecnie mamy dwa miejsca, w których możemy natrafić na fragmentację w sieci: kiedy drukujemy dokument i jeśli korzystamy z układu wielokolumnowego. Te dwie rzeczy są zasadniczo takie same. Gdy drukujesz (lub zapisujesz w pliku PDF) stronę internetową, jej zawartość jest podzielona na tyle stron, ile jest wymagane do wydrukowania zawartości.
Gdy używasz multicol, zawartość jest podzielona na kolumny. Każde pole kolumny jest jak strona w kontekście stronicowania. Jeśli myślisz, że zestaw kolumn jest bardzo podobny do zestawu stron, może to być pomocny sposób myślenia o multicol i o tym, jak działa w nim fragmentacja.
Jeśli spojrzysz na specyfikację fragmentacji CSS, zobaczysz trzeci wspomniany pofragmentowany kontekst — ten kontekst to regiony. Ponieważ nie ma obecnie użytecznych implementacji Regionów, nie będziemy się tym zajmować w tym artykule, ale zamiast tego przyjrzymy się dwóm kontekstom, na które możesz natknąć się w swojej pracy.
Pudełka blokowe i wbudowane
W tym artykule będę często wspominał o skrzynkach blokowych. Każdy element Twojej strony ma pole. Niektóre z tych pól są ułożone jako bloki: akapity, pozycje listy, nagłówki. Mówi się, że uczestniczą w kontekście formatowania blokowego. Inne są wbudowane, takie jak słowa w akapicie, spas i elementy zakotwiczenia. Uczestniczą one w kontekście formatowania wbudowanego. Mówiąc prościej, kiedy odnoszę się do pola blokowego, mówię o polach wokół takich rzeczy, jak akapity. Kiedy mamy do czynienia z fragmentacją, ważne jest, aby wiedzieć, z jakim rodzajem pudełka mamy do czynienia.
Aby uzyskać więcej informacji na temat układu blokowego i wbudowanego, zobacz artykuł MDN „Układ blokowy i wbudowany w normalnym przepływie”. Jest to jedna z tych rzeczy, które prawdopodobnie wszyscy rozumiemy na pewnym poziomie, ale być może wcześniej nie spotkaliśmy się z terminologią.
Kontrolowanie przerw
Niezależnie od tego, czy tworzysz arkusz stylów drukowania, używasz specjalnego agenta użytkownika drukowania do utworzenia pliku PDF, czy używasz multicol, czasami napotkasz problemy, które wyglądają tak.
W poniższym przykładzie multicol mam zawartość, którą wyświetlam w trzech kolumnach. W środku treści znajduje się obramowany obszar, który jest podzielony na dwie kolumny. Nie chcę tego zachowania — chciałbym, żeby pudełko pozostało razem.
Aby to naprawić, dodaję właściwość break-inside: avoid
do pudełka. Właściwość break-inside
steruje przerwaniami wewnątrz elementów, gdy znajdują się one w kontekście pofragmentowanym. W przeglądarce, która obsługuje tę właściwość, pole pozostanie teraz w jednej z kolumn. Kolumny będą jednak wyglądały na mniej wyważone, co generalnie jest lepsze niż rozbicie boxoutu na kolumny.
Właściwość break-inside
jest jedną z właściwości wyszczególnionych w specyfikacji fragmentacji. Pełna lista nieruchomości przedstawia się następująco:
-
break-before
-
break-after
-
break-inside
-
orphans
-
widows
-
box-decoration-break
Przyjrzyjmy się, jak mają one działać, zanim przejdziemy do tego, co faktycznie dzieje się w przeglądarkach.
break-before
i break-after
Właściwości
Istnieją dwie właściwości, które kontrolują przerwy między polami blokowymi: break-before
i break-after
. Jeśli masz h2
, po którym następują dwa akapity, <p>
masz trzy pola blokowe i użyjesz tych właściwości do kontrolowania przerw między nagłówkiem a pierwszym akapitem lub między dwoma akapitami.
Właściwości są używane w selektorach, których celem jest element, który chcesz przerwać przed lub po.
Na przykład możesz chcieć, aby arkusz stylów drukowania był dzielony na nową stronę za każdym razem, gdy występuje nagłówek poziomu 2. W tym przypadku użyjesz break-before: page
na elemencie h2
. Kontroluje to fragmentację i zapewnia, że przed pudełkiem elementu h2
zawsze jest przerwa.
h2 { break-before: page; }
Innym powszechnym wymogiem jest zapobieganie, aby nagłówki kończyły się jako ostatnia rzecz na stronie lub kolumnie. W takim przypadku możesz użyć break-after
z wartością avoid
. Powinno to zapobiec przerwie bezpośrednio za pudełkiem elementu:
h1, h2, h3, h4 { break-after: avoid; }
Fragmenty wewnątrz fragmentów
Możliwe, że element, który jest pofragmentowany, jest zagnieżdżony w innym. Na przykład posiadanie multicol wewnątrz czegoś, co jest stronicowane. W takim przypadku możesz chcieć kontrolować przerwy dla stron, ale nie dla kolumn lub na odwrót. Dlatego mamy takie wartości jak page
, które zawsze wymuszają przerwę przed lub po elemencie, ale tylko wtedy, gdy fragment jest stroną. Lub avoid-page
, która pozwoliłaby uniknąć przerwy przed lub po elemencie tylko w przypadku stronicowanych kontekstów.
To samo dotyczy kolumn. Jeśli użyjesz column
wartości , zawsze wymusi to przerwę przed lub po tym elemencie, ale tylko w przypadku kontekstów multicol. Wartość avoid-column
zapobiegłaby przerwom w kontekstach wielokolumnowych.
W specyfikacji poziomu 4 always
znajduje się wartość, która wskazuje, że chcesz przebić się przez wszystko — stronę lub kolumnę. Jednak jako niedawny dodatek do specyfikacji nie jest on obecnie dla nas przydatny.
Dodatkowe wartości dla stronicowanych mediów
Jeśli tworzysz książkę lub czasopismo, masz lewą i prawą stronę. Możesz kontrolować łamanie, aby wymusić coś na lewej lub prawej stronie rozkładówki. Dlatego użycie poniższego spowoduje wstawienie jednej lub dwóch stron łamania przed h2
, aby upewnić się, że została sformatowana jako właściwa strona.
h2 { break-before: right; }
Istnieją również wartości recto i verso, które odnoszą się do progresji stron, ponieważ książki napisane w języku pionowym lub od prawej do lewej mają inną progresję stron niż książki napisane w języku angielskim. Nie będę omawiał tych wartości dalej w tym artykule, ponieważ tym razem interesuje mnie przede wszystkim to, co jest możliwe z przeglądarki.
break-inside
Widzieliśmy już przykład nieruchomości break-inside
. Właściwość ta kontroluje łamanie wewnątrz pól blokowych, np. wewnątrz akapitu, nagłówka lub div.
Rzeczy, których możesz nie chcieć złamać, mogą zawierać ramkę, jak opisano powyżej: liczby, w których nie chcesz, aby podpis był oddzielony od obrazu, tabele, listy i tak dalej. Dodaj break-inside: avoid
kontenera, którego nie chcesz przerywać w kontekście fragmentacji. Jeśli chcesz tylko uniknąć przerw między kolumnami, użyj break-inside: avoid-column
i między stronami break-inside: avoid-page
.
orphans
I widows
Posiadłości
Właściwości orphans
i widows
określają, ile wierszy należy pozostawić przed lub po przerwie (spowodowanej przez kolumnę lub nową stronę). Na przykład, jeśli chcę uniknąć pozostawienia pojedynczego wiersza na końcu kolumny, użyłbym właściwości orphans
, tak jak w typografii, sierota to pierwszy wiersz akapitu, który pojawia się sam na dole strony z reszta akapitu podzielona na inną stronę. Właściwość należy dodać do tego samego elementu, który fragmentuje (w naszym przypadku do kontenera multicol).
.container { column-count: 3; orphans: 2; }
Aby kontrolować, ile wierszy powinno znajdować się na górze kolumny lub strony po przerwie, użyj widows
:
.container { column-count: 3; widows: 2; }
Te właściwości dotyczą przerw między polami śródliniowymi, takimi jak wiersze słów w akapicie. Dlatego nie pomagają w sytuacji, gdy nagłówek lub inny element bloku jest sam na dole kolumny lub strony, do tego potrzebne są właściwości break omówione powyżej.
Dekoracja pudełka
Ostatnią właściwością, która może być interesująca, jest właściwość box-decoration-break
. Kontroluje to sytuację, w której masz ramkę z przerwaną ramką między dwiema ramkami kolumn lub stronami. Czy chcesz, aby granica była zasadniczo przecięta na pół? A może chcesz, aby każda z dwóch połówek pudełka była całkowicie owinięta ramką?
Pierwszy scenariusz jest domyślny i wygląda tak, jakby ustawić właściwość box-decoration-break
na slice
na polu.
.box { box-decoration-break: slice; }
Aby uzyskać drugie zachowanie, ustaw box-decoration-break
na clone.
.box { box-decoration-break: clone; }
Obsługa przeglądarek dla fragmentacji
Teraz dochodzimy do powodu, dla którego nie mam powyżej kilku przykładów CodePen, aby to wszystko zademonstrować, i główny powód, dla którego napisałem ten artykuł. Obsługa tych właściwości przez przeglądarkę nie jest świetna.
Jeśli pracujesz w Paged Media z konkretnym agentem użytkownika, takim jak Prince, możesz cieszyć się naprawdę dobrą obsługą fragmentacji i prawdopodobnie uznasz te właściwości za bardzo przydatne. Jeśli pracujesz z przeglądarką internetową, w trybie wielokolorowym, tworząc arkusze stylów drukowania lub używając czegoś takiego jak Headless Chrome do generowania plików PDF, obsługa jest nieco niejednolita. Przekonasz się, że przeglądarką z najlepszą obsługą jest Edge — dopóki i tak nie zostanie przeniesiona na Chromium!
Czy mogę użyć nie jest zbyt pomocny w wyjaśnianiu obsługi ze względu na mieszanie właściwości fragmentacji z multicol, a następnie posiadanie oddzielnych danych dla starszych właściwości. Tak więc w ramach pracy, którą wykonywałem dla MDN, aby udokumentować właściwości i ich obsługę, zacząłem testować rzeczywistą obsługę przeglądarek. Poniżej znajduje się kilka porad opartych na tych testach.
Wcześniejsze i właściwości przedrostkowe dostawcy
Daleko nie mogę posunąć się bez lekcji historii. Jeśli okaże się, że naprawdę potrzebujesz wsparcia dla fragmentacji, możesz znaleźć pewną ulgę w starszych właściwościach, które pierwotnie były częścią CSS2 (lub w niektórych istniejących właściwościach z przedrostkiem).
W CSS2 istniały właściwości kontrolujące łamanie strony. Multicol w tym momencie nie istniał, więc jedynym fragmentarycznym kontekstem był kontekst stronicowany. Oznaczało to, że wprowadzono trzy konkretne właściwości łamania stron:
-
page-break-before
-
page-break-after
-
page-break-inside
Działają one podobnie do bardziej ogólnych właściwości bez page-
strony, kontrolując przerwy przed, po i wewnątrz pól. W przypadku arkuszy stylów drukowania zauważysz, że niektóre starsze przeglądarki, które nie obsługują nowych właściwości break-
, obsługują te właściwości z przedrostkiem strony. Właściwości są traktowane jako aliasy dla nowych właściwości.
W wersji roboczej specyfikacji multicol z 2005 r. znajdują się szczegóły dotyczące właściwości łamania dla multicol — przy użyciu właściwości poprzedzonych przedrostkiem column-
(tj column-break-before
, column-break-after
i column-break-inside
). Do 2009 roku te zniknęły, a szkic był w specyfikacji multicol dla nieprefiksowanych właściwości break, które ostatecznie trafiły do specyfikacji CSS Fragmentation.
Jednak niektóre właściwości specyficzne dla kolumny z przedrostkiem dostawcy zostały zaimplementowane na podstawie tych właściwości. To są:
-
-webkit-column-break-before
-
-webkit-column-break-after
-
-webkit-column-break-inside
Wsparcie dla fragmentacji w Multicol
Poniższe informacje są oparte na testowaniu tych funkcji w kontekstach wielokolorowych. Próbowałem wyjaśnić, co jest możliwe, ale spójrz na CodePens w dowolnej dostępnej przeglądarce.
Multicol i break-inside
Wsparcie w multicol jest najlepsze dla nieruchomości break-inside
. Aktualne wersje przeglądarek Chrome, Firefox, Edge i Safari obsługują break-inside: avoid
. Powinieneś więc zauważyć, że możesz zapobiec łamaniu pól między kolumnami podczas korzystania z multicol.
Kilka przeglądarek, z wyjątkiem Firefoksa, obsługuje właściwość -webkit-column-break-inside
, której można użyć z wartością avoid
i może uniemożliwić łamanie pól między kolumnami, które nie obsługują break-inside
.
Firefox obsługuje page-break-inside: avoid
w multicol. Dlatego użycie tej właściwości zapobiegnie przerwom wewnątrz pól w przeglądarkach Firefox przed Firefox 65.
Oznacza to, że jeśli chcesz zapobiec przerwom między polami w multicol, użycie poniższego CSS obejmie jak najwięcej przeglądarek, cofając się tak daleko, jak to możliwe.
.box { -webkit-column-break-inside: avoid; page-break-inside: avoid; break-inside: avoid; }
Jeśli chodzi o wartość column
, wyraźne stwierdzenie, że chcesz uniknąć przerw między kolumnami, a nie stronami, działa we wszystkich przeglądarkach oprócz Firefoksa.
Poniższy CodePen podsumowuje niektóre z tych testów w multicol, dzięki czemu możesz je wypróbować samodzielnie.
Multicol i break-before
Aby zapobiec przerwom przed elementem, powinieneś mieć możliwość użycia break-before: avoid
lub break-before: avoid-column
. Właściwość omijania nie obsługuje przeglądarki.
Edge obsługuje break-before: column
aby zawsze wymusić przerwę przed pudełkiem elementu.
Safari, Chrome i Edge obsługują również -webkit-column-break-before: always
co wymusza przerwę przed pudełkiem elementu. Dlatego jeśli chcesz wymusić przerwę przed pudełkiem elementu, powinieneś użyć:
.box { -webkit-column-break-before: always; break-before: column; }
Zapobieganie przerwie przed pudełkiem jest obecnie zadaniem niewykonalnym. Poniżej możesz pobawić się kilkoma przykładami tych właściwości:
Multicol i break-after
Aby zapobiec przerwom po elemencie, aby nie stał się on ostatnią rzeczą na dole kolumny, powinieneś mieć możliwość użycia break-after: avoid
i break-after: avoid-column
. Jedyną przeglądarką obsługującą to jest Edge.
Edge obsługuje również wymuszanie przerw po elemencie za pomocą break-after: column
, Chrome obsługuje break-after: column
a także -webkit-column-break-after: always
.
Firefox nie obsługuje break-after
ani żadnych właściwości z prefiksami, aby wymusić lub pozwolić na przerwy po ramce.
Dlatego też, poza Edge'em, nie można naprawdę uniknąć przerw po pudełku. Jeśli chcesz je wymusić, uzyskasz wyniki w niektórych przeglądarkach za pomocą następującego kodu CSS:
.box { -webkit-break-after: always; break-after: column; }
Wsparcie podczas drukowania z przeglądarki
Nie ma znaczenia, czy drukujesz bezpośrednio z przeglądarki na komputerze, czy generujesz pliki PDF za pomocą bezgłowego Chrome lub innego rozwiązania opartego na technologii przeglądarki. Jesteś uzależniony od obsługi przez przeglądarkę właściwości fragmentacji.
Jeśli utworzysz arkusz stylów drukowania, znajdziesz podobne wsparcie dla właściwości break, jak dla multicol; jednakże, aby obsługiwać starsze przeglądarki, należy podwoić właściwości, aby użyć właściwości z page-
strony.
Wydrukuj arkusze stylów i break-inside
W nowoczesnych przeglądarkach właściwość break-inside
może być używana do zapobiegania przerwom wewnątrz ramek. Dodaj właściwość page-break-inside
, aby dodać obsługę starszych przeglądarek.
.box { page-break-inside: avoid; break-inside: avoid; }
Wydrukuj arkusze stylów i break-before
Aby wymusić przerwy przed ramką, użyj break-before:page
wraz z page-break-before: always
.
.box { page-break-before: always; break-before: page; }
Aby uniknąć przerw przed ramką, użyj break-before: avoid-page
wraz z page-break-before: avoid
.
.box { page-break-before: avoid; break-before: avoid-page; }
Obsługa wartości page
i stron do avoid-page
jest lepsza niż w przypadku równoważnych wartości multicol. Większość nowoczesnych przeglądarek obsługuje.
Wydrukuj arkusze stylów i break-before
Aby wymusić podziały po ramce, użyj break-after: page
oraz page-break-after: always
.
.box { page-break-after: always; break-after: page; }
Aby zapobiec przerwom po ramce, użyj break-after: avoid-page
wraz z page-break-after: avoid
.
.box { page-break-after: avoid; break-after: avoid-page; }
Wdowy i sieroty
Właściwości widows
i orphans
cieszą się dobrą obsługą wielu przeglądarek — jedyną przeglądarką bez implementacji jest Firefox. Sugerowałbym ich użycie podczas tworzenia układu wielokolorowego lub arkusza stylów wydruku. Jeśli z jakiegoś powodu nie będą pracować, dostaniesz wdowy i sieroty, co nie jest idealne, ale też nie jest katastrofą. Jeśli zadziałają, twoja typografia będzie wyglądać lepiej.
Przerwa-dekoracyjna-pudełkowa
Ostatnia właściwość box-decoration-break
obsługuje multicol i print w Firefoksie. Safari, Chrome i inne przeglądarki oparte na Chromium obsługują -webkit-box-decoration-break
, ale tylko w elementach wbudowanych. Możesz więc na przykład klonować obramowania, zaokrąglając linie zdania; nie mają wsparcia w kontekście, na który patrzymy.
W poniższym CodePen możesz zobaczyć, że testowanie dla -webkit-box-decoration-break: clone
z zapytaniami funkcji zwraca wartość true; jednak właściwość nie ma wpływu na obramowanie pola w kontekście multicol.
Korzystanie z fragmentacji
Jak widać, obecny stan fragmentacji w przeglądarkach jest nieco pofragmentowany! To powiedziawszy, istnieje rozsądna kwota, którą możesz osiągnąć, a tam, gdzie się nie powiedzie, wynik jest zwykle nieoptymalny, ale nie katastrofa. Co oznacza, że warto spróbować.
Warto zauważyć, że zbytnie obchodzenie się z tymi właściwościami może skutkować czymś innym niż to, na co liczyłeś. Jeśli pracujesz w Internecie, zamiast drukować i wymuszać podziały kolumn po każdym akapicie, a następnie skończysz z większą liczbą akapitów niż miejsca na kolumny, multicol przepełni się w kierunku śródliniowym. Zabraknie kolumn, w których można umieścić dodatkowe akapity. Dlatego nawet tam, gdzie istnieje wsparcie, nadal musisz dokładnie testować i pamiętać, że w wielu przypadkach mniej znaczy więcej.
Więcej zasobów
Aby przeczytać więcej o właściwościach, przejdź do MDN, niedawno zaktualizowałem tam strony i staram się również aktualizować dane dotyczące kompatybilności przeglądarki. Strona główna fragmentacji CSS zawiera linki do poszczególnych stron właściwości, które zawierają dalsze przykłady, dane dotyczące zgodności przeglądarki i inne informacje dotyczące korzystania z tych właściwości.