web 适配RTL语言的方案

Web 适配 RTL 语言方案

RTL(Right-To-Left)语言包括阿拉伯语、希伯来语、波斯语(法尔西语)、乌尔都语等。本文系统梳理 Web 端适配 RTL 的完整方案。


一、基础设置

1.1 HTML dir 属性

<!-- 全局设置 -->
<html dir="rtl" lang="ar">

<!-- 局部覆盖(某块内容强制 LTR) -->
<div dir="ltr">...</div>

1.2 CSS direction 属性

/* 全局 */
:root {
  direction: rtl;
}

/* 局部覆盖 */
.code-block {
  direction: ltr;
  text-align: left;
}

1.3 <meta>lang 配合

<html lang="ar" dir="rtl">
<meta charset="UTF-8">

推荐:优先使用 HTML dir 属性,而非纯 CSS,因为浏览器会根据 dir 自动处理表单、光标方向等行为。


二、CSS 逻辑属性(推荐方案)

CSS 逻辑属性(Logical Properties)是适配 RTL 的最佳实践,无需为 RTL 单独写覆盖样式。

2.1 方向无关的属性对照表

2.2 示例

/* ❌ 传统写法:需要为 RTL 单独覆盖 */
.nav-icon {
  margin-right: 8px;
}
[dir="rtl"] .nav-icon {
  margin-right: 0;
  margin-left: 8px;
}

/* ✅ 逻辑属性写法:自动适配 LTR/RTL */
.nav-icon {
  margin-inline-end: 8px;
}

三、Flexbox 与 Grid 的自动镜像

Flex 和 Grid 布局天然支持 RTL,flex-direction: row 在 RTL 下会自动变为从右到左排列。

.toolbar {
  display: flex;
  flex-direction: row; /* RTL 下自动从右到左 */
  gap: 12px;
}

注意flex-direction: row-reverse 会与 RTL 叠加,产生 LTR 效果,通常不是预期行为,慎用。


四、图标与图像的镜像处理

4.1 需要镜像的图标

方向性图标(箭头、返回、前进、菜单展开等)在 RTL 下需要水平翻转:

/* 方案一:CSS transform */
[dir="rtl"] .icon-arrow,
[dir="rtl"] .icon-back,
[dir="rtl"] .icon-forward {
  transform: scaleX(-1);
}

/* 方案二:使用 logical 版本的 SVG */

4.2 不需要镜像的图标

  • 时钟、问号、感叹号、勾选等无方向性图标不需要镜像

  • Logo、品牌图标通常不镜像

4.3 Google Material Icons 的 RTL 支持

Google 的图标系统为部分图标提供了 .material-icons-rtl 的镜像标注,可参考其文档。


五、字体处理

5.1 为 RTL 语言单独指定字体

:lang(ar) {
  font-family: 'Cairo', 'Noto Sans Arabic', sans-serif;
}

:lang(he) {
  font-family: 'Assistant', 'Heebo', sans-serif;
}

5.2 字号调整

阿拉伯字体的视觉大小通常与拉丁字体不一致,需微调:

:lang(ar) {
  font-size: 1.1em; /* 阿拉伯字母在相同 font-size 下视觉偏小 */
  line-height: 1.8;  /* 阿拉伯字体行高需更大 */
}

六、使用 CSS 变量统一管理

:root {
  --spacing-start: 16px;
  --spacing-end: 8px;
}

[dir="rtl"] {
  --spacing-start: 8px;
  --spacing-end: 16px;
}

.item {
  padding-inline-start: var(--spacing-start);
  padding-inline-end: var(--spacing-end);
}

七、框架层面的方案

7.1 Tailwind CSS

Tailwind v3+ 支持 RTL variant:

<!-- 在 tailwind.config.js 中开启 -->
<!-- { future: { hoverOnlyWhenSupported: true }, ... } -->

<div class="ml-4 rtl:ml-0 rtl:mr-4">...</div>

<!-- 或使用逻辑属性 utility(Tailwind v3.3+) -->
<div class="ms-4">...</div>  <!-- margin-inline-start -->
<div class="me-4">...</div>  <!-- margin-inline-end -->
<div class="ps-4">...</div>  <!-- padding-inline-start -->

7.2 Bootstrap 5

Bootstrap 5 内置 RTL 支持,只需引入 RTL 版本的 CSS:

<link rel="stylesheet" href="bootstrap.rtl.min.css">

7.3 styled-components / Emotion(CSS-in-JS)

import { css } from 'styled-components';

const rtl = (ltr, rtlValue) => css`
  ${ltr}: ${ltrValue};
  [dir="rtl"] & {
    ${ltr}: initial;
    ${rtl}: ${rtlValue};
  }
`;

// 使用 stylis-plugin-rtl 或 postcss-rtl 自动转换

7.4 PostCSS 自动转换

使用 postcss-logical@csstools/postcss-logical 自动将物理属性转为逻辑属性:

// postcss.config.js
module.exports = {
  plugins: [
    require('postcss-logical')(),
    require('postcss-dir-pseudo-class')()
  ]
};

八、JavaScript 动态处理

8.1 检测文档方向

const isRTL = document.documentElement.dir === 'rtl'
  || document.documentElement.lang === 'ar';

// 或使用 getComputedStyle
const dir = getComputedStyle(document.documentElement).direction;

8.2 动态切换方向

function setDirection(lang) {
  const rtlLangs = ['ar', 'he', 'fa', 'ur'];
  const dir = rtlLangs.includes(lang) ? 'rtl' : 'ltr';
  document.documentElement.setAttribute('dir', dir);
  document.documentElement.setAttribute('lang', lang);
}

8.3 处理第三方组件的方向

// 如 date-picker、rich-text editor 等
import { useEffect } from 'react';

useEffect(() => {
  if (isRTL) {
    editorInstance.setDirection('rtl');
  }
}, [isRTL]);

九、常见陷阱与注意事项


十、测试建议

  1. 浏览器 DevTools:临时在 Console 执行 document.dir = 'rtl' 快速预览

  2. Chrome 扩展:使用 RTL Tester 一键切换

  3. 真实内容测试:使用真实的阿拉伯语/希伯来语文本,而非 Lorem Ipsum

  4. 视觉回归测试:在 CI 中加入 RTL 截图对比(Chromatic、Percy 等)

  5. 键盘导航测试:Tab 顺序应与视觉顺序一致


十一、国际化(i18n)框架配合

// 使用 Intl API 检测语言方向
const locale = new Intl.Locale('ar');
console.log(locale.textInfo.direction); // "rtl"

参考资源


web 适配RTL语言的方案
https://blog.fullsize.cn/2026/03/19/notion/web-gua-pei-rtl-yu-yan-de-fang-an/
作者
fullsize
发布于
2026年3月19日
许可协议