O macete para unidades de viewport em mobile

O macete para unidades de viewport em mobile para conseguir 100vh real na tela!

Ir para o artigo

Unidades de viewport podem ser controversas, e parte disso é devido à maneira como os navegadores móveis tornaram as coisas mais complicadas ao terem suas próprias opiniões sobre como implementá-las.

Caso em questão: a barra de rolagem deve ser levada em consideração para a unidade vw? E quanto à navegação de um site ou aos controles de página, eles devem ser considerados no cálculo? Depois, existem atributos físicos dos próprios dispositivos que não podem ser ignorados — olá, notch!

Recentemente, publicamos o artigo Algumas coisas que você deve saber ao trabalhar com unidades de viewport, em que abordávamos um pouco sobre isso, mas o que você vai aprender a seguir, realmente vai um passo além.

Um pouco de contexto

A especificação é bastante vaga sobre como as unidades de viewport devem ser calculadas. Em dispositivos móveis, geralmente nos preocupamos com a altura vertical; portanto, vejamos especificamente sobre viewport height (vh):

unidade vh
Igual a 1% da altura do containing block inicial.

Então, sim, não há orientações claras quando se trata de lidar com diferenciações específicas de dispositivos e navegadores.

vh foi inicialmente calculado pela viewport atual do seu navegador. Se você abriu o navegador e começou a carregar um site, 1vh era igual a 1% da altura da tela, menos a interface do navegador.

Mas… Se você começar a rolar a tela, é uma história diferente! Depois que você passa por uma parte da interface do navegador, como a barra de endereço, o valor vh será atualizado e o resultado será um salto estranho (awkward jump) no conteúdo.

O Safari para iOS foi um dos primeiros navegadores móveis a atualizar sua implementação, escolhendo definir um valor fixo para vh com base na altura máxima da tela. Ao fazer isso, o usuário não experimentaria saltos na página depois que a barra de endereços ficasse fora de vista. O navegador móvel do Chrome seguiu o exemplo.

Embora o uso de um valor fixo seja bom, isso também significa que você não pode ter um elemento de altura total se a barra de endereço estiver em exibição. A parte inferior do elemento será cortada.

Comparativo de telas mobile, uma mostrando o erro que acontece e a outra está correta devido à implementação do macete para unidades de viewport em mobile.
Um elemento é cortado na parte inferior quando a barra de endereço está à vista (esquerda), mas o resultado desejado é ter a coisa completa (direita).

CSS Custom Properties: o truque para corrigir o dimensionamento

CSS Custom Properties (mais conhecidas como Variáveis CSS) e algumas linhas de JavaScript podem ser a maneira perfeita de obter o dimensionamento consistente e correto que eu precisava.

Em JavaScript, é possível obter o valor da viewport atual usando a variável global window.innerHeight. Esse valor leva em conta a interface do navegador e é atualizado quando sua visibilidade muda. O truque é armazenar o valor da viewport em uma variável CSS e aplicá-lo ao elemento em vez da unidade vh.

Digamos que, neste exemplo, a variável CSS seja --vh. Isso significa que o código serial algo como:

Agora é pegar a altura interna da viewport no JavaScript:

O JS vai pegar a altura da viewport e a ajustar em 1/100 desse total para que se tenha um valor para atribuir como o valor da unidade de altura da viewport. Então, pedimos educadamente ao JS para criar a variável CSS (--vh) em :root.

Como resultado, agora é possível usar usar --vh como o valor de altura (tal como é possível com qualquer outra unidade de vh), multiplicá-lo por 100 e conseguir a altura total desejada.

Opa, tem mais um detalhe!

Apesar de a solução já parecer concluída, aqueles com um olhar mais acurado para os detalhes podem ter percebido que o JavaScript é acionado, mas nunca atualiza o tamanho do elemento quando a altura da janela de visualização muda!

É possível atualizar o valor de --vh para ficar escutando o evento resize da janela. Isso é útil caso o usuário gire a tela do dispositivo ou a navegação saia da vista ao scrollar.

Além disso, convém implementar um método de debounce para o evento de redimensionamento para evitar o acionamento de muitos eventos enquanto o usuário está redimensionando a janela do navegador. Veja debouncing e throttling sendo explicados através de exemplos.

Agora sim o exemplo está funcionando corretamente. 👍

Conclusão

Só relembrando o aviso dado, esse macete para unidades de viewport em mobile provavelmente não cairá bem e todo e qualquer projeto. Você deve avaliar se o usará ou não.

Além disso, hoje em dia os navegadores tendem a serem atualizados muito rapidamente, portanto, esteja atendo e confira se a solução de hoje continuará relevante (e funcionando) amanhã.

E você, já escutou reclamações sobre esse problema e não sabia como arrumar na época? Bem, agora você sabe como fazer… De qualquer maneira, comente sobre esse caso aí nos comentários!

Usamos cookies para melhorar sua experiência e para ajudar a entender como nosso site é usado. Ao utilizar este site, você aceita o uso de cookies. Consulte nossa política de privacidade para obter mais informações.