关于javascript:关于如何在-CSS-中为-RTL-设置样式的广泛指南

31次阅读

共计 11221 个字符,预计需要花费 29 分钟才能阅读完成。

原文来自 https://rtlstyling.com/posts/…

全世界有超过 2.92 亿人将阿拉伯语作为他们的第一语言。阿拉伯语(al-Arabiyyah,发音为 /al ʕarabijja/,/ʕarabiː/)是我的母语,我有时会构建须要同时反对从左到右 (LTR) 和从右到左 (RTL) 款式的网站。

RTL 款式介绍

CSS 中的默认页面方向是 LTR。如果您查看您抉择的浏览器并查看该 html 元素的浏览器默认代理款式,您会留神到这是 ltrdir(或 direction)属性的默认值。上面是一个根本示例,用于显示 LTR 和 RTL 布局之间的区别。

请留神,对于 RTL 局部,文本从右到左读取,这与 LTR 文本相同。侥幸的是,浏览器实现了这个简略示例的所有工作。要切换文档的语言方向,您须要将 dir 属性增加到根元素。

<html dir="rtl">...</html>

dir 扭转时,以下因素也应主动翻转:题目,段落,链接,图像和表单元素。

值得一提的是,有一个 dir="auto" 属性,它会依据解析的内容主动切换方向。依据 HTML 标准:

催促作者仅在文本方向的确未知时才将此值用作最初的伎俩,并且无奈利用更好的服务器端启发式办法。

https://codepen.io/shadeed/pe…

除了 dir=rtl 在 HTML 元素上设置属性外,咱们还能够增加 direction: rtl 为 CSS 款式。

.element {direction: rtl;}

然而,CSSWG 倡议应该在 html 根元素上定义方向,以确保在没有 CSS 的状况下正确的双向布局。

翻转设计的根本示例

让咱们看一个更具体的示例,摸索如何将设计从 LTR 翻转到 RTL。

<article class="media">
    <img src="blueberry-cheesecake.jpg" alt="">
    <div class="media__content">
      <h2>Blueberry Cheesecake</h2>
      <p>...</p>
      <p><a href="#" class="link">View Recipe</a></p>
    </div>
</article>

最后,我在 LTR 设计中应用旧的浮点数将图像与左侧对齐——当然,我应用了 clearfix。

.media:after {
    content: "";
    display: block;
    clear: both;
}

.media__photo {
    float: left;
    width: 200px;
    margin-right: 16px;
}

增加 dir="rtl" 阿拉伯元素后,后果如下所示:


除了图像,所有货色都被翻转了。那是因为它有 float: leftmargin-right: 16px。为了解决这个问题,咱们须要笼罩这些款式:

.media[dir="rtl] img {
    float: right;
    margin-right: 0;
    margin-left: 16px;
}

https://codepen.io/shadeed/pe…

在 LTR 布局中混合英语和阿拉伯语内容

如果某些文本混合了英语和阿拉伯语单词,而布局是 LTR,会产生什么状况?好吧,后果看起来很奇怪。

浏览器显示题目不正确。对于讲阿拉伯语的人来说,题目读起来会很凌乱,除非你是写它的作者。它应该依照下图
为防止此问题,请尽可能设置适当的语言方向。一旦 dir="rtl" 在元素上设置,

https://codepen.io/shadeed/pe…
当题目更长时,它会变得更简单。上面,我把题目加长了一点,后果出其不意。我曾经附加了数字以显示正确的程序。

dir="rtl" 在元素上设置时,题目就清晰多了。也就是说,句子在语法上看起来是正确的,并且程序正确。

https://codepen.io/shadeed/pe…

解决字体

依据 LTR 和 RTL 布局的设计,每个方向都应该有特定的字体。有些字体能够用于多种语言,这很棒。然而,品牌和企业偏向于为 RTL 应用不同的字体。

思考到这一点,咱们应该在我的项目的字体设置中定义不同的字体。无关更多详细信息,请参阅自动化工具。

字体系列

在 CSS 中,它的 font-family 工作形式能够很容易地回退到另一种字体,以防字体未加载。然而,事实证明,如果申明中的第一种字体不反对特定字形,它将尝试应用第二种字体。

依据 MDN:

字体抉择不会简略地停在用户零碎上列表中的第一个字体处。相同,字体抉择一次一个字符实现,因而如果可用字体没有所需字符的字形,则尝试应用后一种字体。

Omar Bourhaouta 做了以下演示,证实了上述概念:
https://codepen.io/bourhaouta…

body {font-family: 'Roboto','Amiri', sans-serif;}

Roboto 字体无奈辨认阿拉伯字形,因而它退回到第二个字体申明。

弹性盒布局模块

Flexbox 基于文档的书写模式。写入模式用于指定块在页面上的布局形式。例如,一个中文网站是从上到下布局的。写入模式就是为了这个目标。在 flexbox 中,items 是依据文档的书写形式来调配的。writing-mode英语和阿拉伯语的默认值为horizontal-tb

依据 MDN,horizontal-tb意思如下:

内容从左到右程度流动,从上到下垂直流动。下一条水平线位于前一条线的下方。

当页面的方向更改为 RTL 时,地翻转其我的项目。这是一个微小的益处!下图显示了 flexbox 轴如何依据方向翻转。

在上面的示例中,我安排了三个我的项目并为每个项目编号以显示

<div class="element">
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
</div>
.element {
    display: flex;
    flex-direction: row; /* Default value, added for clarity */
}


https://codepen.io/shadeed/pe…

grid 网格布局模块

和 flexbox 一样,grid 布局模块依赖于文档的书写模式,这给了咱们应用 flexbox 一样的益处。

在上面的示例中,main当方向为 LTR 时,侧边栏应在左侧,内容应在右侧。对于 RTL,反之亦然。当咱们应用 CSS grid 时,翻转会依据页面的方向主动实现。

<div class="element">
    <div class="side">Side</div>
    <div class="main">Main</div>
</div>
.element {
    display: grid;
    grid-template-columns: 220px 1fr;
    grid-gap: 1rem;
}

https://codepen.io/shadeed/pe…

翻转到 RTL 时的常见谬误

非阿拉伯语人士会犯一些很容易发现的常见谬误。

  1. 字母间距
    在英语中,增加 letter-spacing 来调整单词的字母是很常见的。它也被称为排版中的跟踪。思考以下英语内容示例。看起来很失常。

    然而,如果将雷同的 letter-spacing 款式增加到阿拉伯语内容中,则会看起来很奇怪。思考以下现实生活中的例子。

    请留神,在带有 的内容中 letter-spacing,每个单词的字母看起来彼此断开。那是不对的。阿拉伯字母应该看起来是相连的,而放弃英文则与之相同letter-spacing。确保letter-spacing: 0 在解决多语言布局时进行设置。

https://codepen.io/shadeed/pe…

  1. 文字透明度
    扭转文本色彩的透明度是很常见的——例如,让它看起来是主要的。这在英语中无效。然而,当内容是阿拉伯语时,会导致奇怪的文本出现问题。

有些区域的字母之间色彩不同。在这个例子中,letter-spacing没有被调整,所以问题与此无关。解决方案是简略地设置没有 RGBa 或不透明度的色彩。
https://codepen.io/shadeed/pe…

  1. 语言之间的字数差别
    有时,当一个网站被翻译成阿拉伯语时,因为某些词在翻译后变大或变小,元素的大小会发生变化。思考以下示例,其中我模仿了 Smashing Magazine 网站的导航。

    在阿拉伯语版本中,有些单词的大小与英语对应的单词简直雷同,有些雷同,有些则更大。为了更分明,这里是每个单词及其阿拉
    您可能想晓得为什么我要议论字数的差别,因为这是失常的和预期的。思考以下来自 LinkedIn 的实在示例。

    按钮“实现”在阿拉伯语中被翻译为“تم”,这使得按钮太小而且看起来很奇怪。最好有一个 min-width 按钮来解释这种状况。我在浏览器的开发人员工具中增加了它,以显示它的外观:

    这是来自 Twitter 的一个十分类似的例子:

请留神,截至撰写本文时(2019 年 12 月 13 日),您曾经真正发现了 LinkedIn 和 Twitter 上的上述问题。

  1. 文本截断
    我已经参加过一个内容混合的我的项目,我遇到了一个与文本截断方向谬误相干的问题。思考以下示例。

英文文本的截断不正确。它应该在元素的开端,而不是它的结尾。为了解决这个问题,dir="auto"在元素自身上设置属性,而后浏览器会主动解析内容并决定 dir 它是哪个。

<p dir="auto">أهلاً وسهلاً بكم في المقال الذي يتحدث عن تصميم صفحات الويب للغة العربية</p>
<p dir="auto">Welcome to the article that explains how to design for RTL pages.</p>


https://codepen.io/shadeed/pe…

  1. 抉择一个蹩脚的 RTL 字体
    领有设计的 RTL 版本并不意味着您能够抉择零碎的默认字体并出工。必须认真抉择字体以确保良好的可读性。一个例子是 Twitter:

从阿拉伯语使用者的角度来看,“تغريد”这个词很难读,起因如下:

  • 字体不好。
  • 粗体字妨碍了可读性。
  • 这个词的点很小,十分靠近字母。
    我模仿了一个看起来更清晰的设计:
  • 混合印地语和阿拉伯数字 #
    在阿拉伯语中,有两种书写数字的形式:
  • 印地语:٠ ١ ٢ ٣ ٤ ٥ ٦ ٧ ٨ ٩
  • 阿拉伯语:0 1 2 3 4 5 6 7 8 9
    英语中应用的数字继承自阿拉伯数字:“0, 1, 2, 3, 4, 5, 6, 7, 8, 9”。蕴含数字的内容应该是统一的,无论是印地语还是阿拉伯数字。

依据维基百科:

这些数字在欧洲和美洲更常被称为“阿拉伯数字”的起因是它们在 10 世纪由北非的阿拉伯语使用者引入欧洲,过后他们应用从利比亚到摩洛哥的数字。

以下模型混合了印地语和阿拉伯数字。它看起来不统一,它应该与一种数字看起来对立。

可能不适用于 RTL 的常见事件

  1. 线高
    为 RTL 布局设置不同的字体是很常见的。在这种状况下,测试内容在一行和多行上的外观。在以下示例中,阿拉伯语文本的行间距小于英语文本的行间距,即便它们具备雷同的 line-height.

    思考到这一点并提供适宜 line-height 阿拉伯语的内容十分重要。
    https://codepen.io/shadeed/pe…
    例如,在 Twitter 上,因为 的值不适合,有一个带有截断内容的按钮line-height

请留神,在第一个图像中,阿拉伯语变音符号被截断了。它被称为“kasra”,它对于正确浏览这个词至关重要。在相邻的图像中,我曾经固定了行高,当初它齐全显示而没有被切断。

  1. 带下划线的链接
    与阿拉伯语单词一起应用时,默认文本下划线看起来很蹩脚。这与如何用阿拉伯语书写单词和字母无关。请参阅下图:

    我用红色圆圈突出显示了奇怪的区域。下划线有点笼罩字母的点。还是不分明?这是一个特写:

    以蓝色突出显示的点与下划线重叠。这不好,而且它使文本难以浏览。解决方案是在 CSS 中应用自定义下划线。

2.1. 文字装璜
能够应用 newtext-decoration-styletext-decoration-colorproperties 更改下划线的款式和色彩。然而,不能保障实用于所有字体和字体大小。在撰写本文时,Firefox 是对这些属性反对最好的浏览器。

更新:2020 年 1 月 18 日
基于 Github 上的这个问题,后果证实应用 text-decoration-skip-ink 属性能够解决点与下划线重叠的问题。它的默认值为skip

https://codepen.io/shadeed/pe…
在撰写本文时,Safari 不反对旧版 Edge(Chromium Edge 反对)。这是它在 Safari 中的外观:

2.2. 盒子暗影
浏览器对 box-shadow 的反对比 text-decoration 好得多。能够检测到对新属性之一 text-decoration 的反对,如果浏览器不反对它,那么它将回退到 box-shadow 该属性。

.link-3 {
  color: #000;
  text-decoration-color: rgba(21, 132, 196, 0.2);
  text-decoration-style: normal;
  text-underline-offset: 4px;
  text-decoration-thickness: 2px;
  box-shadow: inset 0 -5px 0 0 rgba(#1584c4, 0.2);
}

@supports (text-decoration-color: red){
  .link-3 {box-shadow: none;}
}
  1. 换行
    如果您的 CSS 具备该 word-break 属性,则须要对其进行测试,因为它可能会毁坏阿拉伯语单词。思考以下:

因为 的影响,圈出的区域是断断续续的阿拉伯语单词word-break。在阿拉伯语中,没有断字之类的货色。一个单词的字母是相互连接的,所以不可能打断一个单词。

  1. 缩写
    在英语中,通常应用缩写来示意星期几。所以,“星期六”变成了“星期六”。

    在阿拉伯语中,这基本不可能,因为单词的字母是要连贯的。

    双向图标

    对称图标不须要在 LTR 和 RTL 布局之间翻转。这里有些例子:

    然而,对于某些图标,在 RTL 布局中翻转它们的方向很重要,以便用户能够分明地了解它们。

    然而,总有例外。依据 Material Design 指南,如果一个图标代表一个人能够用右手握住的对象,那么它就不须要翻

    媒体播放器图标

    大概 15 年前,当我父亲给我买了一个 MP3 播放器时,我回到了过来。它有一个播放按钮,它有一个播放按钮,它的方向指向右边。

有些图标是通用的,不须要咱们翻转它们。起因是因为那些播放按钮代表的是正在播放的磁带的方向,而不是工夫的方向。以下是 Spotify 应用程序在英语和阿拉伯语中的外观:

请留神,播放图标不会翻转,因为它们是通用图标。

音讯应用程序

在一个乏味的 Twitter 探讨中,我被问到是否要翻转音讯应用程序的发送图标。我为 Facebook Messenger、WhatsApp 和 Twitter 做了一些钻研。

发送图标被翻转,在我集体看来,这是正确的做法,因为我感觉这更合乎逻辑。此外,发送和“+”按钮的地位应该翻转以使其更正确。见上面的样机:

另一方面,Facebook 和 Twitter 都没有翻转发送图标。

翻转组件

在解决某些组件时,我须要一种疾速翻转它们的办法。在 Sketch 应用程序中,我将复制一个组件,而后应用“翻转”命令翻转它。Adobe XD 和 Figma 中提供了雷同的性能。


为了明确我的意思,这里有一个 GIF 显示我在翻转一个组件后做了什么。

RTL 设计注意事项

在本节中,我将介绍最常见的组件并展现它们在 RTL 模式下的外观。

按钮图标

通常有一个带有图标的按钮,用于关上更多操作的菜单。在这种状况下,图标的地位应该在 RTL 布局中翻转。

表单输出

某些表单输出应在 RTL 中放弃左对齐 – 例如,电子邮件和手机号码输出。

值得注意的是,如果占位符内容是阿拉伯语或其余 RTL 语言,则占位符应向右对齐。一旦输出被聚焦并且用户开始输出,对齐将向左翻转。

感激蒋元浩让我晓得下面的用例。

面包屑

面包屑模式中的箭头也应该翻转。

页眉

页眉组件蕴含开始和完结局部。它们中的每一个都应该在 RTL 中翻转。

桌子也应该翻转。

标签

对于 LTR 中的选项卡组件,图标将位于标签的左侧。在 RTL 中,这些应该被翻转。

卡片

对于程度卡片,图像和文本的程序应该在 RTL 中翻转。

正告

正如您所料,“敞开”和正告图标应该翻转。

块援用

图标应该像上面的模型一样翻转。

CSS 逻辑属性

依据 MDN:

CSS 逻辑属性和值是 CSS 的一个模块,它引入了逻辑属性和值,提供了通过逻辑而不是物理方向和维度映射来管制布局的能力。

咱们举一个简略的例子。假如咱们须要将一串文本向左对齐。因而,咱们增加以下内容:

.page-header {text-align: right;}

对于 RTL:

[dir="rtl"] .nav-item {text-align: left;}

如果有一种办法能够增加一个 text-align 依据页面方向改变方向的值呢?CSS 逻辑属性来援救你!

.page-header {text-align: end;}

有了这个,的方向 text-align 将基于页面。演示

为了更容易看到的区别 startend,我做了上面的样机。该 start 值在 LTR 中等于 left,end在 RTL 中等于 right。这同样实用于 end

当初您曾经对它的工作原理有了根本的理解,让咱们摸索更多 CSS 逻辑属性的示例和用例。

逻辑填充

假如咱们有一个搜寻输出,右侧有一个搜寻图标。咱们应该在左侧和右侧增加填充。左边的填充会大一点,以避免文本落在搜寻图标下方。

.input--search {  
  padding-inline-start: 1rem;
  padding-inline-end: 2.5rem;
}

此图标右侧的边距须要合乎逻辑,因而咱们将应用margin-inline-start

.page-header__avatar {margin-inline-start: 1rem;}

逻辑边界

很多时候,您可能须要增加边框来批示导航元素处于活动状态。在下面的设计中,每个导航元素的左侧都有一个边框。咱们如何使它合乎逻辑?

.nav__item {border-inline-start: 3px solid transparent;}

.nav__item.is-active {border-color: #1e9ada;}

逻辑边界半径


在下面的设计中,导航元素的背景只有右上角和右下角的边框半径。为了在逻辑上做到这一点,咱们应用以下内容:

.nav__item {  
  border-start-end-radius: 30px;
  border-end-end-radius: 30px;
  background-color: transparent;
}

.nav__item.is-active {background-color: #ecf6fb;}

逻辑属性备忘单

当对定向 CSS 属性的逻辑等效项有疑难时,请应用上面的备忘单。请留神,蕴含的属性仅限于对 LRT 和 RTL 有用的属性。我是依据 Adrian Roselli 的一篇很棒的文章制作的。
https://codepen.io/shadeed/pe…
除此之外,Adrian 创立了一个演示,能够轻松了解逻辑 CSS 属性和定向 CSS 属性之间的区别。
https://codepen.io/aardrian/p…

浏览器反对

浏览器反对是相当不错的 paddingmargintext-align。然而,这对边界半径属性不利。以下是 Can I Use 中的反对表:


只管反对并不完满(并且永远不会完满),但我建议您应用带有回退的 CSS 逻辑属性。例如:

.input--search {  
  padding-left: 1rem;
  padding-right: 2.5rem;
  padding-inline-start: 1rem;
  padding-inline-end: 2.5rem;
}

此外,您能够应用 PostCSS Logical 插件,它为所应用的每个逻辑属性增加一个回退。

CSS 命名约定

一般来说,防止给与元素关联的 CSS 类名称。应用能够提取到可重用组件的名称。思考以下:

<div class="c-section">
  <p><a href="#" class="see-link">See more</a></p>
</div>

<div class="c-section">
  <p><a href="#" class="see-link">Learn more</a></p>
</div>

在这两个局部中,链接是雷同的,但它们的标签不同。在第二局部,see-link没有意义。一个好名字可能是 c-link。该c 代表组成,这是我从 ITCSS 框架教训。

既然您曾经有了这个想法,咱们也能够将其利用于 RTL 款式。上面的设计模型有一个局部有两个孩子。

我没有给元素命名,比方 .c-page-header__left.c-page-header__right,而是将它们命名为.c-page-header__startand .c-page-header__end。这更具前瞻性,并且不会假如网站只是 LTR 或 RTL。

双向垂直滚动条

据我所知,CSS 中容器内的垂直滚动条方向会依据页面方向而变动。对于 RTL 布局,滚动条方向在左侧,而对于 LTR,则在右侧。

思考下图。

然而,对于操作系统,浏览器的滚动条不会扭转,无论操作系统语言如何,它都放弃在右侧。然而对于操作系统自身,滚动条会依据其语言而变动。

自动化工具

当咱们须要将设计从 LTR 翻转到 RTL 时,有很棒的工具能够使咱们的工作更轻松。

1. Bi-App-Sass

Anas Nakawa 的 Bi-App-Sass 容许您编写样式表一次,而后将它们编译成两个不同的样式表,一个用于 LTR,另一个用于 RTL。

这个工具对于大型项目很有用。后果将是每个语言方向的多个样式表。思考以下:

.elem {
  display: flex;
  @include margin-left(10px);
  @include border-right(2px solid #000);
}

生成的 CSS 将是这样的:
app-ltr.css

.elem {
  display: flex;
  margin-left: 10px;
  border-right: 2px solid #000;
}

app-rtl.css

.elem {
  display: flex;
  margin-right: 10px;
  border-left: 2px solid #000;
}

然而请留神,GitHub 存储库中的最初一次提交是四年前(2015 年 11 月)。

2. RTLCSS

Mohammad Younes 的 RTLCSS 是一个将 LTR 样式表转换为 RTL 的框架。

此工具的不同之处在于它仅在 CSS 文件的构建版本上运行。例如,如果您有一个蕴含 50 多个 Sass 组件的我的项目,RTLCSS 将派上用场,用于解析已编译的 CSS 文件并创立它的 RTL 版本。

理论例子

网站题目 #
我专门设计了一个布局来向您展现我将如何解决和思考将其翻转为 RTL 布局。

让咱们从题目组件开始。为了正确编码,我概述了一个通用框架。请留神,我已将题目分为次要局部和子局部。另外,我为这些局部增加了开始和完结类。

.header__main,
.header__sub {
    display: flex;
    justify-content: space-between;
}

并且因为 CSS flexbox 基于页面的方向工作,正如本指南后面所解释的,它会为 RTL 主动翻转。

接下来是标记和导航之间的分界线。起初,我思考应用 border-right. 它无效但并不现实。应用伪元素会更好,因为它会根

.c-brand:after {
  content: "";
  display: inline-block;
  vertical-align: middle;
  width: 3px;
  height: 38px;
  border-radius: 5px;
  background: #e4e4e4;
  margin-inline-start: 1.25rem;
}

这是到目前为止的后果:

接下来,我将解决主题组件(带有标签和计数器的子标题中的组件)。这是主题组件在 LTR 和 RTL 中的外观设计模型。请留神,计数器的地位是不同的。

乍一看仿佛很简略,然而须要在 LTR 和 RTL 之间解决多个 padding 和 margin 申明。

.topics-heading {margin-inline-end: 1.5rem;}

.topics-list {margin-inline-end: 1rem;}

.c-topic {padding-inline-start: 0.5rem;}

.c-topic:not(:last-child) {margin-inline-end: 10px;}

.c-topic__counter {margin-inline-start: 1rem;}

如您所见,我应用了 CSS 逻辑属性,而不是 leftright

下一步是“查看全副”链接。留神它开端的箭头。上面是它的要求:

  • 箭头的色彩应该在悬停时扭转。
  • 悬停时箭头应向右挪动。
    为此,我抉择应用内联 SVG。当我用 translate 给箭头增加动画时,我想到了 RTL。这没有逻辑属性,我须要摸索其余解决方案。我想出的一种解决方案是为边距设置动画。

    .c-link svg {
      margin-inline-start: 4px;
      transition: 0.15s ease-in;
    }
    
    .c-link:hover svg {margin-inline-start: 8px;}

    然而动画边距对性能不利,只管它无效。另一种解决方案是检测页面的方向,并用 translate 基于此设置申明。

    .c-link:hover svg {transform: translateX(6px);
    }
    /* I’m using dir=rtl in the header for the purpose of clarity. It should be added to the root element. */
    .c-header[dir="rtl"] .c-link svg {transform: scaleX(-1);
    }
    
    .c-header[dir="rtl"] .c-link:hover svg {transform: scaleX(-1) translateX(6px);
    }

    请留神,对于 RTL,我增加 scaleX(-1) 程度翻转箭头图标。你能够改用rotate(180deg),但 scaleX 对我来说更间接。

接下来是搜寻输出。以下是要求:

  • 搜寻图标必须呈现在输出元素的开端。
  • 搜寻图标的地位必须是动静的。

    .c-input--search {background-image: url("data:image/svg+xml...");
    background-position: right 6px center;
    }
    
    .c-header[dir="rtl"] .c-input--search {
    /* We replace the original icon with a flipped one. */
    background-image: url("data:image/svg+xml...");
    background-position: right 6px center;
    }

    此外,当用户在搜寻框中键入时,文本不应在图标下方滑动。为防止这种状况,请在右侧或左侧增加填充。

    .c-input {padding-inline-end: 32px;}

    这是迄今为止 LTR 和 RTL 的后果:

接下来是挪动菜单。我将应用一个汉堡包图标来批示菜单。图标的地位将在 LTR 和 RTL 之间更改。translate动画的方向也是如此。

查看 CodePen 上的演示。

资源和相干文章

  • (从右到左)镜子世界
  • 让咱们谈谈 RTL
  • Flexbox 的基本概念
  • 网格布局的基本概念
  • 从右到左开发:提醒和技巧
  • 阿拉伯数字

正文完
 0