Codificação UTF-8
UTF significa Unicode Transformation Format. O '8' indica que blocos de 8 bits são usados para representar um caractere.
Todo caractere que você digita em uma página web — uma simples letra latina, um é acentuado, um π grego, o símbolo de euro € ou um emoji — precisa ser convertido em bytes antes de poder ser armazenado ou enviado pela rede. As regras que mapeiam caracteres em bytes são chamadas de codificação de caracteres. Unicode é o catálogo universal que atribui a cada caractere um número único (um code point), e UTF-8 é a codificação que escreve esses code points como bytes. Como autor HTML, acertar a codificação é o que separa você do temido "mojibake" — saída corrompida como é onde deveria aparecer um é. Esta página explica o que é UTF-8, como declará-lo, como inserir qualquer caractere Unicode pelo seu code point e inclui uma tabela de referência com os intervalos Unicode mais comuns.
Capítulos relacionados: Entidades HTML lista os atalhos nomeados como
©e&, e Conjuntos de Caracteres HTML explica como Unicode, UTF-8 e o charset do documento se relacionam entre si.
O Que É UTF-8?
O Formato de Transformação Unicode de 8 bits, chamado UTF-8, é uma codificação de caracteres de largura variável capaz de codificar todos os 1.114.112 code points válidos do Unicode com um a quatro bytes de 8 bits. O número "8" significa que blocos de 8 bits são usados pelo UTF para representar um caractere.
Desde 2009, o UTF-8 é a codificação dominante para a World Wide Web e hoje é utilizado pela esmagadora maioria de todas as páginas web.
Declarando a Codificação no HTML
Um navegador não consegue adivinhar de forma confiável qual codificação seus bytes utilizam, por isso você deve sempre informá-lo. No HTML5, isso é feito com uma única tag <meta>, colocada como o primeiro elemento dentro de <head> (dentro dos primeiros 1024 bytes do documento):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>UTF-8 example</title>
</head>
<body>
<p>Prices: €10 · Greek letter: π · Smiley: 😀</p>
</body>
</html>Salve o arquivo como UTF-8 no seu editor e declare <meta charset="UTF-8">, e os dois estarão em acordo. Se o <meta charset> estiver ausente, o navegador recorre a uma suposição (historicamente windows-1252 para muitas localidades ocidentais, ou uma heurística), o que é exatamente como o texto corrompido aparece. Saiba mais no capítulo sobre a Tag HTML <meta>.
Por Que a Declaração Deve Vir Cedo
Um navegador não espera o arquivo HTML completo chegar antes de começar a trabalhar — ele começa a decodificar os bytes em caracteres assim que o primeiro bloco é recebido. Para isso, ele precisa escolher uma codificação antes de ter lido o documento inteiro. A especificação HTML, portanto, exige que <meta charset> apareça dentro dos primeiros 1024 bytes, para que o navegador possa encontrá-lo durante esse passe inicial.
Se você declarar a codificação tarde demais (por exemplo, após um longo bloco de comentários ou conteúdo), o navegador já terá decodificado os bytes anteriores usando sua suposição de fallback. Esses bytes serão mal interpretados e, no momento em que a declaração tardia for encontrada, a página pode precisar de um reparse completo — ou simplesmente exibir texto corrompido. Manter <meta charset="UTF-8"> como o primeiro filho de <head> garante que ele seja visto a tempo.
Usando Code Points Unicode no HTML
Você não precisa digitar um caractere exótico diretamente para utilizá-lo. Qualquer code point Unicode pode ser inserido com uma referência numérica de caractere, em decimal (&#NNNN;) ou hexadecimal (&#xHHHH;). Muitos caracteres comuns também têm uma entidade nomeada fácil de lembrar.
Por exemplo, o símbolo de euro (code point U+20AC) pode ser escrito de três formas equivalentes:
<p>Euro: € € €</p>
<!-- all three render as: € -->O mesmo funciona para letras de qualquer script, como a letra grega maiúscula sigma (U+03A3):
<p>Greek sigma: Σ Σ Σ</p>
<!-- renders as: Σ -->As referências numéricas são úteis para caracteres difíceis de digitar ou para ser explícito e evitar ambiguidade de codificação. Para a lista completa de atalhos nomeados (como ©, &, <), veja Entidades HTML.
Referências Numéricas de Caracteres
Tanto &#NNN; (decimal) quanto &#xHHHH; (hexadecimal) identificam um caractere pelo seu code point Unicode — o mesmo número atribuído pelo Unicode, apenas escrito em duas bases diferentes. O x após &# é o que marca os dígitos como hexadecimais. Por fazerem referência diretamente ao code point, as referências numéricas funcionam para todos os caracteres Unicode, mesmo aqueles sem entidade nomeada.
Por exemplo, o coração preto cheio (code point U+2764, decimal 10084) não tem uma entidade nomeada amplamente suportada, mas você ainda pode escrevê-lo:
<p>Heart: ❤ and the same in hex: ❤</p>
<!-- both render as: ❤ -->Os zeros à esquerda são opcionais, então ❤ e ❤ são equivalentes. O hexadecimal é conveniente porque corresponde à notação U+.... que você vê nos gráficos Unicode.
Dica: Para uma visão geral de como codificações, code points e o charset do documento se encaixam, veja Conjuntos de Caracteres HTML.
Quantos Bytes um Caractere Ocupa
UTF-8 é de largura variável: caracteres com code points pequenos ocupam menos bytes, portanto o texto em inglês simples permanece compacto enquanto ainda permite todo o intervalo Unicode. O valor do code point sozinho determina quantos bytes o UTF-8 usa para ele, de acordo com quatro intervalos inclusivos:
| Intervalo de code point | Decimal | Bytes | Caractere de exemplo |
|---|---|---|---|
| U+0000 – U+007F | 0 – 127 | 1 byte | A (U+0041) |
| U+0080 – U+07FF | 128 – 2047 | 2 bytes | é (U+00E9), π (U+03C0) |
| U+0800 – U+FFFF | 2048 – 65535 | 3 bytes | € (U+20AC), 中 (U+4E2D) |
| U+10000 – U+10FFFF | 65536 – 1114111 | 4 bytes | 😀 (U+1F600) |
- 1 byte (U+0000–U+007F). Esses bytes são idênticos aos valores ASCII originais, razão pela qual qualquer arquivo ASCII puro já é um UTF-8 válido.
- 2 bytes (U+0080–U+07FF). Cobre a maioria das letras latinas com acentos, além do grego, cirílico, hebraico e árabe.
- 3 bytes (U+0800–U+FFFF). Inclui a maioria dos outros scripts modernos, junto com muitos símbolos e caracteres CJK (chinês, japonês, coreano). Este intervalo vai até U+FFFF, inclusive.
- 4 bytes (U+10000–U+10FFFF). Abrange scripts menos comuns, caracteres históricos e emojis, até o code point Unicode válido mais alto, U+10FFFF.
Por Que o UTF-8 Dominou a Web
Codificações mais antigas como ASCII, Latin-1 (ISO-8859-1) e Windows-1252 usavam um único byte por caractere, portanto podiam representar no máximo 256 caracteres. Isso é suficiente para um idioma, mas uma página não pode misturar, digamos, francês, russo e japonês em um único arquivo. O UTF-8 resolve isso cobrindo todos os caracteres do Unicode enquanto permanece compatível com ASCII — os primeiros 128 code points mapeiam para os mesmos bytes únicos. Essa compatibilidade, somada à sua compactação para texto em inglês, é o motivo pelo qual o UTF-8 substituiu as codificações legadas de byte único e tornou-se o padrão da web.
A Marca de Ordem de Byte (BOM)
Alguns editores adicionam alguns bytes invisíveis ao início de um arquivo UTF-8, chamados de marca de ordem de byte (BOM).
Você Deve Usar um BOM no HTML?
No UTF-8, o BOM é a sequência de três bytes EF BB BF. Ele pode funcionar como sinal de que um arquivo está codificado em UTF-8, mas para HTML é desnecessário e deve ser evitado: sua declaração <meta charset="UTF-8"> já informa a codificação, e um BOM indevido pode causar bugs sutis (por exemplo, espaço em branco inesperado antes de <!DOCTYPE>, ou quebra de scripts PHP que emitem saída). Se o seu editor oferecer a escolha, salve como "UTF-8 sem BOM."
Referência de Intervalos Unicode
A lista abaixo mostra alguns blocos Unicode comumente usados, cada um indicado pelo seu intervalo de code point em decimal e hexadecimal. A coluna de exemplo mostra um glifo do bloco.
| Códigos de Caractere | Decimal | Hexadecimal | Exemplo |
|---|---|---|---|
| C0 Controls and Basic Latin | 0-127 | 0000-007F | A B c 7 ? |
| C1 Controls and Latin-1 Supplement | 128-255 | 0080-00FF | é ñ ü © ÷ |
| Latin Extended-A | 256-383 | 0100-017F | ā Œ ş ž ł |
| Latin Extended-B | 384-591 | 0180-024F | ƀ Ɛ ǎ ǔ |
| Spacing Modifiers | 688-767 | 02B0-02FF | ˆ ˜ ˘ |
| Diacritical Marks | 768-879 | 0300-036F | combining accents |
| Greek and Coptic | 880-1023 | 0370-03FF | α β π Σ Ω |
| Cyrillic Basic | 1024-1279 | 0400-04FF | Д Ж и я ё |
| Cyrillic Supplement | 1280-1327 | 0500-052F | Ҡ ҩ Ӂ |
| Latin Extended Additional | 7680-7935 | 1E00-1EFF | ḅ ẁ ẞ ṩ |
| General Punctuation | 8192-8303 | 2000-206F | — … ‹ › † |
| Currency Symbols | 8352-8399 | 20A0-20CF | € £ ¥ ₽ ₹ |
| Letterlike Symbols | 8448-8527 | 2100-214F | ™ ℃ № ℅ |
| Arrows | 8592-8703 | 2190-21FF | ← ↑ → ↓ ↔ |
| Mathematical Operators | 8704-8959 | 2200-22FF | ∑ √ ∞ ≠ ≤ |
| Box Drawings | 9472-9599 | 2500-257F | ─ │ ┌ ┐ └ |
| Block Elements | 9600-9631 | 2580-259F | ░ ▒ ▓ █ |
| Geometric Shapes | 9632-9727 | 25A0-25FF | ■ ● ▲ ◆ ◇ |
| Miscellaneous Symbols | 9728-9983 | 2600-26FF | ☀ ☂ ★ ☎ ✿ |
| Dingbats | 9984-10175 | 2700-27BF | ✂ ✈ ✉ ✏ ❤ |
| Emoji (Emoticons) | 128512-128591 | 1F600-1F64F | 😀 😂 😍 🙏 😎 |