O que Árabe RTL para Web faz?
Um checklist para páginas em árabe que são lidas naturalmente, se posicionam corretamente em 375px e nunca bagunçam números, URLs ou palavras em inglês. Aplique cada seção que tocar na tarefa e, em seguida, execute o checklist final.
1. Direção e idioma
- Elemento raiz:
<html lang="ar" dir="rtl">, escrito no HTML (não adicionado por JavaScript) para que a primeira renderização já seja RTL. - Não substitua
dirpor CSSdirection: rtl. O atributo também controla bidi, controles de formulário e leitores de tela. - Um bloco em inglês dentro de uma página em árabe:
<p lang="en" dir="ltr">. Texto digitado por usuários (nomes, comentários, chat):dir="auto".
2. Layout com propriedades lógicas
Left/right físicos nunca se invertem. Use propriedades lógicas para que uma única folha de estilo funcione em ambas as direções.
| Evite | Use |
|---|---|
margin-left, padding-right | margin-inline-start, padding-inline-end |
left: 0, right: 0 | inset-inline-start: 0, inset-inline-end: 0 |
text-align: left | text-align: start |
border-left | border-inline-start |
border-top-left-radius | border-start-start-radius |
float: left | float: inline-start |
- Flexbox e grid já seguem
dir: em RTL,flex-direction: rowcomeça na direita. Nunca adicionerow-reversepara "corrigir" RTL. transform: translateX(),background-positione deslocamentos de box-shadow são físicos. Inverta-os com:dir(rtl)ou[dir="rtl"]quando necessário.- Tailwind:
ms-*,me-*,ps-*,pe-*,start-*,end-*,text-starte as variantesrtl:/ltr:.
3. Fontes web árabes
- Escolha uma família projetada para árabe (IBM Plex Sans Arabic, Noto Naskh Arabic, Noto Sans Arabic, Tajawal, Cairo, Almarai, Readex Pro). Mantenha faces decorativas como Aref Ruqaa apenas para títulos.
- Hospede você mesmo arquivos WOFF2: sem requisições de terceiros, funciona offline, nada vaza para um CDN de fontes. Verifique a licença (OFL permite auto-hospedagem).
- Use
font-display: swape divida arquivos árabes e latinos comunicode-range, para que cada página baixe apenas o que usa:
@font-face { font-family: 'Plex'; font-weight: 400; font-display: swap;
src: url(plex-400-ar.woff2) format('woff2');
unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+200C-200E, U+FB50-FDFF, U+FE70-FEFC; }
@font-face { font-family: 'Plex'; font-weight: 400; font-display: swap;
src: url(plex-400-lat.woff2) format('woff2');
unicode-range: U+0000-00FF, U+2000-206F; }
body { font: 400 17px/1.75 'Plex', 'Segoe UI', Tahoma, sans-serif; }
- O árabe precisa de uma altura de linha maior (1.6 a 1.8) para diacríticos e descendentes, e um tamanho ligeiramente maior do que o texto latino.
- Nunca use
letter-spacingem árabe (quebra a junção de letras). Semtext-transform, sem itálico falso. Evitetext-align: justifyem colunas estreitas. - Não estique palavras com tatweel (U+0640). Isso quebra pesquisa e copiar-colar.
4. Bidi: números, URLs e inglês dentro do árabe
O algoritmo bidi do Unicode reordena caracteres neutros próximos a números e texto latino. Dois bugs clássicos em um parágrafo RTL:
- Telefone
+966 55 123 4567mostra seus grupos de dígitos na ordem inversa:4567 123 55 +966. - Intervalo de tempo
10:00 - 12:00é exibido como12:00 - 10:00.
Correções:
<bdi>em torno de valores inseridos de direção desconhecida:مرحبًا <bdi>${userName}</bdi>، أهلًا بك.dir="ltr"em valores que são sempre LTR:<span dir="ltr">+966 55 123 4567</span>, URLs, e-mails, caminhos de arquivo, IBANs,<code dir="ltr">,<pre dir="ltr">.- CSS para padrões repetidos:
.num, .code { unicode-bidi: isolate; }. Note que<bdi>isola por padrão. - Inputs para e-mail, URL e telefone:
<input type="email" dir="ltr">. - Onde a marcação é impossível (título de documento, notificações, strings simples), envolva com isoladores Unicode: FSI U+2068 ... PDI U+2069, ou LRI U+2066 ... PDI para texto sabidamente LTR.
5. Dígitos: um sistema por página
- Escolha latinos
0-9ou árabe-indianos٠-٩(U+0660 a U+0669) e use-os em toda a página, incluindo tabelas, gráficos e datas. - Misturar confunde os leitores (uma tabela com ambos parece um erro), quebra pesquisa ("15" não corresponde a "١٥"), ordenação e copiar-colar em planilhas.
- Dígitos persas
۰-۹(U+06F0 a U+06F9) são pontos de código diferentes. Não os misture. - Os padrões de
Intldiferem por localidade e versão do motor: no Node 24,ar-SAformata com dígitos árabe-indianos enquantoarsimples dá latinos. Defina o sistema de numeração explicitamente:new Intl.NumberFormat('ar-SA-u-nu-latn')ou'ar-SA-u-nu-arab'. - Com dígitos árabe-indianos, o separador decimal é
٫(U+066B) e o separador de milhares é٬(U+066C). - Armadilha real: um ponto médio (U+00B7) usado como separador ao lado de dígitos árabe-indianos parece o zero árabe-indiano (U+0660), que também é um pontinho. "12, separador, 3" é então lido como "1203". Separe com a vírgula árabe «،», uma barra ou espaçamento extra (CSS
gap).
6. Pontuação árabe
- Use
،(U+060C),؛(U+061B) e؟(U+061F), não,;?. O ponto final e!são compartilhados. - Sem espaço antes de um sinal de pontuação, um espaço depois: «كيف حالك؟» e não «كيف حالك ؟».
- Escolha um estilo de citação («...» ou "...") por página.
7. Ícones e espelhamento
Espelhe ícones que mostram direção ou sequência: setas de voltar e avançar, chevrons em listas e breadcrumbs, steppers e direção de progresso, "enviar", indentação de texto e ícones de lista.
Não espelhe: logotipos e marcas, controles de mídia (play, rebobinar, avançar rápido), relógios e temporizadores, marcas de verificação, fotos e ícones que contenham letras latinas ou dígitos.
:dir(rtl) .icon-dir { transform: scaleX(-1); } /* classe opt-in, nunca global */
8. Entrada de números de teclados árabes
- Prefira
<input inputmode="decimal" autocomplete="off">em vez detype="number". O valor de um input number só é válido com dígitos ASCII, então dígitos árabe-indianos podem retornar como string vazia; ele também adiciona spinners. - Usuários digitam
٠-٩, o separador decimal árabe٫e, às vezes, dígitos persas. Normalize antes deNumber():
function parseArabicNumber(raw) {
const s = String(raw ?? '').trim()
.replace(/[٠-٩]/g, (d) => d.charCodeAt(0) - 0x0660)
.replace(/[۰-۹]/g, (d) => d.charCodeAt(0) - 0x06F0)
.replace(/٫/g, '.')
.replace(/٬/g, '');
if (s === '') return null; // Number('') é 0, então verifique vazio primeiro
const n = Number(s);
return Number.isFinite(n) ? n : NaN;
}
parseArabicNumber('٩٥٫٥'); // 95.5
- Decida como uma
,digitada é tratada (marca decimal ou separador de milhares) e documente isso. - Mostre mensagens de validação em árabe, defina
aria-invalide associe a mensagem comaria-describedby. - Ordene nomes árabes com
new Intl.Collator('ar').compare. Para pesquisa, normalize formas alef (أ إ آ para ا), remova tashkeel e tatweel tanto na consulta quanto nos dados.
9. Testes
- Teste com largura de 375px (e 320px se possível). Confirme que
document.documentElement.scrollWidth <= innerWidth. - Teste palavras longas em árabe com letras ligadas, como «والمستشفيات» ou «باستخداماتها», em títulos e botões. Use
overflow-wrap: anywhereem títulos e cards, emin-width: 0em filhos de flex e grid. - Use conteúdo real em árabe com inglês e números misturados, não lorem ipsum.
- Verifique no Safari no iOS e Chrome no Android, além de zoom de 200% e ordem de foco do teclado (Tab move da direita para a esquerda).
10. A pegadinha do [hidden]
O atributo hidden é apenas um display: none do agente de usuário. Qualquer regra do autor como .card { display: flex } o sobrescreve, então el.hidden = true silenciosamente para de funcionar. Adicione isso à folha de estilo base:
[hidden] { display: none !important; }
Checklist final
-
<html lang="ar" dir="rtl">no código fonte - Nenhuma propriedade física left/right deixada no novo CSS
- Fonte árabe auto-hospedada,
font-display: swap, divisão porunicode-range - Números de telefone, URLs, códigos e nomes de usuário isolados
- Um sistema de dígitos; nenhum ponto médio ao lado de dígitos árabe-indianos
- Pontuação árabe, sem espaço antes dela
- Apenas ícones direcionais espelhados
- Inputs numéricos aceitam
٠-٩e٫ - Sem rolagem horizontal em 375px; palavras longas quebram
-
[hidden] { display: none !important; }presente