Quebrando caixas com fragmentação CSS
Publicados: 2022-03-10Neste artigo, apresentarei a especificação de fragmentação de CSS. Você pode nunca ter ouvido falar disso, no entanto, se você já criou uma folha de estilo de impressão e deseja controlar onde o conteúdo se divide entre as páginas ou o layout de várias colunas e deseja interromper uma quebra de figura entre as colunas, você o encontrou.
Acho que muitas vezes os problemas que as pessoas relatam com o multicol são realmente problemas com o suporte à fragmentação do navegador. Após um rápido resumo das propriedades contidas nesta especificação, explicarei o estado atual do suporte ao navegador e algumas das coisas que você pode fazer para que funcione tão bem quanto possível em seus projetos multicol e de impressão.
O que é fragmentação?
A fragmentação em CSS descreve o processo pelo qual o conteúdo é dividido em diferentes caixas. Atualmente, temos dois lugares em que podemos nos deparar com fragmentação na web: quando imprimimos um documento e se usamos o layout de várias colunas. Essas duas coisas são essencialmente as mesmas. Quando você imprime (ou salva em PDF) uma página da Web, o conteúdo é fragmentado em quantas páginas forem necessárias para imprimir seu conteúdo.
Quando você usa multicol, o conteúdo é fragmentado em colunas. Cada caixa de coluna é como uma página no contexto paginado. Se você pensar em um conjunto de colunas como sendo muito parecido com um conjunto de páginas, pode ser uma maneira útil de pensar sobre multicol e como a fragmentação funciona nele.
Se você der uma olhada na Especificação de Fragmentação CSS, verá um terceiro contexto fragmentado mencionado — esse contexto é Regiões. Como não há implementações usáveis atuais de Regiões, não vamos lidar com isso neste artigo, mas sim analisar os dois contextos que você pode encontrar em seu trabalho.
Caixas de bloco e em linha
Vou mencionar muito as caixas de bloco neste artigo. Cada elemento da sua página tem uma caixa. Algumas dessas caixas são dispostas como blocos: parágrafos, itens de lista, títulos. Diz-se que eles estão participando de um contexto de formatação de bloco. Outros são embutidos, como as palavras em um parágrafo, extensões e elementos âncora. Eles participam de um contexto de formatação embutido. Simplificando, quando me refiro a uma caixa de bloco, estou falando de caixas em torno de coisas como parágrafos. Ao lidar com a fragmentação, é importante saber com qual tipo de caixa você está lidando.
Para obter mais informações sobre layout de bloco e inline, consulte o artigo do MDN “Block And Inline Layout In Normal Flow”. É uma daquelas coisas que provavelmente todos nós entendemos em algum nível, mas talvez não tenhamos encontrado a terminologia de antes.
Controlando quebras
Esteja você criando uma folha de estilo de impressão, usando um agente de usuário de impressão específico para fazer um PDF ou usando multicol, às vezes você terá problemas que se parecem com isso.
No exemplo multicol abaixo, tenho algum conteúdo que estou exibindo como três colunas. No meio do conteúdo há uma área em caixa, que está sendo dividida em duas colunas. Eu não quero esse comportamento - eu gostaria que a caixa ficasse junta.

Para corrigir isso, adiciono a propriedade break-inside: avoid
à caixa. A propriedade break-inside
controla quebras dentro de elementos quando eles estão em um contexto fragmentado. Em um navegador que suporte esta propriedade, a caixa ficará agora em uma das colunas. As colunas parecerão menos equilibradas, no entanto, isso geralmente é uma coisa melhor do que acabar com o boxout dividido entre as colunas.
Veja o exemplo Pen Simple break-inside por (Rachel Andrew.
A propriedade break-inside
é uma das propriedades detalhadas na especificação de fragmentação. A lista completa de imóveis é a seguinte:
-
break-before
-
break-after
-
break-inside
-
orphans
-
widows
-
box-decoration-break
Vamos dar uma olhada em como eles devem funcionar antes de passarmos para o que realmente acontece nos navegadores.
As propriedades break-before
e break-after
Existem duas propriedades que controlam as quebras entre as caixas de nível de bloco: break-before
e break-after
. Se você tem um h2
seguido de dois parágrafos <p>
você tem três caixas de bloco e você usaria essas propriedades para controlar as quebras entre o título e o primeiro parágrafo, ou entre os dois parágrafos.
As propriedades são usadas em seletores que visam o elemento que você deseja quebrar antes ou depois.
Por exemplo, você pode querer que sua folha de estilo de impressão seja dividida em uma nova página toda vez que houver um título de nível 2. Nesse caso, você usaria break-before: page
no elemento h2
. Isso controla a fragmentação e garante que sempre haja uma pausa antes da caixa do elemento h2
.
h2 { break-before: page; }
Outro requisito comum é evitar que os títulos terminem como a última coisa em uma página ou coluna. Nesse caso, você pode usar break-after
com um valor de avoid
. Isso deve evitar uma quebra logo após a caixa do elemento:
h1, h2, h3, h4 { break-after: avoid; }
Fragmentos dentro de fragmentos
É possível que você tenha um elemento fragmentado aninhado dentro de outro. Por exemplo, ter um multicol dentro de algo que é paginado. Nesse caso, você pode querer controlar quebras para páginas, mas não para colunas, ou vice-versa. É por isso que temos valores como page
que sempre forçariam uma quebra antes ou depois do elemento, mas apenas quando o fragmento for uma página. Ou avoid-page
que evitaria uma quebra antes ou depois do elemento apenas para contextos paginados.
O mesmo se aplica às colunas. Se você usar o valor column
, isso sempre forçaria uma quebra antes ou depois desse elemento, mas apenas para contextos multicol. O valor avoid-column
evitaria uma quebra em contextos multicol.
Há um valor always
na especificação do Nível 4 que indica que você deseja romper tudo — página ou coluna. No entanto, como uma adição recente à especificação, atualmente não é útil para nós.
Valores adicionais para mídia paginada
Se você estiver criando um livro ou revista, terá as páginas esquerda e direita. Você pode querer controlar a quebra para forçar algo na página esquerda ou direita de uma página espelhada. Portanto, usar o seguinte inseriria quebras de uma ou duas páginas antes do h2
para garantir que ele fosse formatado como uma página correta.
h2 { break-before: right; }
Há também valores de frente e verso que se relacionam à progressão de página, pois livros escritos em um idioma vertical ou da direita para a esquerda têm uma progressão de página diferente dos livros escritos em inglês. Não vou abordar esses valores mais neste artigo, pois estou preocupado principalmente com o que é possível no navegador desta vez.
break-inside
Já vimos um exemplo da propriedade de break-inside
. Esta propriedade controla a quebra de caixas de bloco, por exemplo, dentro de um parágrafo, título ou div.
Coisas que você pode não querer quebrar podem incluir um boxout como descrito acima: figuras onde você não quer que a legenda seja destacada da imagem, tabelas, listas e assim por diante. Adicione break-inside: avoid
qualquer container que você não queira quebrar em nenhum contexto de fragmentação. Se você deseja apenas evitar quebras entre colunas, use break-inside: avoid-column
e entre páginas break-inside: avoid-page
.
As propriedades dos orphans
e widows
As propriedades orphans
e widows
lidam com quantas linhas devem ser deixadas antes ou depois de uma quebra (causada por uma coluna ou uma nova página). Por exemplo, se eu quiser evitar que uma única linha seja deixada no final de uma coluna, eu usaria a propriedade orphans
, como na tipografia, um órfão é a primeira linha de um parágrafo que aparece sozinha na parte inferior de uma página com o resto do parágrafo dividido em outra página. A propriedade deve ser adicionada ao mesmo elemento que está fragmentando (no nosso caso, o container multicol).
.container { column-count: 3; orphans: 2; }
Para controlar quantas linhas devem estar na parte superior de uma coluna ou página após uma pausa, use widows
:
.container { column-count: 3; widows: 2; }
Essas propriedades lidam com quebras entre caixas embutidas, como as linhas de palavras dentro de um parágrafo. Portanto, eles não ajudam na situação em que um título ou outro elemento de bloco está sozinho na parte inferior de uma coluna ou página, você precisa das propriedades de quebra discutidas acima para isso.
Decoração da caixa
Uma propriedade final que pode ser interessante é a propriedade box-decoration-break
. Isso controla a situação em que você tem uma caixa com uma borda quebrada entre duas caixas de colunas ou páginas. Você quer que a borda seja essencialmente cortada ao meio? Ou você quer que cada uma das duas metades da caixa seja totalmente embrulhada em uma borda?
O primeiro cenário é o padrão e é como se você definisse a propriedade box-decoration-break
para slice
a caixa.
.box { box-decoration-break: slice; }

Para obter o segundo comportamento, defina box-decoration-break
para clonar.
.box { box-decoration-break: clone; }

Suporte do navegador para fragmentação
Agora chegamos ao motivo pelo qual não tenho um monte de exemplos do CodePen acima para demonstrar tudo isso para você, e o principal motivo para eu escrever este artigo. O suporte do navegador para essas propriedades não é ótimo.

Se você estiver trabalhando em mídia paginada com um agente de usuário específico, como Prince, poderá desfrutar de um suporte muito bom para fragmentação e provavelmente achará essas propriedades muito úteis. Se você estiver trabalhando com um navegador da Web, seja em multicol, criando folhas de estilo de impressão ou usando algo como o Headless Chrome para gerar PDFs, o suporte é um pouco irregular. Você descobrirá que o navegador com o melhor suporte é o Edge - até que ele mude para o Chromium de qualquer maneira!
Can I Use não é muito útil para explicar o suporte devido à mistura das propriedades de fragmentação com multicol e, em seguida, ter alguns dados separados para propriedades herdadas. Então, como parte do trabalho que tenho feito para o MDN documentar as propriedades e seu suporte, comecei a testar o suporte real do navegador. O que se segue são alguns conselhos com base nesse teste.
Propriedades Prefixadas Legadas e de Fornecedor
Não posso ir muito mais longe sem uma aula de história. Se você achar que realmente precisa de suporte para fragmentação, poderá encontrar algum alívio nas propriedades herdadas que originalmente faziam parte do CSS2 (ou em algumas propriedades prefixadas que existem).
No CSS2, havia propriedades para controlar a quebra de página. O Multicol não existia naquele momento, então o único contexto fragmentado era o paginado. Isso significou que três propriedades específicas de quebra de página foram introduzidas:
-
page-break-before
-
page-break-after
-
page-break-inside
Eles funcionam de maneira semelhante às propriedades mais genéricas sem o prefixo de page-
, controlando quebras antes, depois e dentro de caixas. Para folhas de estilo de impressão, você descobrirá que alguns navegadores mais antigos que não suportam as novas propriedades break-
, suportam essas propriedades prefixadas de página. As propriedades estão sendo tratadas como aliases para as novas propriedades.
Em um rascunho de trabalho de 2005 da especificação multicol, há detalhes das propriedades de quebra para multicol — usando propriedades prefixadas com column-
(ou seja column-break-before
, column-break-after
e column-break-inside
). Em 2009, eles foram embora, e um rascunho estava na especificação multicol para propriedades de quebra não prefixadas que eventualmente chegaram à especificação CSS Fragmentation.
No entanto, algumas propriedades específicas de coluna prefixadas do fornecedor foram implementadas com base nessas propriedades. Estes são:
-
-webkit-column-break-before
-
-webkit-column-break-after
-
-webkit-column-break-inside
Suporte para Fragmentação em Multicol
O seguinte é baseado no teste desses recursos em contextos multicol. Eu tentei explicar o que é possível, mas dê uma olhada no CodePens em qualquer navegador que você tenha disponível.
Multicol E break-inside
O suporte em multicol é melhor para a propriedade break-inside
. Todas as versões atualizadas do Chrome, Firefox, Edge e Safari suportam break-inside: avoid
. Portanto, você deve descobrir que pode impedir que as caixas se quebrem entre as colunas ao usar multicol.
Vários navegadores, com exceção do Firefox, suportam a -webkit-column-break-inside
, isso pode ser usado com um valor de avoid
e pode impedir a quebra de caixas entre colunas que não têm suporte para break-inside
.
Firefox suporta page-break-inside: avoid
em multicol. Portanto, o uso dessa propriedade evitará quebras dentro de caixas nos navegadores Firefox anteriores ao Firefox 65.
Isso significa que, se você quiser evitar quebras entre caixas em multicol, usar o CSS a seguir cobrirá o maior número possível de navegadores, voltando o máximo possível.
.box { -webkit-column-break-inside: avoid; page-break-inside: avoid; break-inside: avoid; }
Quanto ao valor da column
, declarar explicitamente que você deseja evitar apenas quebras entre colunas, e não páginas, funciona em todos os navegadores, exceto no Firefox.
O CodePen abaixo resume alguns desses testes em multicol para que você possa experimentá-los por si mesmo.
Veja o Teste de Fragmentação Pen Multicol: break-inside por Rachel Andrew.
Multicol E break-before
Para evitar quebras antes de um elemento, você deve poder usar break-before: avoid
ou break-before: avoid-column
. A propriedade avoid não tem suporte ao navegador.
O Edge suporta break-before: column
para sempre forçar uma quebra antes da caixa do elemento.
Safari, Chrome e Edge também suportam -webkit-column-break-before: always
que forçará uma pausa antes da caixa do elemento. Portanto, se você deseja forçar uma quebra antes da caixa de um elemento, você deve usar:
.box { -webkit-column-break-before: always; break-before: column; }
Prevenir uma pausa antes da caixa é atualmente uma tarefa impossível. Você pode brincar com alguns exemplos dessas propriedades abaixo:
Veja o Teste de Fragmentação Pen Multicol: break-before por Rachel Andrew).
Multicol E break-after
Para evitar quebras após um elemento, para evitar que ele se torne a última coisa na parte inferior de uma coluna, você deve poder usar break-after: avoid
e break-after: avoid-column
. O único navegador com suporte para isso é o Edge.
O Edge também suporta quebras forçadas após um elemento usando break-after: column
, o Chrome suporta break-after: column
e também -webkit-column-break-after: always
.
O Firefox não suporta break-after
ou qualquer uma das propriedades prefixadas para forçar ou permitir quebras após uma caixa.
Portanto, além do Edge, você não pode realmente evitar quebras após uma caixa. Se você quiser forçá-los, obterá resultados em alguns navegadores usando o seguinte CSS:
.box { -webkit-break-after: always; break-after: column; }
Veja o Teste de Fragmentação Pen Multicol: break-after por Rachel Andrew).
Suporte ao imprimir a partir do navegador
Não importa se você imprime diretamente do navegador da área de trabalho ou gera arquivos PDF usando o Chrome sem cabeça ou alguma outra solução que dependa da tecnologia do navegador. Você depende do suporte do navegador para as propriedades de fragmentação.
Se você criar uma folha de estilo de impressão, encontrará suporte semelhante para as propriedades de quebra como para multicol; entretanto, para oferecer suporte a navegadores mais antigos, você deve duplicar as propriedades para usar as propriedades com prefixo de page-
.
Imprimir folhas de estilo e break-inside
Em navegadores modernos, a propriedade break-inside
pode ser usada para evitar quebras dentro de caixas, adicione a propriedade page-break-inside
para adicionar suporte para navegadores mais antigos.
.box { page-break-inside: avoid; break-inside: avoid; }
Imprimir folhas de estilo e break-before
Para forçar quebras antes de uma caixa, use break-before:page
junto com page-break-before: always
.
.box { page-break-before: always; break-before: page; }
Para evitar quebras antes de uma caixa, use break-before: avoid-page
junto com page-break-before: avoid
.
.box { page-break-before: avoid; break-before: avoid-page; }
Há melhor suporte para os valores page
e avoid-page
do que vemos para os valores multicol equivalentes. A maioria dos navegadores modernos tem suporte.
Imprimir folhas de estilo e break-before
Para forçar quebras após uma caixa, use break-after: page
junto com page-break-after: always
.
.box { page-break-after: always; break-after: page; }
Para evitar quebras após uma caixa, use break-after: avoid-page
junto com page-break-after: avoid
.
.box { page-break-after: avoid; break-after: avoid-page; }
Viúvas e órfãos
As propriedades de widows
e orphans
desfrutam de um bom suporte entre navegadores - o único navegador sem implementação é o Firefox. Eu sugeriria usá-los ao criar um layout multicol ou uma folha de estilo de impressão. Se eles não funcionarem por algum motivo, você terá viúvas e órfãos, o que não é o ideal, mas também não é um desastre. Se funcionarem, sua tipografia ficará ainda melhor.
caixa-decoração-quebra
A propriedade final de box-decoration-break
tem suporte para multicol e print no Firefox. Safari, Chrome e outros navegadores baseados em Chromium suportam -webkit-box-decoration-break
, mas apenas em elementos inline. Assim, você pode clonar bordas em volta de linhas de uma frase, por exemplo; eles não têm suporte no contexto que estamos olhando.
No CodePen abaixo, você pode ver que testar para -webkit-box-decoration-break: clone
with Feature Queries retorna true; no entanto, a propriedade não tem efeito na borda da caixa no contexto multicol.
Veja a Pen Multicol: box-decoration-break de Rachel Andrew.
Como usar a fragmentação
Como você pode ver, o estado atual de fragmentação nos navegadores é um pouco fragmentado! Dito isto, há uma quantidade razoável que você pode alcançar e onde ela falha, o resultado tende a ser abaixo do ideal, mas não um desastre. O que significa que vale a pena tentar.
Vale a pena notar que ser muito pesado com essas propriedades pode resultar em algo diferente do que você esperava. Se você estiver trabalhando na web em vez de imprimir e forçar quebras de coluna após cada parágrafo, e acabar com mais parágrafos do que espaço para colunas, multicol acabará transbordando na direção inline. Ele ficará sem colunas para colocar seus parágrafos adicionais. Portanto, mesmo onde há suporte, você ainda precisa testar com cuidado e lembre-se de que menos é mais em muitos casos.
Mais recursos
Para ler mais sobre as propriedades, vá para o MDN, atualizei recentemente as páginas lá e também estou tentando manter os dados de compatibilidade do navegador atualizados. A página principal para Fragmentação de CSS tem links para as páginas de propriedades individuais que têm mais exemplos, dados de compatibilidade do navegador e outras informações sobre o uso dessas propriedades.