Rompere le scatole con la frammentazione CSS

Pubblicato: 2022-03-10
Riassunto veloce ↬ Rachel Andrew ha scavato nelle specifiche della frammentazione CSS e la ricerca del supporto del browser è alquanto frammentaria. In questo articolo, spiega cos'è la frammentazione, perché potresti volerla utilizzare e qual è lo stato del supporto del browser.

In questo articolo, ti presenterò la specifica della frammentazione CSS. Potresti non averne mai sentito parlare, tuttavia, se hai mai creato un foglio di stile di stampa e volevi controllare dove si interrompe il contenuto tra le pagine o il layout a più colonne e volevi fermare una figura che si interrompe tra le colonne, l'hai incontrato.

Trovo che molto spesso i problemi che le persone segnalano con multicol siano in realtà problemi con il supporto della frammentazione del browser. Dopo una rapida carrellata delle proprietà contenute in questa specifica, spiegherò lo stato attuale del supporto del browser e alcune delle cose che puoi fare per farlo funzionare al meglio nei tuoi progetti multicol e di stampa.

Cos'è la frammentazione?

La frammentazione nei CSS descrive il processo mediante il quale il contenuto viene suddiviso in diverse caselle. Attualmente, abbiamo due punti in cui potremmo imbatterci in una frammentazione sul Web: quando stampiamo un documento e se utilizziamo il layout a più colonne. Queste due cose sono essenzialmente le stesse. Quando si stampa (o si salva in PDF) una pagina Web, il contenuto viene frammentato in tante pagine quante sono necessarie per stampare il contenuto.

Quando usi multicol, il contenuto viene frammentato in colonne. Ogni casella di colonna è come una pagina nel contesto della pagina. Se pensi che un insieme di colonne sia molto simile a un insieme di pagine, può essere un modo utile per pensare al multicolo e al modo in cui funziona la frammentazione in esso.

Se dai un'occhiata alla specifica di frammentazione CSS, vedrai menzionato un terzo contesto frammentato: quel contesto è Regions. Poiché non ci sono attualmente implementazioni utilizzabili di Regioni, non ne tratteremo in questo articolo, ma esamineremo invece i due contesti che potresti incontrare nel tuo lavoro.

Altro dopo il salto! Continua a leggere sotto ↓

Block E Scatole Inline

In questo articolo menzionerò molto le scatole a blocchi. Ogni elemento della tua pagina ha una casella. Alcune di queste caselle sono disposte come blocchi: paragrafi, voci di elenco, intestazioni. Si dice che partecipino a un contesto di formattazione a blocchi. Altri sono in linea come le parole in un paragrafo, le campate e gli elementi di ancoraggio. Questi partecipano a un contesto di formattazione in linea. In parole povere, quando mi riferisco a un riquadro a blocchi, sto parlando di riquadri attorno a cose come i paragrafi. Quando si ha a che fare con la frammentazione, è importante sapere con quale tipo di scatola si ha a che fare.

Per ulteriori informazioni sul layout a blocchi e inline, vedere l'articolo MDN "Layout a blocchi e inline nel flusso normale". È una di quelle cose che probabilmente tutti comprendiamo a un certo livello, ma potremmo non aver incontrato la terminologia di prima.

Controllo delle pause

Sia che tu stia creando un foglio di stile di stampa, utilizzando un programma utente di stampa specifico per creare un PDF o utilizzando multicol, a volte ti imbatterai in problemi simili a questo.

Nell'esempio multicolo di seguito, ho alcuni contenuti che sto visualizzando come tre colonne. Nel mezzo del contenuto c'è un'area inscatolata, che viene suddivisa su due colonne. Non voglio questo comportamento, vorrei che la scatola rimanesse unita.

Tre colonne con un'area inscatolata suddivisa su due di esse
Il riquadro si divide su due colonne (Anteprima grande)

Per risolvere questo problema, aggiungo la proprietà break-inside: avoid alla casella. I controlli della proprietà break-inside interrompono gli elementi all'interno quando si trovano in un contesto frammentato. In un browser che supporta questa proprietà, la casella ora rimarrà in una delle colonne. Le colonne sembreranno meno ben bilanciate, tuttavia, in genere è una cosa migliore che finire con il riquadro diviso tra le colonne.

Vedi l'esempio di irruzione Pen Simple di (Rachel Andrew.

Vedi l'esempio di irruzione Pen Simple di (Rachel Andrew.

La proprietà break-inside è una delle proprietà dettagliate nelle specifiche di frammentazione. L'elenco completo degli immobili è il seguente:

  • break-before
  • break-after
  • break-inside
  • orphans
  • widows
  • box-decoration-break

Diamo un'occhiata a come dovrebbero funzionare prima di passare a ciò che accade effettivamente nei browser.

Le proprietà break-before e break-after

Esistono due proprietà che controllano le interruzioni tra le caselle a livello di blocco: break-before e break-after . Se hai un h2 seguito da due paragrafi <p> ​​hai tre caselle di blocco e useresti queste proprietà per controllare le interruzioni tra l'intestazione e il primo paragrafo, o tra i due paragrafi.

Le proprietà vengono utilizzate sui selettori che prendono di mira l'elemento che si desidera interrompere prima o dopo.

Ad esempio, potresti voler inserire il foglio di stile di stampa su una nuova pagina ogni volta che è presente un'intestazione di livello 2. In questo caso, useresti break-before: page sull'elemento h2 . Questo controlla la frammentazione e assicura che ci sia sempre un'interruzione prima della casella dell'elemento h2 .

 h2 { break-before: page; }

Un altro requisito comune è evitare che le intestazioni finiscano come l'ultima cosa in una pagina o in una colonna. In questo caso, potresti usare break-after con un valore di avoid . Ciò dovrebbe impedire un'interruzione direttamente dopo la casella dell'elemento:

 h1, h2, h3, h4 { break-after: avoid; }

Frammenti all'interno di frammenti

È possibile che un elemento frammentato sia annidato all'interno di un altro. Ad esempio, avere un multicolo all'interno di qualcosa che viene impaginato. In tal caso, potresti voler controllare le interruzioni per le pagine ma non per le colonne, o viceversa. Questo è il motivo per cui abbiamo valori come page che forzerebbero sempre un'interruzione prima o dopo l'elemento ma solo quando il frammento è una pagina. O avoid-page che eviterebbe un'interruzione prima o dopo l'elemento solo per i contesti paginati.

Lo stesso vale per le colonne. Se utilizzi il valore column , questo forzerebbe sempre un'interruzione prima o dopo quell'elemento, ma solo per contesti multicolonna. Il valore avoid-column impedirebbe un'interruzione nei contesti multicolonna.

C'è un valore always nella specifica di livello 4 che indica che vuoi sfondare tutto: pagina o colonna. Tuttavia, in quanto aggiunta recente alle specifiche, al momento non ci è utile.

Valori aggiuntivi per i media paginati

Se stai creando un libro o una rivista, hai le pagine sinistra e destra. Potresti voler controllare l'interruzione per forzare qualcosa sulla pagina sinistra o destra di uno spread. Pertanto, l'utilizzo di quanto segue inserirebbe interruzioni di una o due pagine prima di h2 per assicurarsi che fosse formattato come pagina corretta.

 h2 { break-before: right; }

Esistono anche valori recto e verso che si riferiscono alla progressione di pagina poiché i libri scritti in una lingua verticale o da destra a sinistra hanno una progressione di pagina diversa rispetto ai libri scritti in inglese. Non tratterò ulteriormente questi valori in questo articolo poiché sono principalmente interessato a ciò che è possibile dal browser questa volta.

break-inside

Abbiamo già visto un esempio della proprietà break-inside . Questa proprietà controlla l'interruzione all'interno di riquadri di blocco, ad esempio all'interno di un paragrafo, un'intestazione o un div.

Le cose che potresti non voler rompere possono includere un riquadro come descritto sopra: figure in cui non vuoi che la didascalia si stacchi dall'immagine, tabelle, elenchi e così via. Aggiungi break-inside: avoid qualsiasi contenitore che non desideri interrompere in alcun contesto di frammentazione. Se desideri solo evitare interruzioni tra le colonne, usa break-inside: avoid-column e tra le pagine break-inside: avoid-page .

Gli orphans e widows Proprietà

Le proprietà orphans e widows si occupano di quante righe devono essere lasciate prima o dopo un'interruzione (causata da una colonna o da una nuova pagina). Ad esempio, se voglio evitare che una singola riga venga lasciata alla fine di una colonna, userei la proprietà orphans , poiché in tipografia, un orphan è la prima riga di un paragrafo che appare da sola in fondo a una pagina con il resto del paragrafo spezzato su un'altra pagina. La proprietà deve essere aggiunta allo stesso elemento che sta frammentando (nel nostro caso, il contenitore multicol).

 .container { column-count: 3; orphans: 2; }

Per controllare quante righe devono essere presenti nella parte superiore di una colonna o di una pagina dopo un'interruzione, utilizzare widows :

 .container { column-count: 3; widows: 2; }

Queste proprietà gestiscono le interruzioni tra le caselle inline come le righe di parole all'interno di un paragrafo. Pertanto, non aiutano nella situazione in cui un'intestazione o un altro elemento di blocco è solo nella parte inferiore di una colonna o di una pagina, per questo sono necessarie le proprietà di interruzione discusse sopra.

Decorazione della scatola

Un'ultima proprietà che potrebbe interessare è la proprietà box-decoration-break . Questo controlla la situazione in cui hai una casella con un bordo interrotto tra due caselle o pagine di colonne. Vuoi che il bordo sia essenzialmente tagliato a metà? O vuoi che ciascuna delle due metà della scatola sia completamente avvolta in un bordo?

Il primo scenario è l'impostazione predefinita ed è come se si impostasse la proprietà box-decoration-break per slice la scatola.

 .box { box-decoration-break: slice; } 
Una scatola con un bordo spezzato tra le colonne
Un valore di fetta significa che il bordo è effettivamente tagliato a metà (anteprima grande)

Per ottenere il secondo comportamento, imposta box-decoration-break su clona.

 .box { box-decoration-break: clone; } 
Le scatole sono completamente avvolte in bordi
Un valore di clone significa che il bordo è avvolto completamente attorno a ciascun frammento della scatola (anteprima grande)

Supporto del browser per la frammentazione

Ora veniamo al motivo per cui non ho un sacco di esempi di CodePen sopra per dimostrarti tutto questo e il motivo principale per cui scrivo questo articolo. Il supporto del browser per queste proprietà non è eccezionale.

Se stai lavorando in Paged Media con uno specifico user agent come Prince, allora puoi godere di un ottimo supporto per la frammentazione e probabilmente troverai queste proprietà molto utili. Se stai lavorando con un browser web, in multicol, creando fogli di stile di stampa o utilizzando qualcosa come Chrome senza testa per generare PDF, il supporto è alquanto irregolare. Scoprirai che il browser con il miglior supporto è Edge, fino a quando non si sposta comunque su Chromium!

Posso usare non è particolarmente utile per spiegare il supporto a causa della combinazione delle proprietà di frammentazione con multicol, quindi della disponibilità di alcuni dati separati per le proprietà legacy. Quindi, come parte del lavoro che ho svolto per MDN per documentare le proprietà e il loro supporto, ho iniziato a testare l'effettivo supporto del browser. Quello che segue è un consiglio basato su quel test.

Proprietà con prefisso legacy e fornitore

Non posso andare molto oltre senza una lezione di storia. Se trovi che hai davvero bisogno di supporto per la frammentazione, potresti trovare qualche sollievo nelle proprietà legacy che originariamente facevano parte di CSS2 (o in alcune proprietà prefissate che esistono).

In CSS2 c'erano proprietà per controllare l'interruzione di pagina. Multicol non esisteva a quel punto, quindi l'unico contesto frammentato era quello paginato. Ciò significava che sono state introdotte tre proprietà di interruzione di pagina specifiche:

  • page-break-before
  • page-break-after
  • page-break-inside

Funzionano in modo simile alle proprietà più generiche senza il prefisso di page- , controllando le interruzioni prima, dopo e all'interno delle caselle. Per i fogli di stile di stampa, scoprirai che alcuni browser meno recenti che non supportano le nuove proprietà di break- supportano queste proprietà con prefisso di pagina. Le proprietà vengono trattate come alias per le nuove proprietà.

In una bozza di lavoro del 2005 della specifica multicol sono i dettagli delle proprietà di interruzione per multicol, utilizzando le proprietà con il prefisso column- (cioè column-break-before , column-break-after e column-break-inside ). Nel 2009, questi erano scomparsi e nella specifica multicol c'era una bozza per le proprietà di interruzione senza prefisso che alla fine si sono fatte strada nella specifica di frammentazione CSS.

Tuttavia, alcune proprietà specifiche della colonna con prefisso del fornitore sono state implementate in base a queste proprietà. Questi sono:

  • -webkit-column-break-before
  • -webkit-column-break-after
  • -webkit-column-break-inside

Supporto per la frammentazione in Multicol

Quanto segue si basa sul test di queste funzionalità in contesti multicolonna. Ho provato a spiegare cosa è possibile, ma dai un'occhiata a CodePens in qualsiasi browser tu abbia a disposizione.

Multicolor e break-inside

Il supporto in multicol è il migliore per la proprietà break-inside . Le versioni aggiornate di Chrome, Firefox, Edge e Safari supportano tutte il break-inside: avoid . Quindi dovresti scoprire che puoi impedire che le caselle si interrompano tra le colonne quando usi multicol.

Diversi browser, ad eccezione di Firefox, supportano la -webkit-column-break-inside , che può essere utilizzata con un valore di avoid e può impedire che le caselle si interrompano tra le colonne che non supportano break-inside .

Firefox supporta page-break-inside: avoid in multicol. Pertanto, l'utilizzo di questa proprietà eviterà interruzioni all'interno delle caselle nei browser Firefox precedenti a Firefox 65.

Ciò significa che se vuoi evitare interruzioni tra le caselle in multicol, l'utilizzo del seguente CSS coprirà il maggior numero possibile di browser, tornando il più indietro possibile.

 .box { -webkit-column-break-inside: avoid; page-break-inside: avoid; break-inside: avoid; }

Per quanto riguarda il valore della column , affermando esplicitamente che si desidera evitare solo interruzioni tra le colonne e non le pagine, funziona in tutti i browser tranne Firefox.

Il CodePen di seguito arrotonda alcuni di questi test in multicol in modo che tu possa provarli tu stesso.

Guarda il Pen Multicol Fragmentation Test: break-inside di Rachel Andrew.

Guarda il Pen Multicol Fragmentation Test: break-inside di Rachel Andrew.

Multicol E break-before

Per prevenire interruzioni prima di un elemento, dovresti essere in grado di utilizzare break-before: avoid o break-before: avoid-column . La proprietà evita non ha il supporto del browser.

Edge supporta break-before: column per forzare sempre un'interruzione prima del riquadro dell'elemento.

Safari, Chrome ed Edge supportano anche -webkit-column-break-before: always che forzerà un'interruzione prima della casella dell'elemento. Pertanto, se vuoi forzare un'interruzione prima del riquadro di un elemento, dovresti usare:

 .box { -webkit-column-break-before: always; break-before: column; }

Prevenire una pausa prima della scatola è attualmente un compito impossibile. Puoi giocare con alcuni esempi di queste proprietà di seguito:

Vedi Pen Multicol Fragmentation Test: break-before di Rachel Andrew).

Vedi Pen Multicol Fragmentation Test: break-before di Rachel Andrew).

Multicol E break-after

Per evitare interruzioni dopo un elemento, per evitare che diventi l'ultima cosa in fondo a una colonna, dovresti essere in grado di usare break-after: avoid e break-after: avoid-column . L'unico browser con supporto per questi è Edge.

Edge supporta anche la forzatura delle interruzioni dopo un elemento utilizzando break-after: column , Chrome supporta break-after: column e anche -webkit-column-break-after: always .

Firefox non supporta break-after o alcuna delle proprietà prefissate per forzare o consentire interruzioni dopo una casella.

Pertanto, a parte Edge, non puoi davvero evitare le interruzioni dopo una scatola. Se vuoi forzarli, otterrai risultati in alcuni browser utilizzando il seguente CSS:

 .box { -webkit-break-after: always; break-after: column; } 

Vedi il Pen Multicol Fragmentation Test: break-after di Rachel Andrew).

Vedi il Pen Multicol Fragmentation Test: break-after di Rachel Andrew).

Supporto durante la stampa dal browser

Se stampi direttamente dal tuo browser desktop o generi file PDF utilizzando Chrome senza testa o qualche altra soluzione basata sulla tecnologia del browser non fa alcuna differenza. Fai affidamento sul supporto del browser per le proprietà di frammentazione.

Se crei un foglio di stile di stampa, troverai un supporto simile per le proprietà di interruzione come per multicol; tuttavia, per supportare i browser meno recenti è necessario raddoppiare le proprietà per utilizzare le proprietà con prefisso di page- .

Stampa fogli di stile e break-inside

Nei browser moderni, la proprietà break-inside può essere utilizzata per prevenire interruzioni all'interno delle caselle, aggiungere la proprietà page-break-inside per aggiungere il supporto per i browser meno recenti.

 .box { page-break-inside: avoid; break-inside: avoid; }

Stampa fogli di stile e break-before

Per forzare le interruzioni prima di una casella, utilizzare break-before:page insieme a page-break-before: always .

 .box { page-break-before: always; break-before: page; }

Per evitare interruzioni prima di una casella, utilizzare break-before: avoid-page insieme a page-break-before: avoid .

 .box { page-break-before: avoid; break-before: avoid-page; }

C'è un supporto migliore per i valori di page ed avoid-page rispetto a quello che vediamo per i valori multicol equivalenti. La maggior parte dei browser moderni ha il supporto.

Stampa fogli di stile e break-before

Per forzare le interruzioni dopo una casella, utilizzare break-after: page insieme a page-break-after: always .

 .box { page-break-after: always; break-after: page; }

Per evitare interruzioni dopo una casella, utilizzare break-after: avoid-page insieme a page-break-after: avoid .

 .box { page-break-after: avoid; break-after: avoid-page; }

Vedove e orfani

Le proprietà widows e orphans godono di un buon supporto cross-browser: l'unico browser senza un'implementazione è Firefox. Suggerirei di usarli quando crei un layout multicolo o un foglio di stile di stampa. Se non funzionano per qualche motivo, otterrai vedove e orfani, il che non è l'ideale ma non è nemmeno un disastro. Se funzionano, la tua tipografia avrà un aspetto migliore.

scatola-decorazione-pausa

La proprietà finale di box-decoration-break ha il supporto per multicol e print in Firefox. Safari, Chrome e altri browser basati su Chromium supportano -webkit-box-decoration-break , ma solo su elementi inline. Quindi puoi clonare i bordi attorno alle righe di una frase, ad esempio; non hanno supporto nel contesto che stiamo guardando.

Nella CodePen di seguito, puoi vedere che il test per -webkit-box-decoration-break: clone with Feature Query restituisce true; tuttavia la proprietà non ha effetto sul bordo del box nel contesto multicol.

Guarda Pen Multicol: scatola-decorazione-pausa di Rachel Andrew.

Guarda Pen Multicol: scatola-decorazione-pausa di Rachel Andrew.

Usando la frammentazione

Come puoi vedere, l'attuale stato di frammentazione nei browser è alquanto frammentato! Detto questo, c'è una quantità ragionevole che puoi ottenere e dove fallisce, il risultato tende a essere non ottimale ma non un disastro. Il che significa che vale la pena provare.

Vale la pena notare che essere troppo gravosi con queste proprietà potrebbe comportare qualcosa di diverso da quello che speravi. Se stai lavorando sul Web invece di stampare e forzare le interruzioni di colonna dopo ogni paragrafo, quindi finisci con più paragrafi che spazio per le colonne, multicol finirà per traboccare nella direzione inline. Esaurirà le colonne per posizionare i tuoi paragrafi aggiuntivi. Pertanto, anche dove c'è supporto, è comunque necessario testare attentamente e ricordare che in molti casi meno è di più.

Più risorse

Per saperne di più sulle proprietà, vai su MDN, ho recentemente aggiornato le pagine lì e sto anche cercando di mantenere aggiornati i dati di compatibilità del browser. La pagina principale per la frammentazione CSS si collega alle singole pagine delle proprietà che contengono ulteriori esempi, dati di compatibilità del browser e altre informazioni sull'utilizzo di queste proprietà.