Melhore o tempo de carregamento inicial ignorando a renderização de conteúdo fora da tela.
A propriedade
content-visibility
, lançada no Chromium 85, pode ser uma das novas propriedades do CSS
mais impactantes para melhorar o desempenho do carregamento de página. content-visibility
permite que o
user agent pule o trabalho de renderização de um elemento, incluindo o layout e a pintura,
até que ele seja necessário. Como a renderização é ignorada, se uma grande parte do
conteúdo estiver fora da tela, o uso da propriedade content-visibility
vai acelerar o
carregamento inicial do usuário. Ele também permite interações mais rápidas com o
conteúdo na tela. Muito legal.
Suporte ao navegador
O content-visibility
depende de primitivos da especificação de contenção do CSS. Embora, por enquanto, content-visibility
seja compatível apenas com o Chromium 85 e seja considerado "vale a prototipagem" para o Firefox, a especificação de contenção é compatível com os navegadores mais modernos.
Contenção de CSS
O principal objetivo da contenção do CSS é possibilitar melhorias no desempenho de renderização do conteúdo da Web, fornecendo isolamento previsível de uma subárvore do DOM do restante da página.
Basicamente, um desenvolvedor pode informar ao navegador quais partes da página sã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) têm conteúdo isolado significa que o navegador pode tomar decisões de otimização para a renderização da página.
Existem quatro tipos de contenção de CSS, cada um sendo um valor em potencial para a propriedade CSS contain
, que podem ser combinados em uma lista de valores separados por espaços:
size
: a contenção de tamanho em um elemento garante que a caixa do elemento possa ser disposta sem precisar examinar os descendentes. Isso significa que podemos pular o layout dos descendentes se só precisamos do tamanho do elemento.layout
: contenção de layout significa que os descendentes não afetam o layout externo de outras caixas na página. Isso nos permite pular o layout dos descendentes se quisermos apenas posicionar outras caixas.style
: a contenção de estilo garante que propriedades que podem ter efeitos sobre mais do que apenas seus descendentes não escapem do elemento (por exemplo, contadores). Isso nos permite pular o cálculo de estilo dos descendentes se tudo que queremos for computar estilos em outros elementos.paint
: a contenção de pintura garante que os descendentes da caixa que a contém não sejam exibidos fora dos limites. Nada pode visivelmente estourar o elemento. Se um elemento estiver fora da tela ou não visível, os descendentes dele também não ficarão visíveis. Isso nos permite pular a pintura dos 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, já que as otimizações de navegador só podem entrar em ação quando um conjunto apropriado é especificado. Você pode testar os valores para ver o que funciona melhor ou usar outra propriedade CSS chamada content-visibility
para aplicar a contenção necessária automaticamente. O content-visibility
garante que você tenha os maiores
ganhos de desempenho que o navegador pode oferecer com o mínimo de esforço da sua parte
como desenvolvedor.
A propriedade de visibilidade do conteúdo aceita vários valores, mas auto
é aquela
que oferece melhorias imediatas de desempenho. Um elemento que tem
content-visibility: auto
ganha a contenção layout
, style
e paint
. Se
o elemento estiver fora da tela e não for relevante para o usuário (elementos
relevantes são aqueles que têm foco ou seleção na subárvore), ele
também recebe a contenção de size
e interrompe
a pintura
e
o teste de hit
do próprio conteúdo.
O que isso significa? Em resumo, se o elemento estiver fora da tela, os descendentes dele não serão renderizados. O navegador determina o tamanho do elemento sem considerar nenhum conteúdo e para aí. A maior parte da renderização, como o estilo e o layout da subárvore do elemento, é ignorada.
À medida que o elemento se aproxima da janela de visualização, o navegador não adiciona mais a contenção size
e começa a pintar e testar o conteúdo do elemento. Isso
permite que o trabalho de renderização seja feito apenas a tempo de 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 é possível pesquisar e navegar pelo conteúdo na página sem esperar que ele seja carregado nem prejudicar o desempenho da renderização.
O lado inverso disso, no entanto, é que elementos de ponto de referência com recursos de estilo como display: none
ou visibility: hidden
também aparecerão na árvore de acessibilidade quando estiverem fora da tela, já que o navegador não renderizará esses estilos até que eles entrem na janela de visualização. 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
Um blog de viagens normalmente contém um conjunto de histórias com algumas imagens e um texto descritivo. Veja o que acontece em um navegador comum quando ele acessa um blog de viagens:
- Uma parte da página é transferida por download da rede com os recursos necessários.
- O navegador define e mostra todo o conteúdo da página, sem considerar se o conteúdo está visível para o usuário.
- O navegador volta à etapa 1 até que toda a página e todos os recursos sejam baixados.
Na etapa 2, o navegador processa todo o conteúdo procurando itens que podem ter mudado. 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 é o trabalho de renderização. Isso leva tempo.
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á na
quantidade de trabalho realizada na etapa 2.
Com a visibilidade do conteúdo, ele estiliza e define o layout de todos os conteúdos que estão visíveis para o usuário no momento (que estão na tela). No entanto, ao processar a história que está totalmente fora da tela, o navegador pula o trabalho de renderização e só define o estilo e o layout da própria caixa do elemento.
O carregamento dessa página seria como se ela contivesse histórias completas e caixas vazias para cada uma delas. Isso tem um desempenho muito melhor, com redução esperada de 50% ou mais do custo de renderização de carregamento. No nosso exemplo, notamos um aumento de um tempo de renderização de 232 ms para um tempo de renderização de 30 ms. Isso é um aumento de 7 vezes no desempenho.
Qual é o trabalho que você precisa fazer para colher esses benefícios? Primeiro, dividimos o conteúdo em seções:
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 aproveitar 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 afetem o tamanho do elemento. Isso significa que o elemento
será disposto como se estivesse vazio. Se o elemento não tiver uma altura especificada
em um layout de bloco regular, ele terá a altura 0.
Isso pode não ser o ideal, já que o tamanho da barra de rolagem vai mudar, dependendo de que cada matéria tenha uma altura diferente de zero.
Felizmente, o CSS oferece outra propriedade, contain-intrinsic-size
, que
especifica efetivamente o tamanho natural do elemento se ele for
afetado pela contenção de tamanho. No nosso exemplo, estamos a definindo como 1000px
como
uma estimativa para a altura e a largura das seções.
Isso significa que ele será apresentado como se tivesse um único filho de dimensões "tamanho intrínseco",
garantindo que os divs sem tamanho 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 e em diante, há uma nova palavra-chave auto
para contain-intrinsic-size
. Quando especificado, o navegador se lembra
do tamanho da última renderização, se houver, e o usa em vez do tamanho do marcador de posição
fornecido pelo desenvolvedor. Por exemplo, se você especificou contain-intrinsic-size: auto 300px
, o
elemento vai começar com um dimensionamento intrínseco de 300px
em cada dimensão, mas, quando
o conteúdo do elemento for renderizado, ele vai 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 a largura e a altura ideais, sem reverter
para o tamanho do marcador. Esse recurso é especialmente útil para rolagem infinita,
que agora pode melhorar automaticamente a estimativa de dimensionamento ao longo do tempo à medida que o usuário
explora a página.
Ocultando conteúdo com o content-visibility: hidden
E se você quiser manter o conteúdo não renderizado, independente de ele
estar ou não 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 que o content-visibility: auto
oferece
fora da tela. No entanto, ao contrário do auto
, ele não começa a ser renderizado
automaticamente na tela.
Isso oferece mais controle, permitindo ocultar o conteúdo de um elemento e depois reexibir 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, já que ele (e a 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
preserva o estado de renderização. Portanto, se houver alguma mudança que precise
acontecer, ela só vai acontecer quando o elemento for mostrado novamente (ou seja, a
propriedade content-visibility: hidden
é removida).
Alguns ótimos casos de uso para content-visibility: hidden
são ao implementar
rolagens virtuais avançadas e medir o layout. Elas também são ótimas para
aplicativos de página única (SPAs). As visualizações de apps inativas podem ser deixadas no DOM com
content-visibility: hidden
aplicado para evitar a exibição, mas manter o
estado armazenado em cache. Isso acelera a renderização da visualização quando ela fica ativa novamente.
Efeitos na interação com a próxima exibição (INP, na sigla em inglês)
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 a especificação de contenção do CSS significam que seu arquivo CSS oferece melhorias de desempenho
incríveis. Para mais informações sobre essas propriedades, confira: