# 阿拉伯语右排布局
# 右排布局概述
在普通的网页里,阅读方向是从左往右,但阿拉伯语的阅读方向是从右往左。通过查看阿拉伯语网站和Google的Material Design双向性文章 (opens new window),对比从左到右(LTR)语言网站,从右到左(RTL)语言的网站特点:
- 排版是从右往左
- 文本是向右对齐且从右往左阅读,文本方向始终和语言保持一致,比如数字(电话号码、时间)
- 方向性图标和LTR相反,其他的图标和图片不会镜像

通过上面知道RTL布局的特点后,我们在现有的项目里支持RTL布局需要考虑:
- 以低成本、代码入侵少、可兼容、可维护的改造线上的代码支持RTL布局
- 对于未来新增的页面功能能快速支持LTR和RTL布局
# RTL布局两种方案
# 方案一: 基于transform镜像
通过transform的镜像翻转,使用CSS3的transform属性,通过transform: scaleX(-1)可以使页面沿着X轴进行水平翻转,可以快速的解决布局镜像的问题,思路:
- 在阿拉伯语页面上添加上全局翻转:
/* xx/index.css */ html[lang="ar"] { transform: scaleX(-1); } - 将页面中不需要翻转的内容进行包裹
/* xx/index.css */ html[lang="ar"] .not-flip { transform: scaleX(-1); }
处理后的效果如下:

transform方案优点是无需修改js逻辑,只需要处理css;缺点是我们有五个项目,PC端和移动端,代码入侵大,工作量大,所有涉及到文本和图片的地方都需要进行处理。
# 方案二: 基于direction属性
direction与在html标签上直接添加dir="rtl"的作用一样,可以改变我们网站的布局,CSS手册中对direction属性是这样描述的:该属性指定了块的基本书写方向,以及针对Unicode双向算法的嵌入和覆盖方向。通俗的讲,排版改成从右往左,文字和图片方向不变。
我们在github上找到postcss-rtl开源插件,它的原理就是对CSS文件进行处理,比如将 CSS属性中的left改为right,right改为left。
[dir] .foo {
text-align: right;
}
[dir="ltr"] .foo {
text-align: right;
}
[dir="rtl"] .foo {
text-align: left;
}
基于direction属性RTL布局方案:
webpack中引入插件postcss-rtl (opens new window)vue-cli2脚手架配置: 安装依赖yarn add postcss-loader postcss-rtl -D在webpack中(cloud/build/utils.js)文件里添加postcss-loader的插件postcss-rtlvar postcssLoader = { loader: 'postcss-loader', options: { postcssOptions: { plugins: [ [ 'postcss-rtl', {} ] // 添加阿拉伯语右排布局插件 ] } } } // generate loader string to be used with extract text plugin function generateLoaders(loader, loaderOptions) { var loaders = [cssLoader, autoprefixerLoader, postcssLoader] if (loader) { loaders.push({ loader: loader + '-loader', options: Object.assign({}, loaderOptions, { sourceMap: options.sourceMap }) }) } ... }vue-cli3脚手架配置: 安装依赖yarn add postcss-rtl -D在webpack中(apps-moblie-docs/vue.config.js)文件里添加postcss-rtl插件css: { sourceMap: !isProduction, loaderOptions: { postcss: { plugins: [ require('postcss-rtl')() // 添加阿拉伯语右排布局插件 ] } } }
html标签属性添加默认值dir="ltr", 比如:<html dir="ltr">- 在
app.vue入口里添加根据语言判断修改html的dir属性,比如:document.documentElement.setAttribute('dir', this.$i18n.locale === 'ar' ? 'rtl' : 'ltr') - 方向的图标处理:
// 适配右排布局图标方向 [dir=rtl]{ .components-icons{ &.components-icons-back{ &:before { display: inline-block; transform: scaleX(-1); } } } } - 元素拼接的语句的处理:
// 适配右排布局 [dir=rtl] { .yun-row__desc { direction: ltr; display: inline-flex; justify-content: flex-end; } }
处理后的效果如下:

direction方案优点是工作量减少,代码入侵减少;缺点是需要处理方向性的图标的方向和被元素拼接的语句(断句)。
# 结论
| 方案 | 优点 | 缺点 |
|---|---|---|
transform | 无需修改js逻辑,只需要处理css | 代码入侵大,工作量大 |
direction | 工作量减少,代码入侵减少 | 处理方向性的图标的方向和被元素拼接的语句(断句) |
综合transform和direction方案各方面比较,direction方案的工作量减少、代码入侵少,最后决定使用direction方案。