Criando um validador de senha em JavaScript
Como montar um medidor de força de senha com HTML, CSS e JavaScript puro, validando maiúsculas, minúsculas, números, caracteres especiais e tamanho mínimo com expressões regulares.
Validar senha parece complicado até você abrir o código e ver que é basicamente uma lista de regras sendo checadas uma por uma. Aqui a base é um HTML e um CSS simples, só para dar suporte visual, e o JavaScript inteiro construído do zero, regra por regra, até chegar numa barra de progresso que mostra o quanto da senha já está válida.
O que o validador precisa fazer
O objetivo final: conforme o usuário digita, quatro regras vão sendo marcadas como cumpridas ou não, e uma barra de progresso preenche proporcionalmente. Quando as quatro regras estão satisfeitas, a senha é considerada válida e dá para liberar o que vier depois, enviar o formulário, habilitar um botão, o que fizer sentido pro seu caso.
As quatro regras:
- Pelo menos uma letra maiúscula e uma minúscula.
- Pelo menos um número.
- Pelo menos um caractere especial.
- Pelo menos seis caracteres no total.
Selecionando os elementos
Primeiro, o campo de senha e a barra de progresso, os dois elementos que o JavaScript vai manipular o tempo todo:
const passwordInput = document.querySelector(".password");
const progressBar = document.querySelector(".progress .bar");E o gatilho de tudo: sempre que o usuário soltar uma tecla dentro do campo, a validação roda de novo:
passwordInput.addEventListener("keyup", checkPassword);Calculando a força regra por regra
Dentro de checkPassword, a lógica começa com a força zerada e vai somando um ponto para cada regra satisfeita:
function checkPassword() {
let strength = 0;
const value = passwordInput.value;
strength += renderRule(".lower-upper-case", value.match(/[a-z].*[A-Z]|[A-Z].*[a-z]/));
strength += renderRule(".one-number", value.match(/[0-9]/));
strength += renderRule(".one-special-char", value.match(/[!@#$%^&*_]/));
strength += renderRule(".min-char", value.length >= 6);
const pct = Math.floor((strength / 4) * 100);
progressBar.style.width = `${pct}%`;
// liberar envio, mostrar botão, etc, quando pct === 100
}A primeira regra usa duas expressões regulares unidas por | (ou), uma checando minúscula seguida de maiúscula em qualquer ordem e outra checando o inverso, porque não importa qual vem primeiro, só importa que as duas apareçam. As outras duas regras usam expressões bem mais diretas: um intervalo de números de 0 a 9 e uma lista de caracteres especiais entre colchetes. A última regra nem precisa de regex, é só conferir o length da string.
A função que pinta a regra de verde ou vermelho
renderRule recebe a classe do elemento da regra e o resultado da verificação, e faz duas coisas: muda a cor da bolinha na tela e devolve 1 ou 0 para entrar na soma da força:
function renderRule(ruleClass, valid) {
const ruleArea = document.querySelector(ruleClass);
ruleArea.querySelector(".valid").style.backgroundColor = valid ? "green" : "red";
return valid ? 1 : 0;
}Cada regra no HTML tem uma classe própria (.lower-upper-case, .one-number, .one-special-char, .min-char) e, dentro dela, um elemento .valid que é a bolinha colorida. match retorna um resultado truthy quando encontra a expressão regular no texto e null quando não encontra, então dá para usar o retorno direto como o valid da função, sem precisar de um if separado para cada regra.
A barra de progresso
Com quatro regras no total, cada uma vale 25% da barra. O cálculo é simples: força dividida pelo total de regras, vezes 100, arredondado para baixo com Math.floor para garantir que só bate 100% quando as quatro regras realmente estão completas:
const pct = Math.floor((strength / 4) * 100);
progressBar.style.width = `${pct}%`;Arredondar para baixo evita que 99.9% apareça como barra cheia sem a senha estar de fato válida.
Resultado
Com isso, o campo vai ganhando cor nas regras conforme o usuário digita e a barra de progresso acompanha em tempo real. A partir do pct === 100, dá para tomar qualquer decisão: liberar um botão de envio, desbloquear o próximo passo de um cadastro, mostrar uma mensagem de sucesso. A lógica em si, checar regra por regra e somar uma força, é a parte que vale levar para qualquer linguagem ou framework, independente de como a interface é montada.
Se quiser testar esse validador com senhas realmente fortes em vez de digitar na mão, criei um gerador de senha segura que usa criptografia real do navegador para gerar combinações aleatórias de letras, números e símbolos.
Leia também
- Gerenciamento de estado no React: Context API, Zustand ou Redux?2 de setembro de 2026 · 5 min
- React: quando (e como) criar um custom hook31 de agosto de 2026 · 4 min
- Acessibilidade na prática: o básico que todo site deveria ter30 de agosto de 2026 · 4 min
- TypeScript: generics e utility types na prática29 de agosto de 2026 · 4 min