Pare de Usar 100vh no Mobile: O Guia Completo para Entender e Aplicar 100dvh Corretamente

Published on: 2026-01-06
Post image
pt 100vh 100dvh viewport-height css-mobile css-responsivo front-end desenvolvimento-frontend layout-mobile css-moderno ux-mobile safari-mobile-css chrome-mobile-css dynamic-viewport-height spa-frontend mobile-first design-responsivo css3

Em layouts responsivos, é comum criar seções que ocupam “a altura inteira da tela”, como heróis (hero sections), telas de boas-vindas e modais em tela cheia. Em computadores, a unidade CSS vh costuma funcionar como esperado, mas em dispositivos móveis surgem cortes, espaços em branco e saltos de layout.

Esses problemas normalmente não são causados por erro no CSS, e sim pela forma como navegadores móveis lidam com a própria interface, como barras de endereço e de navegação. Entender a diferença entre 100vh e 100dvh ajuda a construir telas realmente “full screen” sem conteúdo escondido atrás da interface do navegador.

O que é viewport e por que ele muda no celular

Viewport é a área visível onde a página é desenhada dentro do navegador. Em desktops, essa área tende a ser estável, porque a barra do navegador não muda de tamanho durante a rolagem. Em celulares, a interface do navegador pode aparecer e desaparecer conforme a rolagem, alterando a área realmente visível.

Essa variação é chamada de “chrome do navegador”, um termo usado para descrever elementos da interface, como barra de endereço e botões. Quando esses elementos mudam de tamanho, a altura disponível para o conteúdo também muda. O resultado pode ser uma seção que parece ter altura correta em um instante e, em outro, fica grande demais ou pequena demais.

Como o 100vh funciona e por que pode falhar no mobile

A unidade vh significa “viewport height”, ou seja, 1vh equivale a 1% da altura do viewport. Assim, 100vh representa 100% da altura considerada pelo navegador. Em muitos navegadores móveis, essa medida é tratada como uma altura “estática”, que pode não acompanhar as mudanças das barras do navegador.

Na prática, isso pode fazer a seção ocupar mais do que a área visível quando a barra de endereço está presente. Parte do conteúdo pode ficar escondida atrás da barra, dando a impressão de corte no topo ou no rodapé. Em outros momentos, quando a barra se recolhe, surge espaço em branco ou um salto de layout, porque a medida não se ajusta de forma coerente com a área visível real.

O que é 100dvh e o que significa “dynamic viewport height”

A unidade dvh significa “dynamic viewport height”, ou altura dinâmica do viewport. Em termos simples, 100dvh representa 100% da altura realmente visível, recalculada conforme a interface do navegador aparece ou desaparece. Essa unidade foi criada para lidar diretamente com o comportamento variável do viewport em dispositivos móveis.

Com 100dvh, a seção tende a se ajustar ao espaço disponível no momento, evitando que conteúdo fique encoberto pela barra de endereço. Também reduz a chance de sobras visuais e de mudanças bruscas de altura durante a rolagem. Isso melhora a estabilidade do layout, especialmente em páginas que dependem de componentes em tela cheia.

Diferenças práticas entre 100vh e 100dvh

As diferenças ficam mais claras quando a interface do navegador muda durante a navegação. 100vh pode medir uma altura que não corresponde ao “retângulo visível” do conteúdo naquele instante. 100dvh procura sempre corresponder ao que está efetivamente visível na tela.

Os efeitos mais comuns da escolha inadequada aparecem como cortes de conteúdo, sobreposição por barras do navegador e “pulos” ao rolar. Em interfaces que exigem precisão, como uma tela inicial com chamada principal e botão de ação, esses detalhes se tornam problemas de usabilidade. Em geral, 100dvh entrega um encaixe mais previsível para experiências mobile.

Quando usar 100dvh: heróis, modais e telas full-screen

100dvh é especialmente adequado quando a intenção é ocupar a tela visível inteira sem sobras ou cortes. Isso inclui seções de destaque (hero sections), modais em tela cheia e layouts que simulam “aplicativo”, comuns em interfaces modernas. Também é útil em fluxos onde um painel precisa permanecer integralmente visível, como telas de login e onboarding.

Em aplicações de página única, conhecidas como SPA (single-page application), pequenas variações de altura podem causar instabilidade perceptível entre rotas e componentes. Em cenários com cabeçalhos fixos, barras inferiores ou navegação persistente, medir corretamente a altura disponível reduz conflitos. A unidade dinâmica tende a ser uma escolha mais segura para mobile, mantendo o conteúdo dentro do espaço realmente visível.

Exemplo completo: seção de herói com 100vh (comportamento antigo)

O exemplo a seguir mostra uma implementação típica que usa 100vh para preencher a tela. Em muitos celulares, esse padrão pode levar a conteúdo sendo coberto pela barra de endereço ou a variações incômodas ao rolar. O objetivo é ilustrar a abordagem que costuma gerar os problemas descritos.

<!doctype html>
<html lang="pt-BR">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>Exemplo com 100vh</title>
  <style>
    * { box-sizing: border-box; }

    body {
      margin: 0;
      font-family: system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
      line-height: 1.4;
      color: #111;
    }

    .hero {
      height: 100vh; /* altura estática baseada no viewport */
      padding: 24px;
      display: flex;
      flex-direction: column;
      justify-content: center;
      gap: 12px;
      background: #0b5cff;
      color: #fff;
    }

    .hero h1 {
      margin: 0;
      font-size: 32px;
      letter-spacing: -0.02em;
    }

    .hero p {
      margin: 0;
      max-width: 52ch;
      opacity: 0.95;
      font-size: 16px;
    }

    .cta {
      display: inline-block;
      align-self: flex-start;
      background: #fff;
      color: #0b5cff;
      padding: 12px 16px;
      border-radius: 10px;
      text-decoration: none;
      font-weight: 700;
    }
  </style>
</head>
<body>
  <section class="hero">
    <h1>Título em tela cheia</h1>
    <p>Em alguns navegadores móveis, 100vh pode ficar maior do que a área realmente visível quando a barra de endereço aparece.</p>
    <a class="cta" href="#">Ação principal</a>
  </section>
</body>
</html>

Exemplo completo: seção de herói com 100dvh (abordagem moderna)

O exemplo a seguir substitui 100vh por 100dvh, fazendo a seção acompanhar a altura visível real em dispositivos móveis. Isso ajuda a evitar cortes e reduz saltos quando a interface do navegador muda. A estrutura é equivalente, mudando o critério de altura.

<!doctype html>
<html lang="pt-BR">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>Exemplo com 100dvh</title>
  <style>
    * { box-sizing: border-box; }

    body {
      margin: 0;
      font-family: system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
      line-height: 1.4;
      color: #111;
    }

    .hero {
      height: 100dvh; /* altura dinâmica baseada na área visível */
      padding: 24px;
      display: flex;
      flex-direction: column;
      justify-content: center;
      gap: 12px;
      background: #ffcc00;
      color: #1a1a1a;
    }

    .hero h1 {
      margin: 0;
      font-size: 32px;
      letter-spacing: -0.02em;
    }

    .hero p {
      margin: 0;
      max-width: 52ch;
      opacity: 0.95;
      font-size: 16px;
    }

    .cta {
      display: inline-block;
      align-self: flex-start;
      background: #1a1a1a;
      color: #ffcc00;
      padding: 12px 16px;
      border-radius: 10px;
      text-decoration: none;
      font-weight: 700;
    }
  </style>
</head>
<body>
  <section class="hero">
    <h1>Título em tela cheia</h1>
    <p>Com 100dvh, a altura acompanha a área visível, reduzindo cortes e instabilidade quando a interface do navegador muda.</p>
    <a class="cta" href="#">Ação principal</a>
  </section>
</body>
</html>

Uso de min-height: 100dvh e por que isso pode ser mais robusto

Em alguns layouts, usar min-height em vez de height ajuda a acomodar conteúdo variável sem forçar cortes. min-height: 100dvh garante que a seção tenha pelo menos a altura da tela visível, mas permite crescer se houver mais conteúdo. Esse padrão é útil quando o texto, botões ou elementos podem aumentar por tradução, acessibilidade ou quebras de linha.

Quando height é fixado, qualquer conteúdo extra precisa “caber” dentro daquele espaço, o que pode gerar sobreposição ou exigir rolagem interna não planejada. Já min-height preserva a intenção de tela cheia sem limitar o crescimento. Em interfaces móveis, essa flexibilidade tende a reduzir casos em que elementos importantes ficam comprimidos.

overflow: hidden: benefícios e cuidados em telas cheias

A propriedade overflow controla como o conteúdo excedente é tratado quando passa do tamanho do contêiner. Ao usar overflow: hidden em um bloco de tela cheia, a intenção costuma ser eliminar “vazamentos” visuais e evitar barras de rolagem indesejadas causadas por pequenos cálculos de altura. Isso pode deixar a experiência mais limpa, principalmente em heróis com fundo e animações.

Esse uso exige cuidado porque overflow: hidden também pode esconder conteúdo real se o layout for maior do que o espaço disponível. Em seções com textos longos, listas ou componentes que crescem, a ocultação pode reduzir a acessibilidade e a legibilidade. Por isso, a combinação com min-height: 100dvh tende a ser mais segura do que fixar altura rígida em telas com conteúdo variável.

Exemplo completo: layout full-screen com min-height: 100dvh e overflow

O exemplo a seguir demonstra uma configuração comum para seções de impacto, combinando altura mínima dinâmica e controle de overflow. Ele mostra um contêiner que preenche a tela, aceita crescimento quando necessário e evita artefatos visuais. A ideia é concentrar um padrão estável para mobile sem cortes provocados pela UI do navegador.

<!doctype html>
<html lang="pt-BR">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>Full-screen estável com dvh</title>
  <style>
    * { box-sizing: border-box; }

    body {
      margin: 0;
      font-family: system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
      line-height: 1.4;
      color: #0f172a;
      background: #0f172a;
    }

    .tela {
      min-height: 100dvh; /* pelo menos a altura visível */
      overflow: hidden;   /* evita vazamentos e barras indesejadas */
      display: grid;
      place-items: center;
      padding: 24px;
      background: radial-gradient(1200px 600px at 20% 20%, #38bdf8 0%, rgba(56, 189, 248, 0) 55%),
                  radial-gradient(900px 500px at 80% 40%, #a78bfa 0%, rgba(167, 139, 250, 0) 60%),
                  #0f172a;
    }

    .cartao {
      width: min(560px, 100%);
      background: rgba(255, 255, 255, 0.92);
      border-radius: 16px;
      padding: 20px;
    }

    .cartao h1 {
      margin: 0 0 10px 0;
      font-size: 24px;
      letter-spacing: -0.02em;
    }

    .cartao p {
      margin: 0;
      opacity: 0.9;
    }
  </style>
</head>
<body>
  <main class="tela">
    <section class="cartao">
      <h1>Seção em tela cheia</h1>
      <p>A altura acompanha a área visível no mobile, evitando cortes quando a barra do navegador muda. O contêiner pode crescer caso o conteúdo aumente.</p>
    </section>
  </main>
</body>
</html>

Considerações sobre compatibilidade e comportamento em navegadores móveis

Navegadores móveis modernos tendem a lidar melhor com unidades dinâmicas, reduzindo inconsistências entre sistemas e fabricantes. A principal vantagem é alinhar a altura da seção ao espaço realmente visível, mesmo quando barras superiores e inferiores mudam durante a rolagem. Isso diminui situações em que elementos importantes ficam parcialmente fora da área útil.

Mesmo com melhorias, diferenças de implementação ainda podem existir, especialmente em versões antigas de navegadores. Por esse motivo, o comportamento deve ser entendido como uma estratégia para reduzir problemas típicos de mobile, e não como garantia absoluta de uniformidade em ambientes desatualizados. Ainda assim, 100dvh representa a abordagem mais alinhada ao modo como a interface do navegador altera o viewport em tempo real.

Conclusão

O uso de 100vh em celulares pode gerar cortes, sobreposições e saltos porque a interface do navegador altera a área visível sem que a medida estática acompanhe essas mudanças. A unidade 100dvh resolve esse tipo de problema ao representar a altura dinâmica do viewport, ajustando-se conforme barras e controles aparecem ou desaparecem. Em seções de impacto, modais e layouts em tela cheia, a troca para dvh tende a estabilizar a experiência.

Combinações como min-height: 100dvh ajudam quando o conteúdo pode crescer, mantendo a intenção de tela cheia sem limitar o layout. O controle de overflow pode refinar o resultado, evitando artefatos visuais, desde que não oculte conteúdo essencial. Com essas escolhas, interfaces móveis ficam mais consistentes e previsíveis ao lidar com o comportamento real do viewport.