Spargerea casetelor cu fragmentare CSS

Publicat: 2022-03-10
Rezumat rapid ↬ Rachel Andrew a căutat în specificațiile CSS Fragmentation, iar găsirea suportului pentru browser este oarecum fragmentată. În acest articol, ea explică ce este fragmentarea, de ce ați putea dori să o utilizați și care este starea suportului pentru browser.

Î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.

Mai multe după săritură! Continuați să citiți mai jos ↓

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ă.

Trei coloane cu o zonă delimitată între două dintre ele
Caseta se desparte pe două coloane (previzualizare mare)

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.

Vezi exemplul de spargere în interiorul Pen Simple de (Rachel Andrew.

Vezi exemplul de spargere în interiorul Pen Simple de (Rachel Andrew.

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; } 
O cutie cu un chenar care este spart între coloane
O valoare a slice înseamnă că chenarul este efectiv tăiat în jumătate (Previzualizare mare)

Pentru a obține al doilea comportament, setați box-decoration-break pentru a clona.

 .box { box-decoration-break: clone; } 
Cutiile sunt complet împachetate în chenare
O valoare a clonului înseamnă că chenarul este înfășurat complet în jurul fiecărui fragment al casetei (previzualizare mare)

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.

Vezi testul de fragmentare a stiloului multicol: spargere în interior de Rachel Andrew.

Vezi testul de fragmentare a stiloului multicol: spargere în interior de Rachel Andrew.

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:

Vezi Testul de fragmentare a stiloului multicol: break-before de Rachel Andrew).

Vezi Testul de fragmentare a stiloului multicol: break-before de Rachel Andrew).

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; } 

A se vedea testul de fragmentare multicol Pen: break-after de Rachel Andrew).

A se vedea testul de fragmentare multicol Pen: break-after de Rachel Andrew).

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.

Vezi Pen Multicol: box-decoration-break de Rachel Andrew.

Vezi Pen Multicol: box-decoration-break de Rachel Andrew.

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.