iPhone dá zoom ao tocar no campo: a regra dos 16 pixels e a gambiarra a evitar
Entenda por que o Safari do iPhone amplia a página quando o campo tem letra menor que 16 pixels, corrija no CSS sem bloquear o zoom e encontre os campos culpados com um script.
Na página de checkout, a pessoa toca no campo "CEP" e a tela inteira aproxima sozinha. O botão "Calcular frete" sai para fora da área visível, o texto fica cortado nas laterais e ela precisa fazer o gesto de pinça para voltar. Ninguém pediu esse zoom. No Android, o mesmo formulário não faz isso.
A resposta curta: o Safari do iPhone amplia a página ao focar um campo cujo texto tem menos de 16 pixels. A correção é deixar input, select e textarea com font-size de pelo menos 16 pixels. Não resolva com maximum-scale=1 ou user-scalable=no no viewport: isso tira o zoom de quem precisa dele.
Por que o iPhone faz isso
É um comportamento de acessibilidade do navegador. Se o texto do campo é pequeno demais para ler confortavelmente enquanto se digita, o Safari amplia a área do campo para a pessoa enxergar o que escreve. A intenção é boa. O efeito colateral é que a página fica ampliada depois que o foco sai, e o layout que você desenhou para caber na tela deixa de caber.
Na prática, a maioria dos navegadores no iPhone usa o mesmo motor do Safari, então o Chrome no iPhone costuma se comportar igual. No Android, os navegadores em geral não fazem esse zoom automático, e por isso o problema passa despercebido por quem testa só lá ou no desktop.
De onde vem a letra pequena
Quase nunca alguém escreve "14px no input" de propósito. O tamanho pequeno chega por caminhos indiretos:
- Controles de formulário não herdam a fonte do corpo por padrão. O navegador aplica um estilo próprio a eles, geralmente menor que 16 pixels. Se o seu CSS não define a fonte do campo, ela fica no padrão do navegador.
- Raiz reduzida. O projeto define
html { font-size: 87.5%; }para ter 14 pixels como base, e o campo comfont-size: 1remherda os 14. - Componente de biblioteca. O framework de interface usa um tamanho "compacto" de 14 pixels nos campos.
- Media query para telas pequenas que reduz a fonte "para caber mais", justamente no celular.
Como corrigir sem tirar o zoom de ninguém
- Descubra quais campos estão abaixo de 16 pixels (script mais abaixo).
- Defina no CSS global um tamanho mínimo para todos os controles de texto.
- Faça os controles herdarem a família da fonte do site, para o campo não destoar.
- Revise componentes de bibliotecas que sobrescrevem o tamanho.
- Confira o meta viewport e remova qualquer bloqueio de zoom.
- Teste num iPhone de verdade, ou no simulador de iOS do Xcode, que roda o Safari móvel.
input,
select,
textarea {
font-family: inherit;
font-size: max(16px, 1rem);
}
O max() garante os 16 pixels mesmo que a raiz do site seja menor, e respeita uma raiz maior se a pessoa aumentou o tamanho de fonte no sistema ou no navegador. Ele é suportado pelos navegadores atuais. Se você usa uma biblioteca de componentes, aplique a regra com especificidade suficiente para vencer o estilo dela, ou use a variável de tema que a biblioteca oferece para isso.
O meta viewport correto continua sendo o simples:
<meta name="viewport" content="width=device-width, initial-scale=1">
A gambiarra que você vai encontrar na internet
A solução mais copiada é acrescentar maximum-scale=1 (às vezes junto de user-scalable=no) ao meta viewport. Ela some com o zoom no foco, mas o preço é alto: em vários navegadores, principalmente no Android, a pessoa perde também o zoom de pinça. Quem tem baixa visão e amplia a tela para ler o valor do frete fica sem essa saída.
As diretrizes WCAG têm um critério específico sobre redimensionar texto, e bloquear o zoom é uma das falhas mais comuns apontadas em auditoria. Mesmo que o Safari moderno ignore parte dessas instruções para preservar a acessibilidade, você não controla todos os navegadores que vão abrir o seu site. Corrigir a fonte resolve a causa, e o bloqueio só esconde o sintoma.
Outra gambiarra é deixar o campo com 16 pixels e aplicar transform: scale() para ele parecer menor. Funciona visualmente, mas complica alinhamento, área de toque e cálculo de posição do cursor. Se o design insiste em letra pequena no campo, vale a conversa: 16 pixels é um tamanho de leitura confortável no celular, e o campo é justamente onde a pessoa precisa ler com atenção.
Como achar os campos culpados
Cole no console, em cada página com formulário. Rode com a largura de celular no modo responsivo, porque media queries podem mudar o tamanho:
[...document.querySelectorAll('input, select, textarea')]
.filter((el) => el.type !== 'hidden')
.map((el) => ({ el, tamanho: parseFloat(getComputedStyle(el).fontSize) }))
.filter(({ tamanho }) => tamanho < 16)
.forEach(({ el, tamanho }) => console.log(tamanho + 'px', el.name || el.id, el));
No checkout do exemplo, o resultado apontou "cep", "numero" e "complemento" com 14 pixels, vindos de uma classe campo-compacto criada para alinhar os três na mesma linha. A correção foi subir para 16 pixels e deixar o "complemento" ir para a linha de baixo no celular.
O modo responsivo do desktop serve para achar os campos, mas não reproduz o zoom. A confirmação final precisa de um iPhone ou do simulador. Se você tem um Mac, o Safari permite inspecionar a página aberta no aparelho conectado, o que ajuda a ver o tamanho calculado ali mesmo.
Junto com o zoom, confira o teclado
Quando o campo está na metade de baixo da tela, o zoom costuma vir acompanhado de outro problema: o teclado virtual cobre o botão de enviar. As duas coisas aparecem no mesmo teste, e a segunda está em teclado virtual que cobre o botão. Aproveite também para conferir se cada campo abre o teclado certo, numérico para CEP e com arroba para e-mail, como explica inputs HTML5 que ajudam.
E se você está montando o CSS do zero, comece pelo celular: CSS mobile-first mostra como definir a base para a tela pequena, onde 16 pixels nos campos é o ponto de partida natural.
Erros comuns
- Bloquear o zoom no meta viewport. O pulo some, e junto vai o zoom de pinça de quem precisa ampliar para ler.
- Corrigir só o
input.selectetextareatambém disparam o zoom, e o campo de estado no endereço continua pulando. - Confiar no modo responsivo do desktop. Ele não reproduz o comportamento do Safari móvel e o problema chega ao cliente.
- Reduzir a fonte numa media query para celular. A tela que mais precisa de letra legível fica com a menor.
- Esquecer componentes de terceiros. O seletor de data ou o campo de busca da biblioteca mantém 14 pixels e continua ampliando a página.
- Usar
transform: scale()para disfarçar. O campo parece menor, mas o alinhamento e a área de toque ficam imprevisíveis.
Checklist
- Todos os
input,selectetextareavisíveis têm pelo menos 16 pixels de fonte. - A regra global usa
max(16px, 1rem)ou equivalente. - O meta viewport não tem
maximum-scalenemuser-scalable=no. - Componentes de bibliotecas foram conferidos com o script.
- Nenhuma media query reduz a fonte dos campos no celular.
- O formulário foi testado num iPhone real ou no simulador.
Pegue um iPhone, abra o formulário mais importante do seu sistema e toque no último campo. A página ficou do mesmo tamanho ou você precisou fazer pinça para enxergar o botão de novo?
Referência: https://developer.mozilla.org/docs/Web/HTML/Element/input