Adicionar conteúdo às margens das páginas da Web quando impresso usando CSS

Publicado em 30 de outubro de 2024

No Chrome 131, é possível usar CSS para adicionar conteúdo às margens das páginas quando elas são impressas. Esta postagem explica o modelo de página para mídia paginada e como usar esse recurso para melhorar a saída de impressão das suas páginas da Web.

O CSS inclui especificações que lidam com mídia paginada, o módulo de mídia paginada do CSS e o conteúdo gerado por CSS para mídia paginada. Eles definem recursos que são usados apenas quando uma página é impressa (incluindo em PDF). Existem user agents que oferecem suporte a esse CSS e permitem gerar livros e outros materiais impressos de HTML e CSS. No entanto, essa funcionalidade nunca teve suporte adequado em navegadores da Web, apesar de muitas vezes precisarmos imprimir ou criar PDFs em aplicativos.

O Chrome e o Firefox oferecem suporte à a regra @page. Essa regra permite definir o tamanho da página em que você está imprimindo e o tamanho das margens ao redor do conteúdo. No Chrome 131, também é possível usar conteúdo gerado para adicionar conteúdo às margens, segmentando a margem at-rule relevante.

O modelo da página

O modelo de página usado em mídia paginada define uma caixa de página, que é a folha de papel. Dentro da caixa da página, há uma margem, uma borda, um padding e, por fim, a área da página em que o conteúdo é exibido. Quando o conteúdo é impresso, ele é fragmentado em quantas páginas forem necessárias para contê-lo.

A margem da página é dividida em 16 caixas, cada uma com uma regra at correspondente.

  • @top-left-corner
  • @top-left
  • @top-center
  • @top-right
  • @top-right-corner
  • @left-top
  • @left-middle
  • @left-bottom
  • @right-top
  • @right-middle
  • @right-bottom
  • @bottom-left-corner
  • @bottom-left
  • @bottom-center
  • @bottom-right
  • @bottom-right-corner

Dimensionamento da caixa de margem

A altura das caixas de cima e de baixo e a largura das caixas do lado esquerdo e direito são definidas pelo tamanho da margem definido usando @page. Portanto, as caixas de canto têm um tamanho fixo criado pela interseção dessas margens. No entanto, as três caixas entre cada canto são flexíveis. Elas se comportam de maneira semelhante a caixas em um layout flexível usando flex: auto, então elas se estendem para preencher o espaço, mas se você colocar uma string longa de texto em uma e nada nas outras, a que tiver o texto vai crescer em vez de concatenar o texto.

Página com 16 caixas exibidas na margem.
A área da página é cercada pela margem, contendo 16 caixas de margem nomeadas.

Adicionar conteúdo às caixas de margem

Para adicionar conteúdo às caixas de margem, use o conteúdo gerado por CSS, assim como os pseudoelementos ::before e ::after. Nesse caso, use a at-rule relacionada à caixa que você quer segmentar. O CSS a seguir adiciona o texto "Meu livro" à caixa de margem inferior esquerda ou às páginas à direita. Ele também define o estilo desse texto.

@page :right {
  @bottom-left {  
    content: "My book";  
    font-size: 9pt;  
    color: #333; 
  }
}

Além de strings de texto, você pode adicionar contadores de páginas às margens. O contador page predefinido contém a página atual. O CSS a seguir adiciona o ícone ao canto inferior direito das páginas à direita e ao canto inferior esquerdo das páginas à esquerda.

@page :right {  
  @bottom-right {  
    content: counter(page);  
  }
}

@page :left {
  @bottom-left {
    content: counter(page);
  }
}

Há também um contador pages que sempre contém o número total de páginas.

Observações ao usar margens de página

Se você estiver imprimindo de um navegador, ele vai adicionar automaticamente algum conteúdo de margem de página se houver espaço para exibição. Isso vai acontecer mesmo se você tiver adicionado conteúdo. Esses cabeçalhos e rodapés gerados automaticamente podem ser desativados na caixa de diálogo de impressão.

Se você definir as margens de uma página como 0 ou um valor tão pequeno que não haja espaço para os cabeçalhos e rodapés do navegador, eles não serão exibidos.

Devido ao conceito de layout de página padrão no Chromium, se a primeira página do documento impresso não tiver espaço para o conteúdo automático, isso impedirá que o conteúdo do navegador seja exibido nas páginas seguintes, mesmo que elas tenham espaço.

Possibilidades futuras para mídia paginada

As especificações de mídia paginada incluem vários outros recursos, descritos no artigo Design para impressão com CSS. Se você tiver um caso de uso para algum dos recursos abaixo, adicione-o aos bugs vinculados.

Strings de configuração

Os livros geralmente imprimem o título do capítulo atual nas margens. Esse título não pode ser codificado no CSS, porque ele muda conforme você avança no livro. A propriedade string-set permite definir um valor do HTML para usar no conteúdo gerado. O CSS a seguir pressupõe que os títulos dos capítulos sejam marcados como <h1>. Ele pega o conteúdo de cada <h1> e o usa na margem superior direita nas páginas da direita. Quando ele chega ao próximo <h1>, o valor é atualizado para margens depois desse ponto.

h1 {
  string-set: doctitle content();
}

@page :right {
  @top-right {
    content: string(doctitle);
    margin: 30pt 0 10pt 0;
    font-size: 8pt;
  }
}

Bug do Chromium para string-set e string().

Referências cruzadas

Depois que um documento é impresso, as referências a outras páginas geralmente são indicadas usando o número da página em que a referência pode ser encontrada. Essas referências cruzadas podem ser criadas usando target-counter. Quando aplicado a um link, o link funciona para ir para a referência na Web. Quando impresso, o número da página é mostrado.

<a class="xref" href="#ref1">my reference</a>
a.xref:after {
  content: " (page " target-counter(attr(href, url), page) ")";
}

Bug do Chromium para referências cruzadas.

Notas de rodapé

As notas de rodapé também são um recurso das especificações de mídia paginada. No HTML, use uma classe para identificar o texto que deve ser uma nota de rodapé, por exemplo:

<p>This is some text <span class=”fn”>this is a footnote</span>.</p>

Em seguida, use o valor footnote de float para transformar esse texto em notas de rodapé. Ela será removida do parágrafo quando o documento for impresso e exibido como uma nota de rodapé.

.fn {
  float: footnote;
}

Bug do Chromium para notas de rodapé.