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 para mídia paginada, o Módulo de mídia paginada CSS e o Conteúdo gerado pelo CSS para mídia paginada. Eles definem recursos que são usados apenas quando uma página é impressa (inclusive para 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 foi bem suportada em navegadores da Web, apesar de muitas vezes precisarmos imprimir ou criar PDFs a partir de aplicativos.

O Chrome e o Firefox são compatíveis com a @page at-rule. Essa regra permite definir o tamanho da página em que a impressão será feita 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 é sua 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 laterais esquerda e direita é definida 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.

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

Adicionar conteúdo às caixas de margem

Para adicionar conteúdo a caixas de margem, use conteúdo gerado por CSS, da mesma forma que você faria com 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 da 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 no canto inferior direito das páginas à direita e no 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 fixado no código no CSS, já que ele muda conforme você percorre o 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 usa o conteúdo de cada <h1> na margem superior direita nas páginas à direita. Quando chega ao próximo <h1>, o valor é atualizado para margens após esse 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é.