Mudanças de empilhamento chegando à posição:elementos fixos

Tom Wiltzius
Tom Wiltzius

No Chrome 22, o comportamento do layout dos elementos position:fixed é um pouco diferente das versões anteriores. Todos os elementos position:fixed agora formam novos contextos de empilhamento. Isso vai mudar a ordem de empilhamento de algumas páginas, o que pode interromper os layouts. O novo comportamento corresponde ao comportamento dos navegadores do WebKit em dispositivos móveis (iOS Safari e Chrome para Android).

O que há empilhando?

Todo mundo conhece e adora o z-index para determinar a ordem de profundidade dos elementos em uma página. No entanto, nem todos os Z-indexes são criados da mesma forma: o z-index de um elemento determina a ordem em relação a outros elementos no mesmo contexto de empilhamento. A maioria dos elementos em uma página está em um único contexto de empilhamento raiz, mas elementos absolutos ou relativamente posicionados com valores de z-index não automáticos formam os próprios contextos de empilhamento, ou seja, todos os filhos serão ordenados em z dentro do pai e não serão intercalados com conteúdo de fora do pai. A partir do Chrome 22, os elementos position:fixed também vão criar os próprios contextos de empilhamento.

Para uma visão geral sobre o empilhamento de contextos, este artigo da MDN é ótimo para ler.

Compare position:fixed com o novo atributo position:sticky: para referência, position:sticky sempre cria um novo contexto de empilhamento.

Motivação

Os navegadores para dispositivos móveis (Mobile Safari, navegador Android, navegadores baseados em Qt) colocam os elementos position:fixos em seus próprios contextos de empilhamento e têm há algum tempo (desde o iOS5, Android Gingerbread etc.) porque permitem certas otimizações de rolagem, tornando as páginas da web muito mais responsivas ao toque. A mudança está sendo implementada nos computadores por três motivos:

  1. Ter um comportamento de renderização diferente em navegadores para dispositivos móveis e computadores é um obstáculo para os autores da Web. O CSS deve funcionar da mesma forma em qualquer lugar, sempre que possível.
  2. Com tablets, não fica claro qual dos algoritmos de criação de contexto de empilhamento para "dispositivo móvel" ou "computador" é mais apropriado.
  3. Trazer as otimizações de desempenho de rolagem do celular para o computador é bom para usuários e autores.

Detalhes da mudança

Confira um exemplo dos diferentes comportamentos de layout: https://codepen.io/paulirish/pen/CgAof (em inglês).

Com a mudança, as duas versões serão renderizadas como a versão à direita.

Neste exemplo, a caixa verde tem um z-index: 1, a caixa rosa tem um z-index: 3 e a caixa laranja tem um z-index: 2. A caixa azul é um ancestral da caixa laranja e tem position:fixed.

Se a caixa azul receber o próprio contexto de empilhamento, o z-index da caixa laranja vai ser calculado em relação ao contexto de empilhamento da caixa azul. Como a caixa azul tem um z-index de auto, o que dá a ela um nível de empilhamento zero no contexto de empilhamento raiz, isso significa que a caixa laranja fica atrás das caixas verde e rosa, que têm Z-indexes de 1 e 3 (respectivamente) no contexto raiz.

Se a caixa azul não tiver o próprio contexto de empilhamento, o z-index da caixa laranja vai ser calculado em relação ao contexto de empilhamento raiz, com as caixas verde e rosa. Portanto, a caixa laranja acaba intercalada com as caixas rosa e verde.

Para saber mais sobre os critérios de criação de contexto de empilhamento (e como eles se comportam em geral), consulte este artigo da MDN. No exemplo, a versão à direita sempre deu à caixa azul o próprio contexto de empilhamento, porque a opacidade é inferior a 1. A mudança de comportamento feita adiciona outro critério para criar um contexto de empilhamento separado, ou seja, um elemento que tem posição fixa.

Testes e o futuro

Para testar se a página vai mudar, acesse o about:flags do Chrome e ative/desative a opção "Elementos de posição fixa criam contextos de empilhamento". Se o layout se comportar da mesma forma nos dois casos, está tudo pronto. Caso contrário, verifique se o problema é aceitável com essa sinalização ativada, já que esse será o padrão no Chrome 22.

Essa mudança remove um recurso, ou seja, a possibilidade de intercalar o conteúdo dentro de uma subárvore de posição:fixada com conteúdo sem rolagem de fora É improvável que algum desenvolvedor da Web faça isso de propósito, e o mesmo efeito pode ser gerado ao atribuir a vários elementos position:fixos diferentes partes do DOM. Por exemplo, considere estes dois exemplos:

https://codepen.io/wiltzius/pen/gcjCk

Esta página tenta pegar dois divs filhos (overlayA e overlayB) de um elemento position:Fixed e colocar um acima de um div de conteúdo separado e outro abaixo do mesmo div de conteúdo separado. Agora é impossível fazer isso porque o elemento position:fix é o próprio contexto de empilhamento e ele (junto com todos os filhos) vai estar totalmente acima ou abaixo do div de conteúdo. No Chrome 2 e versões anteriores.

Para corrigir isso, as duas sobreposições podem ser divididas em seus próprios elementos de posição:fixo. Cada um tem o próprio contexto de empilhamento. Um deles pode ficar acima do div de conteúdo e outro abaixo dele. Veja o exemplo fixo que funciona no Chrome 21 e 22:

https://codepen.io/wiltzius/pen/vhFzG

O crédito para a gênese deste exemplo vai para o inimitável hixie.

O Google Chrome é o primeiro navegador para computador a fazer com que os elementos position:fixos criem seus próprios contextos de empilhamento. O padrão relevante é a especificação z-index do CSS (por exemplo, https://www.w3.org/TR/CSS21/zindex.html). Ainda não há consenso sobre o que fazer sobre a diferença entre navegadores para dispositivos móveis e computadores. No entanto, por conta da confusão de ter dois comportamentos diferentes em dispositivos móveis e computadores, por enquanto, o Chrome optou por mudar para esse único comportamento em ambas as plataformas.

Atualizado em 1o de outubro de 2012: a versão original deste artigo sugeriu que a especificação z-index do CSS já havia sido alterada para refletir o novo comportamento da posição: elementos fixos. Isso é impreciso; já foi discutido na lista de estilo www, mas ainda nenhuma alteração foi feita na especificação.