
📱 Máscara de input de telefone em JavaScript: 4 métodos com código
Os utilizadores introduzem números de telefone de todas as maneiras: alguns começam com 8, outros com +7, uns escrevem os dígitos sem espaços, outros acrescentam espaços a cada dois dígitos. A base de dados acaba numa confusão. Os gestores perdem tempo a fazer chamadas e metade dos números revela-se inválida. Um cenário familiar para qualquer pessoa que já tenha adicionado um formulário de contacto a um website.
Uma máscara de introdução resolve este problema por completo: o utilizador fica fisicamente impedido de introduzir um número no formato errado. Escreve os dígitos e estes aparecem automaticamente nos sítios certos, enquanto parênteses e hífens surgem por si. Sem erros, sem frustração.
Abaixo estão quatro formas de adicionar uma máscara de telefone a um campo: desde HTML5 nativo, sem JavaScript, até uma biblioteca completa com bandeiras para todos os países. Com código que pode copiar e colar no seu projeto.
💡 Resumo rápido:
- A máscara mais simples usa o atributo
patternetype="tel", sem qualquer JavaScript, funciona em qualquer navegador - Se precisa de bandeiras de países e formatação internacional, use
intl-tel-input, a solução mais popular no GitHub - Se precisa de uma biblioteca para telefones, datas, cartões e outras máscaras, opte por
IMask.js - Se quer escrever uma máscara manualmente sem adicionar dependências, JavaScript puro resolve em 30 linhas
O que é uma máscara de introdução e porque é mais importante do que a validação
Uma máscara de introdução é uma string modelo que controla o que o utilizador vê e pode escrever num campo de formulário. Ao contrário da validação, que verifica os dados após o envio e mostra um erro, uma máscara atua em tempo real durante a introdução: impede que se escreva uma letra onde deveria estar um dígito e insere automaticamente parênteses, hífens e espaços.
A diferença é fundamental. A validação diz «cometeu um erro» e o utilizador já está frustrado e pode abandonar. Uma máscara guia-o passo a passo: os erros são simplesmente impossíveis. Para números de telefone isto é crítico, porque existem dezenas de opções de formatação. Só um número russo pode ser escrito como +7 999 123-45-67, como 8(999)1234567 ou como +7(999)123-45-67, e estas são apenas três variantes entre muitas. Sem uma máscara, cada utilizador inventa o seu próprio formato e a base de dados transforma-se num depósito de lixo.
Método 1: HTML5, type="tel" e pattern
O caminho mais fácil: dispensar completamente o JavaScript. Os navegadores modernos suportam type="tel" e o atributo pattern, que valida a introdução de dados contra uma expressão regular no envio do formulário.
Adicione o campo ao seu markup. O código pode ser inserido em qualquer template HTML: Contact Form 7, um formulário nativo do WordPress ou markup personalizado.
1 <input 2 type="tel" 3 id="phone" 4 name="phone" 5 pattern="\+7\s?[\(]?\d{3}[\)]?\s?\d{3}[\-]?\d{2}[\-]?\d{2}" 6 placeholder="+7 (999) 123-45-67" 7 title="Enter the number in the format +7 (999) 123-45-67" 8 required 9 >
Vamos analisar o que está a acontecer aqui. type="tel" mostra um teclado numérico em dispositivos móveis em vez do teclado normal, tornando a introdução do telefone mais conveniente. pattern define uma expressão regular que permite várias variantes: com ou sem espaços, com ou sem parênteses à volta do indicativo de área. title mostra uma dica ao passar o rato e required impede o envio do formulário com o campo vazio.
A vantagem: zero dependências, funciona em qualquer navegador. Para uma landing page simples, isto é suficiente.
Mas isto não é uma máscara verdadeira. Os parênteses e hífens não aparecem automaticamente; o utilizador tem de os escrever manualmente. O pattern só é acionado no envio do formulário. Se precisa de formatação em tempo real durante a introdução, avance para os próximos métodos.
Método 2: intl-tel-input, formato internacional com bandeiras de países
intl-tel-input é a biblioteca JavaScript mais popular para introdução de telefones. Fornece um campo com uma lista suspensa de bandeiras de países, formatação automática para corresponder ao modelo nacional e validação do número. Em junho de 2026, a biblioteca tinha mais de 7.800 estrelas no GitHub e a versão atual é a 29.
Instale a biblioteca via npm (npm i intl-tel-input) ou CDN. O código abaixo é para JavaScript vanilla; também existem componentes prontos para React, Vue, Angular e Svelte.
1 <!-- In the <head> of the page --> 2 <link 3 rel="stylesheet" 4 href="https://cdn.jsdelivr.net/npm/intl-tel-input@29/build/css/intlTelInput.css" 5 > 6 <script src="https://cdn.jsdelivr.net/npm/intl-tel-input@29/build/js/intlTelInput.min.js"></script>
O elemento de input e a inicialização vão no template onde precisa do campo. Para um tema WordPress, adicione o script via wp_enqueue_script no functions.php e coloque o markup no template apropriado.
1 <input type="tel" id="phone"> 2 3 <script> 4 const input = document.querySelector("#phone"); 5 const iti = intlTelInput(input, { 6 initialCountry: "ru", 7 separateDialCode: true, 8 utilsScript: "https://cdn.jsdelivr.net/npm/intl-tel-input@29/build/js/utils.js" 9 }); 10 </script>
initialCountry: "ru" define a bandeira russa por defeito. separateDialCode: true move o código do país para fora do campo de input: quando o utilizador muda a bandeira, o código é inserido automaticamente. utilsScript carrega utilitários de formatação; sem eles a biblioteca ainda funciona, mas os números não são formatados para corresponder ao padrão do país selecionado.
O objeto devolvido por intlTelInput() fornece vários métodos úteis. iti.getNumber() devolve o número no formato internacional E.164, iti.isValidNumber() verifica a validade e iti.setNumber("9991234567") define o valor programaticamente. Para o Contact Form 7 vai precisar de um script personalizado: encontre o campo .wpcf7-tel e anexe-lhe o intlTelInput.
Vantagem: uma solução internacional completa com formatação automática, bandeiras, validação e integrações com frameworks. Desvantagem: a biblioteca pesa cerca de 40 KB (gzip), o que é excessivo para uma landing page simples com um único campo.
Método 3: IMask.js, uma máscara universal sem jQuery
IMask.js é uma biblioteca de máscaras madura escrita em JavaScript puro: sem jQuery, sem outras dependências. Suporta máscaras para telefones, datas, números, moedas e modelos dinâmicos. É útil quando precisa de diferentes tipos de máscaras num site: um telefone num formulário de contacto, uma data num calendário e um montante numa calculadora. A versão atual é a 7.1.
Instale via npm (npm i imask) ou inclua o CDN:
1 <script src="https://unpkg.com/imask"></script>
Uma máscara de telefone em três linhas. O código pode ir numa tag <script> no footer ou num ficheiro JS separado no seu tema.
1 const phoneInput = document.getElementById('phone'); 2 const maskOptions = { 3 mask: '+{7} (000) 000-00-00' 4 }; 5 IMask(phoneInput, maskOptions);
Sintaxe da máscara: +{7} é um prefixo fixo que o utilizador não pode editar. 0 representa qualquer dígito de 0 a 9. Pode adicionar complexidade: tornar o indicativo de área opcional ou mudar dinamicamente a máscara quando o país muda, usando o parâmetro dispatch.
O IMask devolve um objeto com acesso ao valor bruto: maskRef.unmaskedValue dar-lhe-á os dígitos simples 79991234567, exatamente o que quer guardar na base de dados. O método maskRef.value devolve a string formatada para exibição. O problema clássico está resolvido: os dígitos vão para o backend, enquanto o utilizador vê um número bem formatado.
Vantagem: uma biblioteca para todos os casos, valores brutos prontos a usar, sem dependências. Desvantagem: para um único campo de telefone é mais fácil usar intl-tel-input com bandeiras; o IMask brilha realmente em formulários com três a cinco tipos de campos diferentes.
Método 4: JavaScript puro, uma máscara artesanal
Se não quiser adicionar uma biblioteca apenas para um campo, escreva a máscara em JavaScript puro. O código abaixo trata cada tecla premida e insere automaticamente parênteses e hífens à medida que os dígitos são introduzidos.
Coloque o script no mesmo template onde está o campo de input ou inclua-o como um ficheiro separado. Para WordPress, use wp_enqueue_script com a flag true (no footer).
1 document.getElementById('phone').addEventListener('input', function (e) { 2 let value = e.target.value.replace(/\D/g, ''); 3 4 if (value.length > 11) { 5 value = value.slice(0, 11); 6 } 7 8 let formatted = '+7 ('; 9 if (value.length > 1) formatted += value.slice(1, 4); 10 if (value.length > 4) formatted += ') ' + value.slice(4, 7); 11 if (value.length > 7) formatted += '-' + value.slice(7, 9); 12 if (value.length > 9) formatted += '-' + value.slice(9, 11); 13 14 e.target.value = formatted; 15 });
O evento input é disparado a cada alteração no campo: colar da área de transferência, autocorreção, eliminação. A primeira linha replace(/\D/g, '') remove tudo exceto dígitos: letras e caracteres especiais desaparecem instantaneamente. Depois, o script corta os dígitos em excesso (um número russo tem 11 dígitos, incluindo o código do país) e constrói a string formatada: código do país +7, indicativo de área de três dígitos entre parênteses, três dígitos, dois, dois, separados por hífens.
Antes de usar isto num site ativo, adicione duas melhorias. Primeiro: ao apagar dígitos no meio do número, o cursor pode saltar para o fim do campo; guarde a posição do cursor via selectionStart e restaure-a após a formatação. Segundo: para números de outros países (a Bielorrússia tem 12 dígitos, o Cazaquistão tem 11 dígitos com um código diferente) a lógica torna-se mais complexa e, nesse ponto, o intl-tel-input é plenamente justificado.
Vantagem: 30 linhas, controlo total, zero kilobytes de dependências. Desvantagem: a máscara é feita à medida para um formato; para projetos multinacionais, o código vai inchar.
⁉️🤔 Perguntas frequentes
Porque é que uma máscara é melhor do que uma simples validação?
A validação é acionada após o envio do formulário: o utilizador vê um erro e tem de voltar atrás para o corrigir. Uma máscara funciona durante a introdução, tornando um formato inválido fisicamente impossível. Menos frustração, menos formulários abandonados. Para números de telefone isto é crítico: os erros no número são uma das razões mais comuns para os utilizadores abandonarem um formulário.
Como guardo dígitos simples na base de dados, sem parênteses e hífens?
Todas as bibliotecas neste artigo fornecem valores brutos: o
intl-tel-inputtem um métodogetNumber()que devolve+79991234567, oIMask.jstem uma propriedadeunmaskedValueque devolve79991234567. Antes de enviar os dados para o servidor, obtenha o valor bruto e guarde-o. Mostre a string formatada apenas na interface. Em formulários WordPress, adicione um campo oculto<input type="hidden" name="phone_raw">e preencha-o via JavaScript antes do envio.
A máscara funciona em dispositivos móveis?
Sim, todos os quatro métodos funcionam corretamente em iOS e Android.
type="tel"faz aparecer o teclado numérico, o que é conveniente. Em Android mais antigo (versões abaixo da 6), o eventoinputpode comportar-se de forma diferente com a autocorreção; teste em dispositivos reais. Ointl-tel-inpute oIMask.jssão testados pelos seus programadores em navegadores móveis e não causam problemas.
Posso usar uma máscara com o Contact Form 7?
O CF7 gera campos com classes
.wpcf7-tel. Escreva um script que encontre este campo por seletor e lhe anexe ointl-tel-inputou oIMask. No envio do formulário, o CF7 obtém o valor diretamente do campo, pelo que a biblioteca tem de ter tempo para o formatar previamente. Se usar valores brutos, intercete o eventowpcf7submite substitua os dados num campo oculto.
O que devo fazer com números de diferentes países no mesmo site?
Use o
intl-tel-input: o utilizador seleciona uma bandeira e a máscara muda automaticamente para corresponder ao formato do país escolhido. Para geotargeting, pode definirinitialCountry: "auto"e a biblioteca detetará o país por IP através de um serviço externo. Se houver apenas dois ou três países e o seu orçamento de dependências for mínimo, escreva duas máscaras em JavaScript puro e alterne entre elas com um botão de rádio «Rússia / Cazaquistão» acima do campo.
Qual o método a escolher para a sua tarefa
A escolha resume-se a três perguntas: quantos campos existem no site, precisa de bandeiras de países e quão crítico é o tamanho do pacote.
Um único formulário simples numa landing page: comece com o pattern do HTML5. Rápido, sem JavaScript e, no telemóvel, o teclado muda para numérico. Se o site aceitar números internacionais, o intl-tel-input cobrirá tudo: bandeiras, formatação automática, validação. Para uma loja online ou SaaS, este é o padrão.
Várias máscaras diferentes no site (telefone, data, montante, cartão): o IMask.js dar-lhe-á uma API para todos os campos e não requer jQuery. Está a construir um projeto pessoal e quer controlo total: 30 linhas de JavaScript puro tratarão dos números russos sem uma única dependência.
Teste como a máscara funciona num site ativo: introduza um número com letras, cole da área de transferência, tente apagar alguns dígitos no meio. O campo deve comportar-se de forma previsível em qualquer cenário. Que método escolheu para o seu projeto? Partilhe nos comentários.



