Dev.to WebDev 🛠 Dev 👁 0 📖 2 min read

Como funcionam as "letras diferentes": Unicode na prática com JavaScript

Se você já viu um nick tipo 𝓙𝓸𝓪𝓸 ou uma bio em 𝗻𝗲𝗴𝗿𝗶𝘁𝗼 no Instagram, talvez tenha pensado que é uma fonte instalada no celular. Não é. São caracteres Unicode diferentes que parecem letras estilizadas, e por isso funciona

Se você já viu um nick tipo 𝓙𝓸𝓪𝓸 ou uma bio em 𝗻𝗲𝗴𝗿𝗶𝘁𝗼 no Instagram, talvez tenha pensado que é uma fonte instalada no celular. Não é. São caracteres Unicode diferentes que parecem letras estilizadas, e por isso funcionam em qualquer app que aceite texto.

Eu mantenho o letrasdiferente.online, um gerador de letras diferentes para copiar e colar. Neste post mostro o que acontece por baixo dos panos e os cuidados que aprendi construindo a ferramenta.

O bloco "Mathematical Alphanumeric Symbols"

O Unicode tem um bloco (U+1D400 a U+1D7FF) criado para notação matemática: negrito, itálico, script, fraktur, double-struck, monoespaçado e outros. Cada estilo é um alfabeto completo, com code points próprios.

  • A é U+0041
  • 𝐀 (negrito matemático) é U+1D400
  • 𝐚 é U+1D41A

Ou seja: para "converter" uma letra basta somar um deslocamento ao code point.

Convertendo texto em JavaScript

const ESTILOS = {
  negrito:      { upper: 0x1D400, lower: 0x1D41A },
  italico:      { upper: 0x1D434, lower: 0x1D44E },
  monoespacado: { upper: 0x1D670, lower: 0x1D68A },
};

// Alguns estilos têm "buracos": a letra já existia em outro bloco
const EXCECOES = {
  italico: { h: 'ℎ' }, // ℎ
};

function estilizar(texto, estilo) {
  const { upper, lower } = ESTILOS[estilo];
  return [...texto].map((ch) => {
    const fixo = EXCECOES[estilo]?.[ch];
    if (fixo) return fixo;
    const c = ch.codePointAt(0);
    if (c >= 65 && c <= 90) return String.fromCodePoint(upper + c - 65);
    if (c >= 97 && c <= 122) return String.fromCodePoint(lower + c - 97);
    return ch;
  }).join('');
}

console.log(estilizar('Letras Diferentes', 'negrito'));
// 𝐋𝐞𝐭𝐫𝐚𝐬 𝐃𝐢𝐟𝐞𝐫𝐞𝐧𝐭𝐞𝐬

Repare no mapa EXCECOES: em itálico, o h não existe no bloco matemático porque o Unicode já tinha o ℎ (U+210E, constante de Planck). Script e fraktur têm vários buracos assim. Se você esquecer disso, aparece um quadrado vazio no meio da palavra.

Cuidado 1: .length engana

Esses caracteres ficam fora do BMP, então cada um ocupa dois code units em UTF-16:

'𝐀'.length;       // 2
[...'𝐀'].length;  // 1

Se você mostra um contador de caracteres (bio do Instagram, nick de jogo), conte com [...texto].length ou Intl.Segmenter, senão o limite real fica errado.

Cuidado 2: acentos

Não existe 𝐜̧ pronto nem 𝐚̃ no bloco matemático. Um truque é decompor o texto com normalize('NFD'), estilizar só a letra base e manter o acento combinante (U+0327, U+0303...). Nem todo app renderiza bem, então teste onde vai usar.

Cuidado 3: acessibilidade e busca

Leitores de tela podem ler 𝐋𝐞𝐭𝐫𝐚𝐬 letra por letra ou como "mathematical bold capital L". E texto estilizado não aparece em buscas comuns. Use em nomes, títulos curtos e decoração, não em frases longas ou informação importante.

Conclusão

A ideia é simples: um deslocamento de code point. O trabalho real está nas exceções, nos acentos e na contagem de caracteres.

Se quiser testar dezenas de estilos de uma vez (cursiva, gótica, bolhas, texto pequeno) com contador por plataforma e suporte a ç, ã, é, use o gerador de letras diferentes. Para nick de jogo tem a página de nick Free Fire com símbolos.

Dúvidas sobre Unicode? Deixa nos comentários. 👇

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.