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 CSS
mais impactantes para melhorar o desempenho do carregamento de página. content-visibility
permite que o
user agent ignore o trabalho de renderização de um elemento, incluindo layout e pintura,
até que seja necessário. Como a renderização é ignorada, se grande parte do
conteúdo estiver fora da tela, o uso da propriedade content-visibility
acelera muito 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 na especificação CSS
de contenção (link em inglês). Embora content-visibility
seja compatível apenas com o Chromium 85 por enquanto (e considerado "worth
prototipagem" para o
Firefox), a especificação de contenção é compatível com a maioria dos navegadores
modernos.
Contenção do CSS
O objetivo principal e abrangente da contenção de CSS é permitir melhorias no desempenho da 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 a um navegador quais partes da página são encapsuladas como um conjunto de conteúdo. Isso permite que os navegadores considerem 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 um valor potencial para a propriedade CSS contain
, que pode ser combinado 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 dispostas sem precisar examinar os descendentes. Isso significa que podemos ignorar o layout dos descendentes se só precisamos do tamanho do elemento.layout
: a contenção de layout significa que os descendentes não afetam o layout externo de outras caixas na página. Isso nos permitirá pular o layout dos descendentes se quisermos apenas posicionar outras caixas.style
: a contenção de estilo garante que as propriedades que podem ter efeitos em mais do que apenas os descendentes não escapem do elemento (por exemplo, contadores). Isso permite pular a computação de estilo para os descendentes se quisermos calcular 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 estourar visivelmente o elemento e, se um elemento estiver fora da tela ou não visível, os descendentes também não estarão visíveis. Isso permite pular a pintura dos descendentes se o elemento estiver fora da tela.
Como pular o trabalho de renderização com content-visibility
Pode ser difícil descobrir quais valores de contenção usar, já que as otimizações do navegador só são iniciadas quando um conjunto apropriado é especificado. Faça testes com os valores para ver o que funciona melhor ou use outra propriedade CSS chamada content-visibility
para aplicar a contenção necessária automaticamente. O content-visibility
garante os maiores
ganhos de desempenho que o navegador pode proporcionar 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
é a que fornece melhorias imediatas de desempenho. Um elemento que tem
content-visibility: auto
recebe contenção de layout
, style
e paint
. Se
o elemento estiver fora da tela (e não for relevante para o usuário, porque os elementos
relevantes seriam aqueles com foco ou seleção na subárvore), ele
também receberá contenção de size
(e interrompe a
pintura
e
testes de hit
do conteúdo).
O que isso significa? Em resumo, se o elemento estiver fora da tela, os descendentes não serão renderizados. O navegador determina o tamanho do elemento sem considerar nenhum conteúdo e para por 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 de size
e começa a pintar e testar o conteúdo do elemento. Isso
permite que o trabalho de renderização seja feito a tempo 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 esse conteúdo pode ser pesquisado na página e navegado sem esperar que ele seja carregado ou sacrificar o desempenho da renderização.
O lado negativo disso, no entanto, é que os elementos de ponto de referência com recursos de estilo, como display: none
ou visibility: hidden
, também aparecem na árvore de acessibilidade quando fora da tela, já que o navegador não renderiza esses estilos até entrar na janela de visualização. Para evitar que eles fiquem visíveis na árvore de acessibilidade, o que pode causar desorganizaçã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 fotos e texto descritivo. Veja o que acontece em um navegador comum ao acessar um blog de viagens:
- É feito o download de uma parte da página pela rede, com todos os recursos necessários.
- O navegador define o estilo e layout de todo o conteúdo da página sem considerar se o conteúdo está visível para o usuário.
- O navegador volta para a etapa 1 até concluir o download de toda a página e de todos os recursos.
Na etapa 2, o navegador processa todo o conteúdo à procura de aspectos que podem ter mudado. Ela atualiza o estilo e o layout de todos os novos elementos, com os elementos que podem ter mudado como resultado de novas atualizações. Esse é 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 do 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 feito na etapa 2.
Com a visibilidade do conteúdo, ela aplica estilo e layout a todos os conteúdos que estão visíveis para o usuário (estão na tela). No entanto, ao processar a história que está totalmente fora da tela, o navegador vai ignorar o trabalho de renderização e apenas aplicar estilo e layout à própria caixa do elemento.
O carregamento dessa página seria como se ela contivesse matérias inteiras e caixas vazias para cada uma das histórias fora da tela. Isso tem um desempenho muito melhor, com redução esperada de 50% ou mais do custo de carregamento de renderização. No exemplo, observamos um aumento de tempo de renderização de 232ms para 30ms. Isso representa 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. */
}
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á apresentado como se estivesse vazio. Se o elemento não tiver uma altura especificada
em um layout de blocos normal, ele terá uma altura 0.
Isso pode não ser o ideal, já que o tamanho da barra de rolagem vai mudar, dependendo de que cada história tenha uma altura diferente de zero.
Felizmente, o CSS fornece outra propriedade, contain-intrinsic-size
, que
especifica o tamanho natural do elemento se ele for
afetado pela contenção de tamanho. No nosso exemplo, definimos como 1000px
como
uma estimativa da altura e largura das seções.
Isso significa que ele será apresentado como se tivesse um único filho de dimensões de "tamanho intrínseco", garantindo que seus divs de tamanho não ocupem espaço.
contain-intrinsic-size
atua como um tamanho de marcador de posição em vez do conteúdo renderizado.
No Chromium 98 e versões mais recentes, há uma nova palavra-chave auto
para contain-intrinsic-size
. Quando especificado, o navegador vai se lembrar
do último tamanho renderizado, se houver, e usar esse valor em vez do tamanho do marcador fornecido
pelo desenvolvedor. Por exemplo, se você especificou contain-intrinsic-size: auto 300px
, o
elemento começa com um dimensionamento intrínseco 300px
em cada dimensão, mas, quando
o conteúdo do elemento é renderizado, ele mantém o tamanho intrínseco renderizado.
Qualquer mudança 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 e não será revertido
para o dimensionamento 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 content-visibility: hidden
E se você quiser manter o conteúdo não renderizado, independente de estar ou não
na tela, aproveitando os benefícios do estado de renderização em cache? Digite:
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 de auto
, ela não começa a ser renderizada automaticamente
na tela.
Isso proporciona mais controle, permitindo que você oculte o conteúdo de um elemento e, mais tarde, exiba-o rapidamente.
Compare-o com outras formas comuns de ocultar o conteúdo de um 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 verdade, já que ele (e a subárvore) ainda ocupa espaço geométrico na página e ainda pode ser clicado. Ele também atualiza o estado de renderização sempre que necessário, mesmo quando oculto.
Por outro lado, content-visibility: hidden
oculta o elemento e, ao mesmo tempo,
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
for removida).
Alguns ótimos casos de uso para content-visibility: hidden
são a implementação
de controles de rolagem virtuais avançados e a medição do layout. Elas também são ideais para aplicativos de página única (SPA, na sigla em inglês). As visualizações inativas de apps podem ser deixadas no DOM com
content-visibility: hidden
aplicado para evitar a exibição, mas manter o
estado em cache. Isso agiliza a renderização da visualização quando ela é reativada.
Efeitos na interação com a próxima exibição (INP, na sigla em inglês)
A INP é uma métrica que avalia a capacidade de uma página ser responsiva à entrada do usuário de maneira confiável. A capacidade de resposta pode ser afetada por qualquer quantidade excessiva de trabalho 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, oferece à linha de execução principal a oportunidade de responder às entradas do usuário mais rapidamente. Isso inclui o trabalho de renderização e o uso da propriedade CSS content-visiblity
, quando adequado, pode reduzir o trabalho de renderização, especialmente durante a inicialização, quando a maior parte do trabalho de renderização e layout é feita.
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 ao trabalho crítico visível para o usuário. Isso pode melhorar o INP da sua página em algumas situações.
Conclusão
Com content-visibility
e a especificação de contenção de CSS, algumas melhorias de desempenho
interessantes estão sendo aplicadas ao seu arquivo CSS. Para mais informações sobre essas propriedades, confira: