O que realmente é uma palavra pontilhada

Uma palavra pontilhada não é um conceito mágico da computação. É simplesmente um texto em que os caracteres são substituídos por pontos ou sublinhados, geralmente para mascarar informação sensível ou para criar campos de preenchimento em formulários. Em ambientes de desenvolvimento web, isso aparece como placeholder ou como texto formatado com caracteres de substituição. O objetivo é claro: esconder o conteúdo real sem perder a noção do tamanho ou da estrutura do dado.

Eu trabalho com interfaces e sistemas de formulário há bastante tempo. Já vi gente construir soluções absurdamente complexas para algo que na verdade é trivial quando você entende o que precisa ser feito. Vou explicar como funciona na prática, com exemplos que eu realmente uso no dia a dia.

Implementação prática de palavra pontilhada

O caminho mais direto em HTML e CSS envolve usar pseudo-elementos ou caracteres Unicode específicos. Vamos começar pelo básico. Você tem um input ou span e quer que o conteúdo seja exibido como pontos. Um exemplo simples usando CSS:
.mascarado::after {
  content: "•••••••";
  color: transparent;
  text-shadow: 0 0 0 #000;
}
Esse método funciona bem para senhas e campos curtos. Mas ele tem uma limitação séria: o número de pontos é fixo. Se o conteúdo variar em tamanho, você perde a correspondência visual. Para resolver isso, a abordagem mais robusta usa a propriedade -webkit-text-security, disponível em navegadoresWebKit:
.mascarado {
  -webkit-text-security: disc;
  font-family: monospace;
}
Isso faz com que cada caractere digitado apareça como um disco (ponto). O problema? O suporte varia entre navegadores. No Firefox, por exemplo, você precisa usar circle ou square como fallback. E em alguns dispositivos móveis, especialmente Android mais antigo, o comportamento é inconsistente.

Um detalhe que muita gente perde: a propriedade só funciona se o campo tiver type="password" ou se estiver dentro de um container que o navegador reconhece como campo de segurança. Soltar isso num div comum e esperar que funcione é perda de tempo.

Problemas reais que eu encontrei

Num projeto recente, precisei implementar palavra pontilhada para um campo de CPF em um sistema de dados sensíveis. A exigência era que os pontos correspondessem exatamente à quantidade de dígitos, incluindo os pontos e traços da formatação padrão (111.222.333-00). O truque com -webkit-text-security sozinho não resolve porque ele mascara caractere por caractere, sem respeitar a formatação visual dos separadores. Minha solução foi dividir o campo em três spans separados: um para a parte numérica, outro para os separadores fixos, e um terceiro para aplicar a máscara pontilhada apenas nos dígitos. Usei JavaScript para sincronizar a digitação entre os spans e garantir que os pontos e traços permanecessem visíveis enquanto os números eram mascarados. O resultado ficou com cerca de 60 linhas de código, mas funcionou em todos os navegadores que precisávamos cobrir.

Se você está apenas mascarando senhas curtas, esse nível de complexidade é desnecessário. Mas para campos com formatação específica, considere desde o início que a solução simples provavelmente vai falhar.

Quando a palavra pontilhada não é a melhor opção

Mascaramento visual não é segurança. Isso precisa estar claro. Se o objetivo é proteger dados sensíveis, confiar apenas na apresentação com palavra pontilhada é um erro comum. Alguém com acesso ao código-fonte ou às inspecionar elementos pode ver o valor real em segundos. Para campos que realmente precisam de sigilo, o correto é garantir que o valor nunca chegue ao navegador não criptografado. Alternativamente, se você precisa de algo mais leve e compatível com todos os navegadores sem depender de propriedades específicas deWebKit, considere usar uma camada de sobreposição com caracteres Unicode de substituição gerados dinamicamente via JavaScript. A lógica é simples: capture o evento de digitação, conte os caracteres e gere uma string de pontos correspondente. Leva menos de 20 linhas e não depende de nada experimental.
function atualizarPontilhado(input, output) {
  const valor = input.value;
  output.textContent = '•'.repeat(valor.length);
}
Esse método também permite controle fino sobre o que é exibido. Você pode misturar pontos com caracteres visíveis nas posições que quiser, algo impossível com as soluções puramente em CSS. A desvantagem é que requer JavaScript ativo, o que pode ser um problema em ambientes restritos ou para usuários com scripts desabilitados.

Referências úteis

Para quem quer se aprofundar no assunto, a documentação oficial do MDN sobre -webkit-text-security e os guias de acessibilidade para campos mascarados são bons pontos de partida. Também recomendo testar sempre em dispositivos reais, não apenas no desktop, já que o comportamento em telas touch pode diferir significativamente do esperado.