Formulários de CPF responsivos funcionam em qualquer dispositivo quando combinam abordagem mobile-first, teclado numérico nativo (inputMode="numeric"), touch targets de pelo menos 48px e feedback visual claro. Com CSS e JavaScript simples, é possível criar uma experiência consistente do iPhone SE ao monitor 4K — sem perda de conversão.
Introdução
No Brasil, mais de 60% dos acessos à internet acontecem via dispositivos móveis. Isso significa que a maioria dos seus usuários vai preencher o campo de CPF em uma tela pequena, com teclado virtual e, possivelmente, com uma conexão instável. Se o formulário não for responsivo, a taxa de abandono será alta.
Responsividade vai além de fazer o layout caber na tela. Envolve escolher o teclado virtual correto, dimensionar botões para toque com o dedo, ajustar espaçamentos e garantir que o feedback visual funcione em qualquer resolução. As diretrizes de acessibilidade do W3C recomendam que todos os controles interativos tenham área de toque mínima de 44x44 pixels — um padrão que deve guiar qualquer formulário responsivo.
Princípios de design responsivo para formulários
Mobile-first
Comece projetando para mobile e depois adicione complexidade para telas maiores. Isso garante que a experiência base seja funcional mesmo no menor dispositivo.
Touch targets adequados
O tamanho mínimo recomendado para alvos de toque é 44x44 pixels (Apple) ou 48x48dp (Google). Inputs e botões devem respeitar esse mínimo.
Teclado virtual nativo
Use inputMode="numeric" para exibir apenas o teclado numérico em dispositivos móveis. Isso elimina a necessidade de o usuário trocar de teclado.
Viewport meta tag
Sempre inclua a meta tag de viewport para evitar zoom indesejado em dispositivos móveis.
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
Estrutura HTML do formulário
<form class="form-cpf" id="formCPF">
<div class="form-header">
<h2>Verificacao de CPF</h2>
<p>Informe seu CPF para continuar.</p>
</div>
<div class="form-body">
<div class="campo campo-cpf">
<label for="cpf">CPF</label>
<div class="input-group">
<input
type="text"
id="cpf"
inputmode="numeric"
placeholder="000.000.000-00"
maxlength="14"
autocomplete="off"
required
/>
<div class="input-status" id="inputStatus"></div>
</div>
<p class="feedback" id="feedback" role="alert"></p>
</div>
<div class="dados-resultado" id="dadosResultado" style="display: none;">
<div class="dado">
<span class="dado-label">Nome</span>
<span class="dado-valor" id="resultNome"></span>
</div>
<div class="dado">
<span class="dado-label">Nascimento</span>
<span class="dado-valor" id="resultNasc"></span>
</div>
<div class="dado">
<span class="dado-label">Genero</span>
<span class="dado-valor" id="resultGenero"></span>
</div>
</div>
</div>
<div class="form-footer">
<button type="submit" id="btnSubmit" disabled>Verificar CPF</button>
</div>
</form>
CSS responsivo com media queries
O CSS utiliza a abordagem mobile-first com breakpoints para tablet e desktop.
/* === Base (Mobile) === */
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: #f5f5f5;
color: #333;
padding: 16px;
}
.form-cpf {
background: #fff;
border-radius: 16px;
box-shadow: 0 2px 12px rgba(0,0,0,0.08);
overflow: hidden;
max-width: 100%;
}
.form-header {
padding: 20px 20px 0;
}
.form-header h2 { font-size: 1.3rem; margin-bottom: 4px; }
.form-header p { color: #666; font-size: 0.9rem; }
.form-body { padding: 20px; }
.campo { margin-bottom: 16px; }
.campo label {
display: block;
font-weight: 600;
font-size: 0.9rem;
margin-bottom: 6px;
}
.input-group { position: relative; }
.input-group input {
width: 100%;
padding: 14px 44px 14px 14px;
font-size: 1.1rem;
border: 2px solid #ddd;
border-radius: 10px;
outline: none;
transition: border-color 0.2s;
-webkit-appearance: none;
}
.input-group input:focus { border-color: #3498db; }
.input-group input.valido { border-color: #2ecc71; }
.input-group input.invalido { border-color: #e74c3c; }
.input-status {
position: absolute;
right: 14px;
top: 50%;
transform: translateY(-50%);
font-size: 1.2rem;
}
.feedback {
font-size: 0.85rem;
margin-top: 6px;
min-height: 20px;
}
.dados-resultado {
background: #f8f9fa;
border-radius: 10px;
padding: 16px;
}
.dado {
display: flex;
justify-content: space-between;
padding: 8px 0;
border-bottom: 1px solid #eee;
}
.dado:last-child { border-bottom: none; }
.dado-label { color: #666; font-size: 0.85rem; }
.dado-valor { font-weight: 600; font-size: 0.95rem; }
.form-footer { padding: 0 20px 20px; }
.form-footer button {
width: 100%;
padding: 16px;
font-size: 1.1rem;
font-weight: 600;
border: none;
border-radius: 10px;
background: #3498db;
color: #fff;
cursor: pointer;
transition: background 0.2s;
/* Touch target minimo de 48px */
min-height: 48px;
}
.form-footer button:hover { background: #2980b9; }
.form-footer button:disabled {
background: #bbb;
cursor: not-allowed;
}
/* === Tablet (768px+) === */
@media (min-width: 768px) {
body { padding: 40px; }
.form-cpf {
max-width: 520px;
margin: 0 auto;
}
.form-header { padding: 28px 28px 0; }
.form-header h2 { font-size: 1.5rem; }
.form-body { padding: 28px; }
.input-group input {
padding: 16px 48px 16px 16px;
font-size: 1.2rem;
}
.dados-resultado {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0 16px;
}
.dado:last-child {
grid-column: span 2;
}
.form-footer { padding: 0 28px 28px; }
}
/* === Desktop (1024px+) === */
@media (min-width: 1024px) {
body {
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
padding: 40px;
}
.form-cpf {
max-width: 560px;
box-shadow: 0 4px 24px rgba(0,0,0,0.12);
}
.form-header { padding: 32px 32px 0; }
.form-body { padding: 32px; }
.form-footer { padding: 0 32px 32px; }
.form-footer button:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(52,152,219,0.3);
}
}
JavaScript de validação e consulta
const cpfInput = document.getElementById('cpf');
const feedback = document.getElementById('feedback');
const inputStatus = document.getElementById('inputStatus');
const btnSubmit = document.getElementById('btnSubmit');
function maskCPF(value) {
const d = value.replace(/\D/g, '').slice(0, 11);
let r = '';
for (let i = 0; i < d.length; i++) {
if (i === 3 || i === 6) r += '.';
if (i === 9) r += '-';
r += d[i];
}
return r;
}
function validarCPF(cpf) {
if (cpf.length !== 11 || /^(\d)\1{10}$/.test(cpf)) return false;
let soma = 0;
for (let i = 0; i < 9; i++) soma += parseInt(cpf[i]) * (10 - i);
let resto = (soma * 10) % 11;
if (resto === 10) resto = 0;
if (resto !== parseInt(cpf[9])) return false;
soma = 0;
for (let i = 0; i < 10; i++) soma += parseInt(cpf[i]) * (11 - i);
resto = (soma * 10) % 11;
if (resto === 10) resto = 0;
return resto === parseInt(cpf[10]);
}
cpfInput.addEventListener('input', function () {
this.value = maskCPF(this.value);
const digits = this.value.replace(/\D/g, '');
if (digits.length < 11) {
this.className = '';
inputStatus.textContent = '';
feedback.textContent = '';
btnSubmit.disabled = true;
return;
}
if (validarCPF(digits)) {
this.className = 'valido';
inputStatus.textContent = '\u2713';
inputStatus.style.color = '#2ecc71';
feedback.textContent = '';
btnSubmit.disabled = false;
} else {
this.className = 'invalido';
inputStatus.textContent = '\u2717';
inputStatus.style.color = '#e74c3c';
feedback.textContent = 'CPF invalido.';
feedback.style.color = '#e74c3c';
btnSubmit.disabled = true;
}
});
document.getElementById('formCPF').addEventListener('submit', async function (e) {
e.preventDefault();
const digits = cpfInput.value.replace(/\D/g, '');
btnSubmit.disabled = true;
btnSubmit.textContent = 'Verificando...';
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 10000);
try {
const res = await fetch(`https://api.cpfhub.io/cpf/${digits}`, {
headers: {
'x-api-key': 'SUA_CHAVE_DE_API',
'Accept': 'application/json'
},
signal: controller.signal
});
clearTimeout(timeoutId);
const json = await res.json();
if (json.success) {
document.getElementById('resultNome').textContent = json.data.name;
document.getElementById('resultNasc').textContent = json.data.birthDate;
document.getElementById('resultGenero').textContent =
json.data.gender === 'M' ? 'Masculino' : 'Feminino';
document.getElementById('dadosResultado').style.display = 'block';
feedback.textContent = 'CPF verificado com sucesso!';
feedback.style.color = '#2ecc71';
} else {
feedback.textContent = 'CPF nao encontrado.';
feedback.style.color = '#e74c3c';
}
} catch (err) {
clearTimeout(timeoutId);
feedback.textContent = err.name === 'AbortError'
? 'Tempo esgotado. Tente novamente.'
: 'Erro na consulta. Tente novamente.';
feedback.style.color = '#e74c3c';
} finally {
btnSubmit.disabled = false;
btnSubmit.textContent = 'Verificar CPF';
}
});
Ajustes específicos por dispositivo
Mobile — teclado numérico
O atributo inputMode="numeric" exibe o teclado numérico nativo, sem letras. Isso é essencial para campos de CPF em dispositivos móveis.
Mobile — prevenir zoom no focus
Muitos navegadores mobile dão zoom quando o input tem font-size menor que 16px. Use no mínimo 16px no mobile para evitar esse comportamento.
@media (max-width: 767px) {
.input-group input {
font-size: 16px; /* Previne auto-zoom no iOS */
}
}
Tablet — layout em grade
Em tablets, aproveite a tela maior para exibir dados em duas colunas, economizando rolagem vertical.
Desktop — feedback de hover
Em desktop, adicione efeitos de hover nos botões e transições mais refinadas, já que o usuário tem um mouse e não um dedo.
Testando responsividade
Para garantir que o formulário funciona em todos os dispositivos, teste nos seguintes cenários:
Viewports essenciais
- 320px — iPhone SE (menor smartphone comum).
- 375px — iPhone 12/13/14.
- 768px — iPad em retrato.
- 1024px — iPad em paisagem / laptop pequeno.
- 1440px — desktop padrão.
Checklist de testes
- O teclado numérico aparece em mobile?
- O botão de submit é grande o suficiente para toque?
- O formulário não ultrapassa a largura da tela em nenhum viewport?
- O feedback de validação é legível em telas pequenas?
- A rolagem funciona quando o teclado virtual está aberto?
Teclado virtual e scroll
Em dispositivos móveis, quando o teclado virtual abre, ele pode cobrir o campo de input. Para garantir que o campo seja visível, use scrollIntoView no focus.
cpfInput.addEventListener('focus', function () {
// Aguardar o teclado abrir
setTimeout(() => {
this.scrollIntoView({ behavior: 'smooth', block: 'center' });
}, 300);
});
Perguntas frequentes
Como o inputMode="numeric" melhora a experiência em mobile?
O atributo inputMode="numeric" faz o dispositivo exibir o teclado numérico nativo ao focar no campo de CPF, eliminando a necessidade de o usuário trocar manualmente de teclado. Isso reduz erros de digitação e acelera o preenchimento — especialmente em smartphones com telas menores.
Por que o formulário não deve ter font-size abaixo de 16px no mobile?
Navegadores iOS e Android dão zoom automático em campos de input com font-size menor que 16px ao receber foco. Esse comportamento interrompe a experiência de preenchimento e pode deslocar o layout. Definir font-size: 16px no mobile evita esse zoom indesejado sem prejudicar a legibilidade.
Qual é o tamanho mínimo recomendado para botões em formulários mobile?
As diretrizes do Google recomendam 48x48dp e as da Apple, 44x44pt como área de toque mínima para qualquer elemento interativo. Para o botão de submit de um formulário de CPF, use min-height: 48px e width: 100% no mobile para garantir que usuários com dedos maiores não ativem o botão por engano ou deixem de ativá-lo por área insuficiente.
Como garantir que os dados do CPF apareçam corretamente após a consulta à API?
Após a chamada à API CPFHub.io, popule os campos com os valores retornados em json.data.name, json.data.birthDate e json.data.gender. A resposta chega em ~900ms — tempo suficiente para exibir um indicador de carregamento (spinner ou skeleton) antes de substituir pelo conteúdo real.
Conclusão
Responsividade em formulários de CPF não é um luxo — é uma necessidade. Com a maioria dos acessos vindo de dispositivos móveis, um formulário que não funciona bem em telas pequenas perde conversões. As chaves para um formulário responsivo são: abordagem mobile-first, teclado numérico nativo, touch targets adequados e feedback visual claro em qualquer resolução.
A integração com a API da CPFHub.io retorna nome, data de nascimento e gênero em ~900ms — tempo baixo o suficiente para uma experiência fluida em qualquer dispositivo. Teste seu formulário nos breakpoints críticos (320px, 375px, 768px e 1024px) e garanta que nenhum usuário abandone por dificuldade de preenchimento.
Crie sua conta gratuita em cpfhub.io e faça até 50 consultas por mês sem cartão de crédito. Quando seu volume crescer, o plano Pro parte de R$149/mês — e o excedente custa apenas R$0,15 por consulta adicional.
CPFHub.io
Pronto para integrar a API?
50 consultas gratuitas para testar agora. Sem cartão de crédito. Acesso imediato à documentação.
Sobre a redação
Redação CPFHub.io
Time editorial especializado em APIs de CPF, identidade digital e compliance no mercado brasileiro. Produzimos guias técnicos, análises regulatórias e tutoriais sobre LGPD e KYC para desenvolvedores e líderes de produto.



