你还在手写 RTL 语言的样式吗?

53 阅读4分钟

背景:

由于我们做的是沙特业务,日常开发跟阿语(RTL语言)打交道比较多,在此记录一下如何高效开发镜像语言的样式。

如果你是一个全新的项目,首推肯定是用 CSS 的逻辑属性

CSS 逻辑属性(Logical Properties & Values)

  1. 概念

CSS 逻辑属性(Logical Properties & Values) 是为了解决 LTR / RTL / 纵向书写 等多书写模式问题而设计的。你可以把它理解为:

不再关心 left / right / top / bottom,而是关心 start / end / block / inline

物理方向逻辑方向
left / rightinline-start / inline-end
top / bottomblock-start / block-end
  • inline:文字流方向(LTR / RTL 会变)
  • block:垂直方向(通常是上 → 下)
<html dir="rtl">

浏览器会自动把 inline-start 映射到 right


  1. 最常用的逻辑属性清单(🔥必会)

1️⃣ margin / padding

margin-inline-start
margin-inline-end
margin-block-start
margin-block-end

padding-inline-start
padding-inline-end
padding-block-start
padding-block-end

👉 等价替代:

传统逻辑
margin-leftmargin-inline-start
margin-rightmargin-inline-end
margin-topmargin-block-start
margin-bottommargin-block-end

2️⃣ border

border-inline-start
border-inline-end
border-block-start
border-block-end

border-inline-start-width
border-inline-start-style
border-inline-start-color

3️⃣ inset(替代 top / right / bottom / left)

inset-inline-start
inset-inline-end
inset-block-start
inset-block-end
/* 代替 left: 0 */
inset-inline-start: 0;

4️⃣ size(width / height)

inline-size   /* ≈ width */
block-size    /* ≈ height */

min-inline-size
max-inline-size
min-block-size
max-block-size

5️⃣ text / alignment

text-align: start | end;
float: inline-start | inline-end;
clear: inline-start | inline-end;

其他属性可以到 CSS MDN 查询


  1. 简写属性(非常实用)

margin-inline: 8px 16px;
padding-block: 12px;
border-inline: 1px solid #ddd;
inset: 0; /* 全逻辑版 top/right/bottom/left */

  1. 书写模式相关(进阶)

writing-mode

writing-mode: horizontal-tb; /* 默认 */
writing-mode: vertical-rl;
writing-mode: vertical-lr;

direction

direction: ltr | rtl;

⚠️ direction 只影响 inline 方向


  1. 浏览器兼容性(重点)

总体结论

主流浏览器已全面可用,可直接上生产

详细支持情况(2025)

属性类别ChromeFirefoxSafariEdge
margin / padding 逻辑69+66+12.1+79+
border 逻辑69+66+14+79+
inset-*87+66+14.1+87+
inline-size / block-size69+66+12+79+
text-align: start/end1+1+1+1+
float: inline-*87+66+14+87+

📌 移动端:

  • Android Chrome ✅
  • iOS Safari 12+ ✅

  1. 是否需要 PostCSS / Polyfill?

结论

  • 不需要 polyfill
  • 不需要 postcss-rtlcss

👉 除非:

  • 你要兼容 IE11(已淘汰)
  • 或维护大量 legacy CSS

  1. 真实项目推荐写法(你可以直接用)

.card {
  padding-inline: 16px;
  padding-block: 12px;

  border-inline-start: 4px solid var(--primary);

  inset-inline-start: 0;
  inline-size: 100%;
}
<html dir="ltr">
<html dir="rtl">

零 JS,零构建成本。


  1. 什么时候“不要”用逻辑属性?

❌ 如果你要:

  • 精确控制某一侧(永远是左)
  • Canvas / 绝对定位坐标
  • 老组件库未适配

这种情况下可以 物理属性 + rtlcss


如果你是老项目,使用大量 left / right,且短期内无法全面改成逻辑属性,则可以考虑使用 postcss-rtlcss

postcss-rtlcss

  1. 概念

postcss-rtlcss 是一个 PostCSS 插件,用于在构建阶段自动生成 RTL(Right-to-Left)样式,常见于支持 阿拉伯语 / 希伯来语 等从右到左书写的语言场景。


一句话理解

把 LTR 的 CSS 自动转换成 RTL 版本,不用你手写两套样式。


它解决什么问题?

在国际化(i18n)项目中:

  • LTR(英文 / 中文)
.box {
  margin-left: 16px;
  text-align: left;
}
  • RTL(阿拉伯语)
.box {
  margin-right: 16px;
  text-align: right;
}

👉 postcss-rtlcss 可以 自动完成这种转换


能自动转换哪些东西?

LTRRTL
margin-leftmargin-right
padding-leftpadding-right
leftright
float: leftfloat: right
text-align: lefttext-align: right
border-leftborder-right
background-position: leftright

⚠️ 不会动逻辑属性(如 margin-inline-start),因为它们本身就是方向无关的。


  1. 基本使用方式

1️⃣ 安装

npm install postcss postcss-rtlcss --save-dev

2️⃣ PostCSS 配置

postcss.config.js
module.exports = {
  plugins: [
    require('postcss-rtlcss')()
  ]
}

3️⃣ 生成 RTL CSS(常见做法)

方式一:输出两份 CSS
style.css       // LTR
style.rtl.css   // RTL
require('postcss-rtlcss')({
  // 生成 .rtl.css
  addPrefixToSelector: (selector) => `[dir="rtl"] ${selector}`
})

  1. 在 Vite / Webpack 中使用

Vite 示例

// vite.config.ts
import rtlcss from 'postcss-rtlcss'

export default {css: {postcss: {plugins: [rtlcss()]
    }
  }
}

Webpack 示例

{
  loader: 'postcss-loader',
  options: {
    postcssOptions: {
      plugins: [
        require('postcss-rtlcss')()
      ]
    }
  }
}

  1. 控制哪些规则“不要翻转”

使用注释

/* rtl:ignore */
.box {
  margin-left: 20px;
}

/* rtl:begin:ignore */
.box {
  left: 0;
}
/* rtl:end:ignore */

和 CSS 逻辑属性的关系(很重要)

❌ 传统方式(需要 RTL CSS)

margin-left: 16px;

✅ 现代推荐(不需要 rtlcss)

margin-inline-start: 16px;

👉 如果你全面使用逻辑属性

  • 不需要 postcss-rtlcss
  • 浏览器会自动适配 dir="rtl"