Contenção de CSS no Chrome 52

Texto longo, leia o resumo

A nova propriedade CSS Containment permite que os desenvolvedores limitem o escopo dos estilos, layout e trabalho de pintura do navegador.

Contenção de CSS. Antes: o layout leva 59,6ms. Depois: o layout leva 0,05ms

Ele tem alguns valores, e a sintaxe é a seguinte:

    contain: none | strict | content | [ size || layout || style || paint ]

Ele está disponível no Chrome 52 e no Opera 40 ou superior (e tem suporte público do Firefox), então experimente e nos conte o que fez.

A propriedade "contains"

Ao criar um aplicativo da web, ou mesmo um site complexo, um desafio importante de desempenho é limitar os efeitos de estilos, layout e pintura. Muitas vezes, todo o DOM é considerado "no escopo" para trabalhos de computação, o que pode significar que tentar uma "visualização" independente em um aplicativo da Web pode ser complicada: alterações em uma parte do DOM podem afetar outras partes e não há como dizer ao navegador o que deve estar dentro ou fora do escopo.

Por exemplo, digamos que parte do seu DOM tenha esta aparência:

    <section class="view">
      Home
    </section>

    <section class="view">
      About
    </section>

    <section class="view">
      Contact
    </section>

E você anexa um novo elemento a uma visualização, o que acionará estilos, layout e pintura:

    <section class="view">
      Home
    </section>

    <section class="view">
      About
      <div class="newly-added-element">Check me out!</div>
    </section>

    <section class="view">
      Contact
    </section>

Nesse caso, no entanto, todo o DOM está efetivamente no escopo, o que significa que os cálculos de estilo, layout e pintura precisarão considerar todos os elementos, independentemente de terem sido alterados ou não. Quanto maior o DOM, mais trabalho de computação envolve, o que significa que você pode fazer com que seu aplicativo não responda à entrada do usuário.

A boa notícia é que os navegadores modernos estão ficando muito inteligentes em limitar automaticamente o escopo de estilos, layout e pintura, o que significa que as coisas estão ficando mais rápidas sem que você tenha que fazer nada.

Mas a notícia ainda melhor é que há uma nova propriedade CSS que envia os controles de escopo para os desenvolvedores: a Conteinment.

A contenção de CSS é uma nova propriedade, com a palavra-chave “contains”, que aceita quatro valores:

  • layout
  • paint
  • size
  • style

Cada um desses valores permite limitar o trabalho de renderização que o navegador precisa realizar. Vamos analisar cada um com um pouco mais de detalhes.

Layout (conter: layout)

A contenção do layout é provavelmente o maior benefício da contenção, junto com contain: paint.

Normalmente, o layout tem o escopo do documento, o que faz com que ele seja dimensionado proporcionalmente ao tamanho do seu DOM. Portanto, se você mudar a propriedade left de um elemento, cada elemento no DOM precisará ser verificado.

Ativar a contenção aqui pode reduzir potencialmente o número de elementos para apenas alguns, em vez de todo o documento, economizando muito trabalho desnecessário para o navegador e melhorando significativamente o desempenho.

Tinta (conter: tinta)

A definição do escopo é outro benefício incrivelmente útil da contenção. A contenção de pintura basicamente recorta o elemento em questão, mas também tem alguns outros efeitos colaterais:

  • Ele atua como um bloco para elementos de posição absoluta e fixa. Isso significa que todos os filhos são posicionados com base no elemento com contain: paint, e não em qualquer outro elemento pai, como o documento.
  • Ela se torna um contexto de empilhamento. Isso significa que coisas como z-index vão afetar o elemento, e os filhos serão empilhados de acordo com o novo contexto.
  • Ela se torna um novo contexto de formatação. Isso significa que, se você tiver, por exemplo, um elemento no nível do bloco com contenção de pintura, ele será tratado como um ambiente de layout novo e independente. Isso significa que o layout fora do elemento normalmente não afeta os filhos do elemento contêiner.

Tamanho (conter: size)

O que contain: size significa é que os filhos do elemento não afetam o tamanho do elemento pai e que as dimensões inferidas ou declaradas serão usadas. Consequentemente, se você definir contain: size, mas não especificar as dimensões do elemento (diretamente ou usando propriedades flexíveis), ele será renderizado em 0 x 0 px.

A contenção de tamanho é uma medida de cinto e chaves para garantir que você não dependa de elementos filhos para o dimensionamento, mas por si só não oferece muitos benefícios de desempenho.

Estilo (conter: estilo)

Pode ser difícil prever quais efeitos que a alteração dos estilos de um elemento terá na árvore do DOM estarão presentes novamente na árvore. Um exemplo disso é em algo como os contadores CSS, em que a alteração de um contador em um filho pode afetar os valores de contador com o mesmo nome usados em outras partes do documento. Com a contain: style definida, as mudanças de estilo não serão propagadas para além do elemento contêiner.

Para esclarecer, o que o contain: style não oferece é o estilo com escopo, semelhante ao do Shadow DOM. a contenção aqui se trata puramente de limitar as partes da árvore que estão em consideração quando os estilos são transformados, não quando são declarados.

Restrição e contenção de conteúdo

Também é possível combinar palavras-chave, como contain: layout paint, que vão aplicar somente esses comportamentos a um elemento. Mas “contains” também é compatível com dois outros valores:

  • contain: strict significa o mesmo que contain: size layout paint
  • contain: content significa o mesmo que contain: layout paint

O uso de contenção rigorosa é ótimo quando você sabe o tamanho do elemento com antecedência (ou quer reservar as dimensões dele), mas tenha em mente que, se você declarar a contenção sem dimensões rígidas, devido à contenção de tamanho implícita, o elemento pode ser renderizado como uma caixa de 0 x 0 px.

A contenção de conteúdo, por outro lado, oferece melhorias significativas de escopo, mas não exige que você conheça ou especifique as dimensões do elemento com antecedência.

Das duas, contain: content é o que você precisa usar por padrão. Trate a contenção rigorosa como alternativa quando o contain: content não é suficiente para suas necessidades.

Conte-nos como você está

A contenção é uma ótima maneira de começar a indicar ao navegador o que você pretende manter isolado na página. Experimente o Chrome 52+ e conte-nos como está fazendo isso.