Spargerea casetelor cu fragmentare CSS
Publicat: 2022-03-10În acest articol, vă voi prezenta specificația CSS Fragmentation. S-ar putea să nu fi auzit niciodată de ea, totuși, dacă ați creat vreodată o foaie de stil de tipărire și ați dorit să controlați locul în care conținutul se întrerupe între pagini sau aspectul cu mai multe coloane și ați vrut să opriți o cifră care se rupe între coloane, ați întâlnit-o.
Găsesc că destul de des problemele raportate de oameni cu multicol sunt într-adevăr probleme cu suportul browserului pentru fragmentare. După o scurtă descriere a proprietăților conținute în această specificație, voi explica starea actuală a suportului pentru browser și câteva dintre lucrurile pe care le puteți face pentru ca acesta să funcționeze cât mai bine în proiectele dvs. multicol și de tipărire.
Ce este fragmentarea?
Fragmentarea în CSS descrie procesul prin care conținutul este împărțit în diferite casete. În prezent, avem două locuri în care s-ar putea să ne confruntăm cu fragmentare pe web: atunci când tipărim un document și dacă folosim aspectul cu mai multe coloane. Aceste două lucruri sunt în esență aceleași. Când imprimați (sau salvați în PDF) o pagină web, conținutul este fragmentat în câte pagini sunt necesare pentru a vă imprima conținutul.
Când utilizați multicol, conținutul este fragmentat în coloane. Fiecare casetă de coloană este ca o pagină în contextul paginat. Dacă vă gândiți la un set de coloane ca fiind mult ca un set de pagini, poate fi o modalitate utilă de a vă gândi la multicol și la modul în care funcționează fragmentarea în el.
Dacă aruncați o privire la specificația de fragmentare CSS, veți vedea un al treilea context fragmentat menționat - acel context este Regiunile. Deoarece nu există implementări utilizabile actuale ale regiunilor, nu ne vom ocupa de asta în acest articol, ci ne vom uita la cele două contexte pe care le-ați putea întâlni în munca dvs.
Blocuri și cutii în linie
O să menționez foarte mult casetele bloc în acest articol. Fiecare element al paginii dvs. are o casetă. Unele dintre aceste casete sunt așezate ca blocuri: paragrafe, articole din listă, titluri. Se spune că acestea participă într-un context de formatare bloc. Altele sunt în linie, cum ar fi cuvintele dintr-un paragraf, se întinde și elementele de ancorare. Acestea participă la un context de formatare inline. Mai simplu, când mă refer la o casetă de bloc, vorbesc despre casete în jurul unor lucruri precum paragrafe. Când aveți de-a face cu fragmentarea, este important să știți cu ce tip de cutie aveți de-a face.
Pentru mai multe informații despre aspectul bloc și inline, consultați articolul MDN „Aspect bloc și inline în flux normal”. Este unul dintre acele lucruri pe care probabil le înțelegem cu toții la un anumit nivel, dar este posibil să nu fi întâlnit terminologia înainte.
Controlul pauzelor
Indiferent dacă creați o foaie de stil de imprimare, folosind un anumit agent de utilizator de imprimare pentru a crea un PDF sau folosiți multicol, uneori veți întâlni probleme care arată astfel.
În exemplul multicol de mai jos, am un conținut pe care îl afișez în trei coloane. În mijlocul conținutului se află o zonă cu casete, care este împărțită pe două coloane. Nu vreau acest comportament — aș dori ca cutia să rămână împreună.
Pentru a remedia acest lucru, adaug proprietatea break-inside: avoid
la casetă. Controalele proprietății break-inside
sparge interiorul elementelor atunci când acestea se află într-un context fragmentat. Într-un browser care acceptă această proprietate, caseta va rămâne acum într-una dintre coloane. Coloanele vor arăta mai puțin bine echilibrate, totuși, acesta este, în general, un lucru mai bun decât a se termina cu împărțirea boxout pe coloane.
Proprietatea break-inside
este una dintre proprietățile detaliate în specificația de fragmentare. Lista completă a proprietăților este următoarea:
-
break-before
-
break-after
-
break-inside
-
orphans
-
widows
-
box-decoration-break
Să aruncăm o privire la cum ar trebui să funcționeze acestea înainte de a trece la ceea ce se întâmplă de fapt în browsere.
Proprietățile break-before
și break-after
Există două proprietăți care controlează pauzele între casetele la nivel de bloc: break-before
și break-after
. Dacă aveți un h2
urmat de două paragrafe <p>
, aveți trei casete de bloc și ați folosi aceste proprietăți pentru a controla pauzele dintre titlu și primul paragraf sau dintre cele două paragrafe.
Proprietățile sunt utilizate pe selectoare care vizează elementul pe care doriți să îl spargeți înainte sau după.
De exemplu, ați putea dori ca foaia dvs. de stil de imprimare să intre pe o pagină nouă de fiecare dată când există un titlu de nivel 2. În acest caz, veți folosi break-before: page
pe elementul h2
. Acest lucru controlează fragmentarea și asigură că există întotdeauna o pauză înaintea casetei elementului h2
.
h2 { break-before: page; }
O altă cerință comună este aceea de a preveni ca titlurile să ajungă ca ultimul lucru dintr-o pagină sau coloană. În acest caz, puteți utiliza break-after
cu o valoare de avoid
. Acest lucru ar trebui să prevină o pauză direct după cutia elementului:
h1, h2, h3, h4 { break-after: avoid; }
Fragmente în interiorul fragmentelor
Este posibil să aveți un element care este fragmentat imbricat în altul. De exemplu, având un multicol în interiorul ceva care este paginat. În acest caz, este posibil să doriți să controlați pauzele pentru pagini, dar nu pentru coloane sau invers. Acesta este motivul pentru care avem valori precum page
care ar forța întotdeauna o pauză înainte sau după element, dar numai atunci când fragmentul este o pagină. Sau avoid-page
care ar evita o pauză înainte sau după element numai pentru contexte paginate.
Același lucru este valabil și pentru coloane. Dacă utilizați column
cu valoare , aceasta ar forța întotdeauna o pauză înainte sau după acel element, dar numai pentru contexte multicol. Valoarea avoid-column
ar preveni o întrerupere în contexte multicol.
Există always
o valoare în specificația de nivel 4 care indică faptul că doriți să spargeți totul - pagină sau coloană. Cu toate acestea, ca o adăugare recentă la specificație, nu ne este util în prezent.
Valori suplimentare pentru media paginată
Dacă creați o carte sau o revistă, aveți pagini din stânga și din dreapta. S-ar putea să doriți să controlați ruperea pentru a forța ceva pe pagina din stânga sau din dreapta a unui spread. Prin urmare, utilizarea următoarelor ar insera una sau două pauze de pagină înainte de h2
pentru a se asigura că a fost formatat ca o pagină corectă.
h2 { break-before: right; }
Există, de asemenea, valori recto și verso care se referă la progresia paginii, deoarece cărțile scrise într-o limbă verticală sau de la dreapta la stânga au o progresie de pagină diferită de cărțile scrise în limba engleză. Nu voi acoperi aceste valori în continuare în acest articol, deoarece sunt în primul rând preocupat de ceea ce este posibil din browser de data aceasta.
break-inside
Am văzut deja un exemplu de proprietate break-inside
. Această proprietate controlează spargerea în interiorul casetelor de bloc, de exemplu în interiorul unui paragraf, titlu sau div.
Lucrurile pe care s-ar putea să nu doriți să le spargeți pot include o casetă așa cum este descris mai sus: figuri în care nu doriți ca legenda să fie desprinsă din imagine, tabele, liste și așa mai departe. Adăugați break-inside: avoid
în orice container pe care nu doriți să îl spargeți în niciun context de fragmentare. Dacă doriți să evitați doar pauzele între coloane, utilizați break-inside: avoid-column
și între pagini break-inside: avoid-page
.
orphans
Și widows
Proprietăți
Proprietățile orphans
și widows
se ocupă de câte rânduri ar trebui să rămână înainte sau după o pauză (fie cauzată de o coloană, fie de o pagină nouă). De exemplu, dacă vreau să evit ca o singură linie să fie lăsată la sfârșitul unei coloane, aș folosi proprietatea orphans
, ca în tipografie, un orfan este primul rând al unui paragraf care apare singur în partea de jos a unei pagini cu restul paragrafului spart pe altă pagină. Proprietatea ar trebui adăugată aceluiași element care se fragmentează (în cazul nostru, containerul multicol).
.container { column-count: 3; orphans: 2; }
Pentru a controla câte rânduri ar trebui să fie în partea de sus a unei coloane sau pagini după o pauză, utilizați widows
:
.container { column-count: 3; widows: 2; }
Aceste proprietăți se ocupă de întreruperi între casetele inline, cum ar fi rândurile de cuvinte din interiorul unui paragraf. Prin urmare, ele nu ajută în situația în care un titlu sau alt element de bloc este singur în partea de jos a unei coloane sau a unei pagini, aveți nevoie de proprietățile de pauză discutate mai sus pentru asta.
Decorare cutie
O proprietate finală care poate fi de interes este proprietatea box-decoration-break
. Aceasta controlează situația în care aveți o casetă cu un chenar între două casete de coloană sau pagini. Vrei ca chenarul să fie, în esență, tăiat în jumătate? Sau vrei ca fiecare dintre cele două jumătăți ale cutiei să fie înfășurată complet într-un chenar?
Primul scenariu este implicit și este ca și cum ați seta proprietatea box-decoration-break
pentru a slice
pe cutie.
.box { box-decoration-break: slice; }
Pentru a obține al doilea comportament, setați box-decoration-break
pentru a clona.
.box { box-decoration-break: clone; }
Suport pentru browser pentru fragmentare
Acum ajungem la motivul pentru care nu am o grămadă de exemple CodePen de mai sus pentru a vă demonstra toate acestea și motivul principal pentru care scriu acest articol. Suportul de browser pentru aceste proprietăți nu este grozav.
Dacă lucrați în Paged Media cu un agent utilizator specific, cum ar fi Prince, atunci vă puteți bucura de un suport foarte bun pentru fragmentare și, probabil, veți găsi aceste proprietăți foarte utile. Dacă lucrați cu un browser web, fie în multicol, creând foi de stil de imprimare sau utilizați ceva de genul Headless Chrome pentru a genera PDF-uri, suportul este oarecum neregulat. Veți descoperi că browserul cu cel mai bun suport este Edge – până când oricum se mută la Chromium!
Can I Use nu este prea util în explicarea suportului din cauza amestecării proprietăților de fragmentare cu multicol, apoi având câteva date separate pentru proprietățile moștenite. Așadar, ca parte a muncii pe care am făcut-o pentru MDN pentru a documenta proprietățile și suportul acestora, am început să testez suportul real pentru browser. Ceea ce urmează sunt câteva sfaturi bazate pe aceste teste.
Proprietățile moștenite și prefixate ale furnizorului
Nu pot merge mult mai departe fără o lecție de istorie. Dacă descoperiți că aveți într-adevăr nevoie de suport pentru fragmentare, atunci este posibil să găsiți o oarecare ușurare în proprietățile moștenite care au fost inițial parte din CSS2 (sau în unele proprietăți prefixate care există).
În CSS2, existau proprietăți pentru a controla ruperea paginii. Multicol nu exista în acel moment, așa că singurul context fragmentat era unul paginat. Aceasta a însemnat că au fost introduse trei proprietăți specifice de rupere a paginii:
-
page-break-before
-
page-break-after
-
page-break-inside
Acestea funcționează într-un mod similar cu proprietățile mai generice fără prefixul de page-
, controlând pauzele înainte, după și în interiorul casetelor. Pentru foile de stil de tipărire, veți descoperi că unele browsere mai vechi, care nu acceptă noile proprietăți break-
, acceptă aceste proprietăți prefixate de pagină. Proprietățile sunt tratate ca alias-uri pentru noile proprietăți.
Într-un proiect de lucru din 2005 al specificației multicol sunt detalii despre proprietățile de rupere pentru multicol — folosind proprietăți prefixate cu column-
(adică column-break-before
, column-break-after
și column-break-inside
). Până în 2009, acestea dispăruseră, iar în specificația multicol era o versiune nefinalizată pentru proprietățile de întrerupere fără prefix, care în cele din urmă și-au făcut loc în specificația CSS Fragmentation.
Cu toate acestea, unele proprietăți specifice coloanei prefixate de furnizor au fost implementate pe baza acestor proprietăți. Acestea sunt:
-
-webkit-column-break-before
-
-webkit-column-break-after
-
-webkit-column-break-inside
Suport pentru fragmentare în multicol
Următoarele se bazează pe testarea acestor caracteristici în contexte multicol. Am încercat să explic ce este posibil, dar aruncați o privire la CodePens în orice browser aveți la dispoziție.
Multicol Și break-inside
Suportul în multicol este cel mai bun pentru proprietatea break-inside
. Versiunile actualizate de Chrome, Firefox, Edge și Safari acceptă toate break-inside: avoid
. Așa că ar trebui să descoperiți că puteți preveni ruperea cutiilor între coloane atunci când utilizați multicol.
Mai multe browsere, cu excepția Firefox, acceptă proprietatea -webkit-column-break-inside
, aceasta poate fi folosită cu valoarea avoid
și poate împiedica ruperea casetelor între coloane care nu au suport pentru break-inside
.
Firefox acceptă page-break-inside: avoid
în multicol. Prin urmare, utilizarea acestei proprietăți va preveni întreruperile din interiorul cutiilor din browserele Firefox înainte de Firefox 65.
Aceasta înseamnă că, dacă doriți să preveniți pauzele între casete în multicol, utilizarea următorului CSS va acoperi cât mai multe browsere posibil, mergând înapoi cât mai mult posibil.
.box { -webkit-column-break-inside: avoid; page-break-inside: avoid; break-inside: avoid; }
În ceea ce privește valoarea column
, afirmând în mod explicit că doriți doar să evitați pauzele între coloane, și nu pagini, funcționează în toate browserele, cu excepția Firefox.
Codul de mai jos prezintă câteva dintre aceste teste în multicol, astfel încât să le puteți încerca singur.
Multicol Si break-before
Pentru a preveni întreruperea înaintea unui element, ar trebui să puteți utiliza break-before: avoid
sau break-before: avoid-column
. Proprietatea avoid nu are suport pentru browser.
Edge suportă break-before: column
pentru a forța întotdeauna o pauză înaintea casetei elementului.
Safari, Chrome și Edge acceptă și -webkit-column-break-before: always
care va forța o pauză înaintea casetei elementului. Prin urmare, dacă doriți să forțați o pauză înaintea casetei unui element, ar trebui să utilizați:
.box { -webkit-column-break-before: always; break-before: column; }
Prevenirea unei pauze înainte de cutie este în prezent o sarcină imposibilă. Vă puteți juca mai jos cu câteva exemple de aceste proprietăți:
Multicol Și break-after
Pentru a preveni rupturi după un element, pentru a evita ca acesta să devină ultimul lucru din partea de jos a unei coloane, ar trebui să puteți folosi break-after: avoid
și break-after: avoid-column
. Singurul browser cu suport pentru acestea este Edge.
Edge acceptă, de asemenea, forțarea pauzelor după un element prin utilizarea break-after: column
, Chrome acceptă break-after: column
și, de asemenea, -webkit-column-break-after: always
.
Firefox nu acceptă break-after
sau oricare dintre proprietățile prefixate pentru a forța sau permite pauze după o casetă.
Prin urmare, în afară de Edge, nu puteți evita cu adevărat pauzele după o cutie. Dacă doriți să le forțați, veți obține rezultate în unele browsere utilizând următorul CSS:
.box { -webkit-break-after: always; break-after: column; }
Asistență la imprimarea din browser
Indiferent dacă imprimați direct din browserul desktop sau generați fișiere PDF folosind Chrome fără cap sau altă soluție care se bazează pe tehnologia browserului, nu are nicio diferență. Vă bazați pe suportul browserului pentru proprietățile de fragmentare.
Dacă creați o foaie de stil de imprimare, veți găsi suport similar pentru proprietățile break ca și pentru multicol; totuși, pentru a accepta browsere mai vechi, ar trebui să dublați proprietățile pentru a utiliza proprietățile prefixate de page-
.
Tipăriți foi de stil și break-inside
În browserele moderne, proprietatea break-inside
poate fi utilizată pentru a preveni întreruperile în interiorul cutiilor, adăugați proprietatea page-break-inside
pentru a adăuga suport pentru browserele mai vechi.
.box { page-break-inside: avoid; break-inside: avoid; }
Tipăriți foi de stil și break-before
Pentru a forța pauzele înaintea unei casete, utilizați break-before:page
împreună cu page-break-before: always
.
.box { page-break-before: always; break-before: page; }
Pentru a evita pauzele înaintea unei casete, utilizați break-before: avoid-page
împreună cu page-break-before: avoid
.
.box { page-break-before: avoid; break-before: avoid-page; }
Există un suport mai bun pentru valorile de page
și avoid-page
decât vedem pentru valorile multicol echivalente. Majoritatea browserelor moderne au suport.
Tipăriți foi de stil și break-before
Pentru a forța pauzele după o casetă, utilizați break-after: page
împreună cu page-break-after: always
.
.box { page-break-after: always; break-after: page; }
Pentru a preveni pauzele după o cutie, utilizați break-after: avoid-page
împreună cu page-break-after: avoid
.
.box { page-break-after: avoid; break-after: avoid-page; }
Văduve și Orfani
Proprietățile widows
și orphans
se bucură de un suport bun între browsere - singurul browser fără implementare fiind Firefox. Aș sugera să le folosiți atunci când creați un aspect multicol sau o foaie de stil de imprimare. Dacă nu funcționează dintr-un motiv oarecare, veți avea văduve și orfani, ceea ce nu este ideal, dar nici nu este un dezastru. Dacă funcționează, tipografia ta va arăta cu atât mai bine.
cutie-decor-pauza
Proprietatea finală a box-decoration-break
are suport pentru multicol și print în Firefox. Safari, Chrome și alte browsere bazate pe Chromium acceptă -webkit-box-decoration-break
, dar numai pe elementele inline. Deci, puteți clona chenarele rotunde ale unei propoziții, de exemplu; nu au sprijin în contextul pe care îl analizăm.
În CodePen de mai jos, puteți vedea că testarea pentru -webkit-box-decoration-break: clone
cu Interogări caracteristici returnează adevărat; cu toate acestea, proprietatea nu are efect asupra marginii cutiei în contextul multicol.
Utilizarea fragmentării
După cum puteți vedea, starea actuală de fragmentare în browsere este oarecum fragmentată! Acestea fiind spuse, există o sumă rezonabilă pe care o puteți obține și, acolo unde eșuează, rezultatul tinde să fie suboptim, dar nu un dezastru. Ceea ce înseamnă că merită încercat.
Este demn de remarcat faptul că a fi prea greoi cu aceste proprietăți ar putea avea ca rezultat altceva decât ceea ce ați sperat. Dacă lucrați pe web, mai degrabă decât tipăriți și forțați întreruperea coloanelor după fiecare paragraf, atunci ajungeți cu mai multe paragrafe decât spațiu pentru coloane, multicol va ajunge să se debordeze în direcția inline. Va rămâne fără coloane pentru a vă plasa paragrafele suplimentare. Prin urmare, chiar și acolo unde există suport, trebuie să testați cu atenție și să vă amintiți că mai puțin înseamnă mai mult în multe cazuri.
Mai multe resurse
Pentru a citi mai multe despre proprietăți, mergeți la MDN, am actualizat recent paginile de acolo și, de asemenea, încerc să păstrez datele de compatibilitate ale browserului la zi. Pagina principală pentru Fragmentarea CSS face link-uri către paginile de proprietăți individuale care au exemple suplimentare, date de compatibilitate cu browserul și alte informații despre utilizarea acestor proprietăți.