关于 css-i18n
CSS Internationalization 是用于适配从右向左布局的技能,帮助开发者识别方向性样式,在适用处改用逻辑属性,并检查 LTR 与 RTL 布局。
主要功能
- 01识别 CSS 样式方案
- 02将物理属性映射为逻辑属性
- 03逐项判断方向性样式
- 04验证 LTR 与 RTL 布局
适用场景
- 01为阿拉伯语或希伯来语适配布局
- 02检查 CSS Modules 或 Tailwind 样式
- 03转换方向相关的内联样式
- 04检查共享组件的 RTL 行为
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ globalize-now/ globalize-skills --skill css-i18n安装后在 Claude Code 中输入/css-i18n确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
metadata.jsonreferences/css-modules-and-vanilla.mdtailwind.md详细介绍
CSS 国际化
将物理 CSS 属性(left、right、margin-left)转换为逻辑属性(inset-inline-start、margin-inline-start),让布局在 RTL 环境中自动翻转。
**为什么这很重要:**物理属性以视口为基准,而非文本方向。即使设置了 dir="rtl",margin-left: 16px 仍会留在左侧,破坏阿拉伯语、希伯来语及其他 RTL 文字的视觉流。逻辑属性会自动遵循文本方向。
第 1 步:检测样式方案
确定项目编写 CSS 的方式。这将决定要扫描哪些模式,以及要参考哪个文件。
按以下顺序检查:
- Tailwind CSS — 存在
tailwind.config.*,或 CSS 文件中出现@tailwind/@import "tailwindcss"。参见references/tailwind.md。 - CSS Modules — 文件名符合
*.module.css或*.module.scss。参见references/css-modules-and-vanilla.md。 - CSS-in-JS — 从
styled-components、@emotion/styled、@emotion/css、stitches、vanilla-extract导入。遵循与原生 CSS 相同的属性映射,但使用驼峰命名(参见第 2 步的内联样式部分)。 - 原生 CSS — 普通的
.css或.scss文件。参见references/css-modules-and-vanilla.md。 - 内联样式 — JSX/TSX 中的
style={{ marginLeft: ... }}。遵循第 2 步中的驼峰命名映射。
项目通常会采用多种方案。扫描所有适用的方案。
第 2 步:扫描并转换
逐个处理文件。对每个文件,查找物理方向属性并转换为对应的逻辑属性。
始终转换(高置信度)
在几乎所有情况下,转换以下属性都是安全的:
Margin 和 padding
| 物理属性 | 逻辑属性 |
|---|---|
margin-left | margin-inline-start |
margin-right | margin-inline-end |
padding-left | padding-inline-start |
padding-right | padding-inline-end |
带有明确左右值的简写属性:
/* Before — 4-value shorthand: top right bottom left */
margin: 0 24px 0 16px;
/* After — use longhand logical properties */
margin-block: 0;
margin-inline-start: 16px;
margin-inline-end: 24px;
左右值相同时,使用 inline 简写:
/* Before */
padding-left: 16px;
padding-right: 16px;
/* After */
padding-inline: 16px;
定位
| 物理属性 | 逻辑属性 |
|---|---|
left | inset-inline-start |
right | inset-inline-end |
top | inset-block-start |
bottom | inset-block-end |
设置四边时,使用 inset 简写:
/* Before */
top: 0; right: 0; bottom: 0; left: 0;
/* After */
inset: 0;
文本对齐
| 物理属性 | 逻辑属性 |
|---|---|
text-align: left | text-align: start |
text-align: right | text-align: end |
text-align: center 已与方向无关,无需更改。
浮动和清除
| 物理属性 | 逻辑属性 |
|---|---|
float: left | float: inline-start |
float: right | float: inline-end |
clear: left | clear: inline-start |
clear: right | clear: inline-end |
边框
| 物理属性 | 逻辑属性 |
|---|---|
border-left | border-inline-start |
border-right | border-inline-end |
border-left-color | border-inline-start-color |
border-right-color | border-inline-end-color |
border-left-width | border-inline-start-width |
border-right-width | border-inline-end-width |
border-left-style | border-inline-start-style |
border-right-style | border-inline-end-style |
尺寸(较少见,但值得转换)
| 物理属性 | 逻辑属性 |
|---|---|
width | inline-size |
height | block-size |
min-width | min-inline-size |
max-width | max-inline-size |
min-height | min-block-size |
max-height | max-block-size |
尺寸说明:
width/height的转换是可选的,优先级较低。它们仅对竖排书写模式(CJK 竖排文本)有影响,对标准 RTL 布局没有影响。只有当项目明确支持竖排书写模式时才转换这些属性,否则可以留待以后处理。优先转换 left/right 属性。
溢出与过度滚动
| 物理属性 | 逻辑属性 |
|---|---|
overflow-x | overflow-inline |
overflow-y | overflow-block |
overscroll-behavior-x | overscroll-behavior-inline |
overscroll-behavior-y | overscroll-behavior-block |
内联样式(JSX)
相同的转换也适用于驼峰命名:
// Before
<div style={{ marginLeft: 16, paddingRight: 8, textAlign: 'left' }}>
// After
<div style={{ marginInlineStart: 16, paddingInlineEnd: 8, textAlign: 'start' }}>
根据情况转换(中等置信度)
逐项检查。判断方向是语义性的(随文本流向变化)还是装饰性的(始终位于同一侧)。
-
包含 4 个物理角的边框圆角:
/* Physical corners */ border-top-left-radius: 8px; border-top-right-radius: 0; /* Logical corners */ border-start-start-radius: 8px; border-start-end-radius: 0;角映射:
top-left=start-start,top-right=start-end,bottom-left=end-start,bottom-right=end-end。 -
transform: translateX():不会自动翻转。如果位移方向随文本方向变化(例如从起始边缘滑入),则需要使用条件判断或 CSS 自定义属性:/* Option 1: custom property set by dir attribute */ :root { --dir: 1; } :root[dir="rtl"] { --dir: -1; } .slide-in { transform: translateX(calc(var(--dir) * 100%)); } /* Option 2: dir-aware selectors */ .slide-in { transform: translateX(100%); } [dir="rtl"] .slide-in { transform: translateX(-100%); } -
background-position: left/right:仅当位置具有语义意义时才转换(例如,图标位于输入框的起始侧)。如果只是装饰用途,则保持不变。 -
值不同的 4 值简写属性:
margin: 8px 24px 8px 16px— 左侧(16px)和右侧(24px)数值不同,因此需要使用逻辑属性的长写形式。 -
scroll-margin-left/right→scroll-margin-inline-start/end -
scroll-padding-left/right→scroll-padding-inline-start/end
绝不转换
- 有意固定的方向:始终指向左侧、不随地区设置变化的“后退”箭头,必须位于特定侧的滚动条,画布或游戏元素的绝对像素定位。
- 动画关键帧:带有方向性变换的
@keyframes通常用于装饰。只有当动画方向随文本方向变化时才进行转换。 writing-mode:此属性控制轴向本身,不属于转换范围。- SVG 属性:SVG 中的
x、y、width、height是坐标系属性,而非布局属性。 - 打印样式表:
@media print规则通常无需进行 RTL 转换。
第 3 步:Flexbox 和 Grid
Flexbox 和 Grid 布局会自动遵循 dir="rtl" — 主轴无需任何 CSS 更改即可翻转。这意味着:
justify-content: flex-start在 RTL 中已经会向右对齐- 在 RTL 中,
order值已经会反转视觉顺序 grid-template-columns中的列顺序已经会翻转
仍需注意的事项:
- 值不对称的
gap:column-gap和row-gap与方向无关,可以安全使用。无需转换。 - Flex 项中的方向性图标:表示“向前”的图标在 RTL 中应翻转。使用带有方向感知选择器的
transform: scaleX(-1),或提供单独的 RTL 图标资源。 flex-direction: row-reverse:在 RTL 中,row-reverse会反转已经反转的方向(恢复为 LTR 视觉顺序)。如果使用row-reverse是为了在 LTR 中创建从右到左的流向,那么它在 RTL 中可能不正确。请检查其用途。
第 4 步:工作流
按以下优先顺序处理文件(与转换技能的模式一致):
- 布局组件(应用外壳、侧边栏、导航栏、页脚)— 影响每个页面
- 共享组件(按钮、卡片、模态框、表单字段)— 在各处重复使用
- 页面级样式 — 仅适用于某个视图
- 工具类/全局 CSS — 重置文件、基础样式、CSS 自定义属性
在每个文件中:
- 找出所有物理方向属性
- 将每项归类为高/中/绝不转换
- 应用转换
- 进行视觉验证(第 5 步)
步骤 5:验证
转换后,验证布局在从左到右和从右到左的方向下都能正常工作:
- 切换方向:在浏览器 DevTools 中设置
<html dir="rtl">,或使用应用的语言区域切换器 - 目视检查:检查以下内容:
- 文本是否与右边缘对齐
- 边距和内边距是否正确镜像
- 定位元素(工具提示、下拉菜单、侧边栏)是否出现在正确的一侧
- 需要翻转的图标(导航箭头、“前进”/“后退”)是否翻转
- 不应翻转的图标(复选标记、通用符号、徽标)是否保持不变
- 运行现有测试:确认没有回归问题。CSS 更改可能会影响快照测试。
- 检查边缘情况:
- 重叠元素(绝对定位/固定定位)
- 滚动容器
- 水平溢出
常见问题
- CSS 中的
direction: rtl与 HTML 中的dir="rtl":始终使用 HTML 的dir属性,而不要使用 CSS 的direction属性。HTML 属性具有语义,会影响表单行为、键盘导航和双向算法。CSS 属性只影响视觉呈现。 - 混合内容:同时包含从左到右和从右到左内容的页面(例如,使用阿拉伯语用户输入的英文 UI)需要设置
dir="auto",或在内容块上显式设置dir属性。逻辑属性在嵌套方向上下文中也能正常工作。 - 水平滚动:
overflow-x: auto并不会在所有浏览器中翻转滚动条的位置。请明确测试。 - 第三方组件:UI 库中的组件内部可能使用物理属性。请检查该库是否提供 RTL 支持或 RTL 主题。
- 包含两个值的
px简写:margin: 8px 16px会设置上下边距和左右边距——但由于左右边距值相同,因此无需转换。只有不对称的四值简写才需要转换。