No Chrome 22, o comportamento de 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 quebrar os layouts delas. O novo comportamento corresponde ao comportamento dos navegadores WebKit em dispositivos móveis (Safari para iOS e Chrome para Android).
O que é o empilhamento?
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 iguais: o z-index
de um elemento determina apenas 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 posicionados de forma absoluta ou relativa com valores z-index
não automáticos formam seus próprios contextos de empilhamento. Ou seja, todos os elementos filhos serão ordenados em z no elemento pai e não serão intercalados com conteúdo de fora dele. 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 dos contextos de empilhamento, este artigo do MDN é uma ótima leitura.
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 (Safari para dispositivos móveis, navegador Android, navegadores baseados em Qt) colocam elementos position:fixed nos próprios contextos de empilhamento e têm isso há algum tempo (desde o iOS5, Android Gingerbread etc.), porque isso permite otimizações de rolagem, tornando as páginas da Web muito mais responsivas ao toque. A mudança foi feita no computador por três motivos:
- Ter um comportamento de renderização diferente em navegadores "mobile" e "desktop" é um obstáculo para os autores da Web. O CSS precisa funcionar da mesma forma em todos os lugares, sempre que possível.
- Com tablets, não está claro qual dos algoritmos de criação de contexto de empilhamento "mobile" ou "desktop" é mais adequado.
- As otimizações de desempenho de rolagem do dispositivo móvel para o computador são boas para usuários e autores.
Detalhes da mudança
Confira um exemplo que mostra os diferentes comportamentos de layout: https://codepen.io/paulirish/pen/CgAof
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 tiver seu próprio contexto de empilhamento, o z-index
da caixa laranja será calculado em relação ao contexto de empilhamento da caixa azul. Como a caixa azul tem um z-index
de auto
, a ela um nível de empilhamento de zero no contexto de empilhamento raiz, isso significa que a caixa laranja fica atrás das caixas verde e rosa, que têm índices Z de 1 e 3 (respectivamente) no contexto raiz.
Se a caixa azul não receber o próprio contexto de empilhamento, o z-index
da caixa laranja será calculado em relação ao contexto de empilhamento raiz (junto com as caixas verde e rosa). Portanto, a caixa laranja acaba sendo intercalada com as caixas rosa e verde.
Para mais detalhes sobre os critérios para a criação de contexto de empilhamento (e como os contextos de empilhamento se comportam em geral), consulte este artigo do MDN. No exemplo, a versão do lado direito sempre dava à caixa azul o próprio contexto de empilhamento porque a opacidade dela é menor que 1. A mudança de comportamento adiciona outro critério para criar um contexto de empilhamento separado, ou seja, um elemento position:fixed.
Testes e o futuro
Para testar se a página vai mudar, acesse about:flags
do Chrome e ative/desative a opção "Os elementos de posição fixa criam contextos de empilhamento". Se o layout se comportar da mesma forma nos dois casos, está tudo certo. Caso contrário, verifique se a flag ativada parece aceitável para você, já que esse será o padrão no Chrome 22.
Essa mudança remove uma capacidade: a capacidade de intercalar conteúdo em um subárvore position:fixed com conteúdo não rolável de fora. É improvável que os desenvolvedores da Web estejam fazendo isso de propósito, e o mesmo efeito pode ser criado ao fornecer vários elementos position:fixed às diferentes partes do DOM. Por exemplo, considere estes dois exemplos:
https://codepen.io/wiltzius/pen/gcjCk
Esta página tenta pegar duas divs filhas (overlayA e overlayB) de um elemento position:fixed e colocar uma acima de uma div de conteúdo separada e outra abaixo dessa mesma div de conteúdo separada. Agora é impossível fazer isso porque o elemento position:fixed é o próprio contexto de empilhamento, e ele (junto com todos os filhos) será totalmente acima ou totalmente abaixo da div de conteúdo. Observe que este exemplo funciona no Chrome 21 e versões anteriores, mas não no Chrome 22.
Para corrigir isso, as duas sobreposições podem ser divididas em elementos position:fixed. Cada um é o próprio contexto de empilhamento, e um deles pode ficar acima do div de conteúdo e outro abaixo. Confira o exemplo corrigido, que funciona no Chrome 21 e 22:
https://codepen.io/wiltzius/pen/vhFzG
O crédito pela origem deste exemplo vai para a inimitável hixie.
O Chrome é o primeiro navegador para computador que faz com que os elementos position:fixed criem seus próprios contextos de empilhamento. O padrão relevante é a especificação do índice z do CSS (consulte, por exemplo, https://www.w3.org/TR/CSS21/zindex.html). Ainda não há consenso sobre o que fazer com a diferença entre os navegadores para dispositivos móveis e computadores. No entanto, devido à confusão de ter dois comportamentos diferentes em dispositivos móveis e computadores, o Chrome optou por mudar para esse comportamento único em ambas as plataformas por enquanto.
Atualizado em 1º de outubro de 2012:a versão original deste artigo sugeria que a especificação CSS z-index
já havia sido alterada para refletir o novo comportamento de position: fixed elements. Isso não é preciso. O assunto foi discutido na lista de estilo www, mas nenhuma mudança foi feita na especificação até o momento.