content-visibilidade: a nova propriedade de CSS que melhora o desempenho de renderização

Melhore o tempo de carregamento inicial ignorando a renderização de conteúdo fora da tela.

O content-visibility lançada no Chromium 85, pode ser um dos novos CSS mais impactantes para melhorar o desempenho do carregamento de página. content-visibility ativa os o user agent de pular o trabalho de renderização de um elemento, incluindo o layout e a pintura, até que sejam necessários. Como a renderização é ignorada, se uma grande parte do conteúdo estiver fora da tela, a propriedade content-visibility vai acelerar muito a carga inicial do usuário. Isso também permite interações mais rápidas com o conteúdo na tela. Muito legal.

demonstração com figuras que representam resultados da rede
Na demonstração do nosso artigo, aplicar content-visibility: auto a áreas de conteúdo divididas proporciona um aumento de 7x no desempenho de renderização no carregamento inicial. Continue lendo para saber mais.

Suporte ao navegador

Compatibilidade com navegadores

  • Chrome: 85
  • Borda: 85.
  • Firefox: 125.
  • Safari: 18.

Origem

content-visibility depende de primitivos dentro da contenção CSS Especificação. Enquanto content-visibility é de suportado no Chromium 85 por enquanto (e considerado "vale a pena prototipagem" para Firefox), a especificação de contenção tem suporte na maioria navegadores.

Contenção de CSS

O principal objetivo da contenção do CSS é permitir a renderização de melhoria no desempenho do conteúdo da web ao fornecer isolamento previsível de uma subárvore do DOM do resto da página.

Basicamente, um desenvolvedor pode informar ao navegador quais partes da página estão encapsuladas como um conjunto de conteúdo, permitindo que os navegadores analisem o conteúdo sem precisar considerar o estado fora da subárvore. Saber quais partes do conteúdo (subárvores) contêm conteúdo isolado, significa que o navegador pode fazer otimização para a renderização da página.

Há quatro tipos de contenção de CSS, cada um um valor potencial para a propriedade CSS contain, que pode ser combinada em uma lista de valores separados por espaços:

  • size: o tamanho da contenção em um elemento garante que a caixa dele possa ser dispostos sem precisar examinar os descendentes. Isso significa que podemos pode pular o layout dos descendentes se tudo que precisamos for o tamanho do .
  • layout: contenção de layout significa que os descendentes não afetam o o layout externo de outras caixas na página. Isso nos permite pular dos descendentes se quisermos apenas posicionar outras caixas.
  • style: a contenção de estilo garante que as propriedades que podem ter efeitos mais do que apenas seus descendentes não escapar do elemento (por exemplo, contadores). Isso nos permite pular o cálculo de estilo para os descendentes se todos quer é calcular estilos em outros elementos.
  • paint: a contenção de pintura garante que os descendentes da caixa que a contém não são exibidos fora dos limites. Nada pode visivelmente estourar o elemento, e, se um elemento estiver fora da tela ou não estiver visível, seus descendentes ficam visíveis. Isso nos permite pular a pintura da descendentes se o elemento estiver fora da tela.

Pulando o trabalho de renderização com content-visibility

Pode ser difícil descobrir quais valores de contenção usar, pois o navegador só poderão ser iniciadas quando um conjunto apropriado for especificado. Você pode testar os valores para ver o que funciona melhor ou você pode usar outra propriedade CSS chamada content-visibility para aplicar o a contenção automaticamente. O content-visibility garante que você receba os maiores ganhos de desempenho que o navegador pode oferecer com o mínimo de esforço do desenvolvedor.

A propriedade de visibilidade do conteúdo aceita vários valores, mas é auto. que oferece melhorias imediatas de desempenho. Um elemento que tem content-visibility: auto ganha contenção layout, style e paint. Se o elemento está fora da tela (e não é relevante para o usuário, ou seja, elementos sejam os que têm foco ou seleção em sua subárvore), isso também ganha size contenção (e para pintura e teste de hit o conteúdo dele).

O que isso significa? Em resumo, se o elemento está fora da tela, seus descendentes não renderizado. O navegador determina o tamanho do elemento sem considerar todo o conteúdo dele e para ali. A maior parte da renderização, como o estilo e o layout da subárvore do elemento são ignorados.

À medida que o elemento se aproxima da janela de visualização, o navegador não adiciona mais a size. a contenção e começa a pintar e fazer um teste de hit no conteúdo do elemento. Isso permite que o trabalho de renderização seja feito na hora certa para ser visto pelo usuário.

Observação sobre acessibilidade

Um dos recursos do content-visibility: auto é que o conteúdo fora da tela permanece disponível no modelo de objeto do documento e, portanto, na árvore de acessibilidade (ao contrário do visibility: hidden). Isso significa que o conteúdo pode ser pesquisado na página e navegado sem esperar o carregamento ou sacrificar o desempenho da renderização.

No entanto, o lado negativo é que os elementos de referência com recursos de estilo, como display: none ou visibility: hidden, também aparecem na árvore de acessibilidade quando estão fora da tela, já que o navegador não renderiza esses estilos até que eles entrem na viewport. Para evitar que eles fiquem visíveis na árvore de acessibilidade, possivelmente causando confusão, adicione também aria-hidden="true".

Exemplo: um blog de viagens

Neste exemplo, usamos como base o blog de viagens à direita e aplicamos o content-visibility: auto às áreas divididas à esquerda. Os resultados mostram tempos de renderização de 232 ms a 30 ms no carregamento inicial da página.

Um blog de viagens normalmente contém um conjunto de histórias com algumas fotos e algumas um texto descritivo. Veja o que acontece em um navegador comum quando acessa um blog de viagens:

  1. Uma parte da página é transferida por download da rede, junto com os recursos necessários.
  2. O navegador define e apresenta todo o conteúdo da página, sem considerar se o conteúdo é visível para o usuário.
  3. O navegador volta à etapa 1 até que toda a página e todos os recursos sejam baixado.

Na etapa 2, o navegador processa todo o conteúdo procurando elementos que possam mudaram. Ela atualiza o estilo e o layout de todos os novos elementos, além dos elementos que podem ter mudado como resultado das novas atualizações. Isso é renderizar o trabalho. Isso leva tempo.

Captura de tela de um blog de viagens.
Um exemplo de um blog de viagens. Consulte Demonstração no Codepen

Agora considere o que acontece se você colocar content-visibility: auto em cada uma das histórias individuais no blog. O loop geral é o mesmo: o navegador faz o download e renderiza partes da página. No entanto, a diferença está no que ele executa na etapa 2.

Com a visibilidade do conteúdo, ele vai estilizar e definir o layout de todo o conteúdo visíveis para o usuário no momento (eles estão na tela). No entanto, ao processar o história totalmente fora da tela, o navegador ignora o trabalho de renderização e apenas definir o estilo e o layout da própria caixa do elemento.

O desempenho do carregamento dessa página seria como se ela contivesse histórias completas na tela e caixas vazias para cada uma das histórias fora da tela. Isso tem um bom desempenho melhor, com redução esperada de 50% ou mais do custo de renderização de carregando. No exemplo, notamos um aumento do tempo de renderização de 232 ms para um 30 ms de renderização. Isso é um aumento de 7 vezes no desempenho.

Qual é o trabalho que você precisa fazer para colher esses benefícios? Primeiro, nós dividir o conteúdo em seções:

Uma captura de tela anotada da divisão de conteúdo em seções com uma classe CSS.
Exemplo de divisão de conteúdo em seções com a classe story aplicada para receber content-visibility: auto. Consulte Demonstração no Codepen

Em seguida, aplicamos a seguinte regra de estilo às seções:

.story {
  content-visibility: auto;
  contain-intrinsic-size: 1000px; /* Explained in the next section. */
}

Como especificar o tamanho natural de um elemento com contain-intrinsic-size

Para conhecer os possíveis benefícios do content-visibility, o navegador precisa aplicar contenção de tamanho para garantir que os resultados da renderização do conteúdo não afetam o tamanho do elemento de forma alguma. Isso significa que o elemento serão dispostos como se estivessem vazios. Se o elemento não tiver uma altura especificada em um layout de blocos regular, terá a altura 0.

Isso pode não ser o ideal, já que o tamanho da barra de rolagem mudará, sendo se cada história tiver uma altura diferente de zero.

Felizmente, o CSS oferece outra propriedade, contain-intrinsic-size, que especifica efetivamente o tamanho natural do elemento se o elemento for são afetadas pela contenção de tamanho. Em nosso exemplo, vamos defini-lo como 1000px conforme uma estimativa da altura e largura das seções.

Isso significa que ele será apresentado como se tivesse um único filho de "tamanho intrínseco" as dimensões, garantindo que os divs que não foram dimensionados ainda ocupem espaço. contain-intrinsic-size atua como um tamanho de marcador de posição em vez de conteúdo renderizado.

No Chromium 98 em diante, há um novo auto palavra-chave para contain-intrinsic-size. Quando especificado, o navegador lembrará o tamanho da última renderização, se houver, e use-o em vez do marcador de posição fornecido pelo desenvolvedor tamanho. Por exemplo, se você especificou contain-intrinsic-size: auto 300px, o será iniciado com um tamanho intrínseco de 300px em cada dimensão, mas o conteúdo do elemento for renderizado, ele manterá o tamanho intrínseco renderizado. Qualquer alteração subsequente no tamanho de renderização também será lembrada. Na prática, isso significa que, se você rolar um elemento com content-visibility: auto aplicado e depois rolar de volta para fora da tela, ele vai manter automaticamente a largura e a altura ideais, sem reverter para o tamanho do marcador de posição. Esse recurso é especialmente útil para rolagens infinitas, que agora podem melhorar automaticamente a estimativa de dimensionamento ao longo do tempo conforme o usuário navega pela página.

Ocultando conteúdo com o content-visibility: hidden

E se você quiser manter o conteúdo não renderizado, independentemente de ter ou não está na tela, aproveitando os benefícios do estado de renderização em cache? Insira: content-visibility: hidden:

A propriedade content-visibility: hidden oferece os mesmos benefícios de conteúdo não renderizado e estado de renderização em cache como content-visibility: auto faz fora da tela. No entanto, ao contrário de auto, ele não começa a ser são renderizados na tela.

Isso oferece mais controle, permitindo que você oculte o conteúdo de um elemento e depois reexibi-las rapidamente.

Compare-o com outras formas comuns de ocultar o conteúdo do elemento:

  • display: none: oculta o elemento e destrói o estado de renderização. Isso significa que reexibir o elemento é tão caro quanto renderizar um novo elemento com o mesmo conteúdo.
  • visibility: hidden: oculta o elemento e mantém o estado de renderização. Isso não remove o elemento do documento de fato porque ele (e sua subárvore) ainda ocupa espaço geométrico na página e ainda pode ser clicado. Ela também atualiza o estado de renderização sempre que é necessário, mesmo quando está oculto.

content-visibility: hidden, por outro lado, oculta o elemento enquanto o estado de renderização. Por isso, em caso de alterações que precisem acontecerão, elas só acontecem quando o elemento é mostrado novamente (ou seja, o A propriedade content-visibility: hidden foi removida.

Alguns ótimos casos de uso para content-visibility: hidden são ao implementar controles de rolagem virtuais avançados e medição do layout. Eles também são ótimos para aplicativos de página única (SPAs). As visualizações de aplicativos inativas podem ser deixadas no DOM com content-visibility: hidden foi aplicado para impedir a exibição, mas manter a em cache. Isso acelera a renderização da visualização quando ela fica ativa novamente.

Efeitos na métrica "Interaction to Next Paint" (INP)

INP é uma métrica que avalia a capacidade de uma página de responder de forma confiável à entrada do usuário. A capacidade de resposta pode ser afetada por qualquer quantidade excessiva de trabalho que ocorra na linha de execução principal, incluindo o trabalho de renderização.

Sempre que você pode reduzir o trabalho de renderização em qualquer página, está oferecendo à linha de execução principal a oportunidade de responder às entradas do usuário mais rapidamente. Isso inclui o trabalho de renderização. O uso da propriedade CSS content-visiblity quando apropriado pode reduzir o trabalho de renderização, especialmente durante a inicialização, quando a maior parte dos trabalhos de renderização e layout é concluído.

Reduzir o trabalho de renderização tem um efeito direto no INP. Quando os usuários tentam interagir com uma página que usa a propriedade content-visibility corretamente para adiar o layout e a renderização de elementos fora da tela, você dá à linha de execução principal a chance de responder a trabalhos essenciais visíveis ao usuário. Isso pode melhorar o INP da sua página em algumas situações.

Conclusão

content-visibility e as especificações de contenção do CSS significam um desempenho incrível estão chegando diretamente ao seu arquivo CSS. Para mais informações sobre essas propriedades, consulte: