Skip to content

RTL 和 LTR 布局 #110

@pfan123

Description

@pfan123

双向性
从右向左(RTL)阅读的语言,例如阿拉伯语和希伯来语,其 UI 应该被镜像,以确保内容易于理解。

推荐方案

// direction 只能改变 display: flex/inline-block 元素的书写方,对于 float/绝对定位布局就无能为力,更别谈复杂的页面布局,比如[BFC 布局](https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Block_formatting_context) 、[双飞翼、圣杯布局](https://juejin.im/post/5a9813d6f265da237506506f),input、textarea、img(图片的展示方向不会变)

html.rtl {
    direction: rtl;
}

html.rtl input,textarea {
    text-align: right;
}

//  针对图片、绝对定位
.icon-rtl {
    transform: scaleX(-1),
 }

// direction 无法改变 margin, padding, border 的水平方向,特殊场景特殊处理

RTL 布局概述

MATERIAL DESIGN lrt-vs-rtl.png

如上图所示,左右两边分别展示了 RTL 和 LTR 的效果图。从图中我们可以直观地看出两者布局的区别:文本的对齐方向、主按钮和辅助按钮的排列方向、进度条的填充方向以及返回图标的方向是相反的,而其他图标则是相同的。具体总结如下:

  LTR RTL
文本 句子从左向右阅读 句子从右向左阅读
时间线 事件序列从左向右进行 事件序列从右向左进行
图像 从左向右的箭头表示向前运动:→ 从右向左的箭头表示向前运动:←

了解了 RTL 布局的特点之后,我们可以开始考虑如何低成本地将线上已有场景的 UI 从 LTR 调整为 RTL。在将 UI 从 LTR 调整为 RTL(或反之)时,我们通常称之为镜像。

实现 RTL 的两种方案

transfrom

基于 transform 的方案,是利用 CSS 的 transform 属性,通过设置 transform: scaleX(-1); 实现页面的水平翻转。

如上图所示,通过翻转解决了布局问题,但文字和图像也被翻转。为了解决这个问题,对于不需要翻转的内容(如文字、非指向性图像),需要进行二次翻转。然而,该方案的缺点在于,首次翻转只需要处理根节点,而二次翻转则需要处理所有不需要翻转的元素,工作量较大。该方案的优点在于开发者无需修改 JS 逻辑。例如,通常情况下,左滑/左向箭头图标的点击事件在 RTL 时会将前进改为后退,右向将后退改为前进。

direction

基于 direction 的方案,是利用 CSS 的 direction 属性,该属性用于设置文本、表格列和水平溢出的方向。通过将 direction 设置为 rtl 可以改变页面布局,在 html 标签上添加 dir="rtl" 与设置 direction 效果相同。我们通过一个简单的例子来具体了解设置为 rtl 的效果。

如上图所示,设置为 rtl 之后,我们发现 UI 并没有完全兼容 RTL 场景。我们可以观察到,direction 在设置 rtl 之后只对部分属性进行了镜像处理:

  • 如果元素没有预先定义过 text-align,那么该元素的文本会从向左对齐变成向右对齐,如果设置了 left/center 则 direction 的设置不会对其产生影响

  • inline-blockflextablegrid的布局方向被影响,absolute /fixedfloatmarginpadding无任何变化。

为了页面能够在 RTL 布局时正常呈现,我们需要对未被影响的属性调整。目前有以下两种方式可以解决这个问题。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions