2
头图

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

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

RTL 样式介绍

CSS 中的默认页面方向是 LTR。如果您检查您选择的浏览器并检查该html元素的浏览器默认代理样式,您会注意到这是ltrdir(或direction)属性的默认值。下面是一个基本示例,用于显示 LTR 和 RTL 布局之间的区别。
image.png
请注意,对于 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。
image.png

<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"阿拉伯元素后,结果如下所示:

image.png
除了图像,所有东西都被翻转了。那是因为它有float: leftmargin-right: 16px。为了解决这个问题,我们需要覆盖这些样式:

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

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

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

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

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

https://codepen.io/shadeed/pe...
当标题更长时,它会变得更复杂。下面,我把标题加长了一点,结果出乎意料。我已经附加了数字以显示正确的顺序。
image.png

dir="rtl"在元素上设置时,标题就清晰多了。也就是说,句子在语法上看起来是正确的,并且顺序正确。
image.png
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

根据MDNhorizontal-tb意思如下:

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

当页面的方向更改为 RTL 时,地翻转其项目。这是一个巨大的好处!下图显示了 flexbox 轴如何根据方向翻转。
image.png
在下面的示例中,我布置了三个项目并为每个项目编号以显示

<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 */
}

image.png
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来调整单词的字母是很常见的。它也被称为排版中的跟踪。考虑以下英语内容示例。看起来很正常。
    image.png
    但是,如果将相同的letter-spacing样式添加到阿拉伯语内容中,则会看起来很奇怪。考虑以下现实生活中的例子。
    image.png
    请注意,在带有 的内容中letter-spacing,每个单词的字母看起来彼此断开。那是不对的。阿拉伯字母应该看起来是相连的,而保持英文则与之相反letter-spacing。确保letter-spacing: 0在处理多语言布局时进行设置。

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

  1. 文字透明度
    改变文本颜色的透明度是很常见的——例如,让它看起来是次要的。这在英语中有效。但是,当内容是阿拉伯语时,会导致奇怪的文本呈现问题。

image.png

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

  1. 语言之间的字数差异
    有时,当一个网站被翻译成阿拉伯语时,由于某些词在翻译后变大或变小,元素的大小会发生变化。考虑以下示例,其中我模拟了 Smashing Magazine 网站的导航。
    image.png
    在阿拉伯语版本中,有些单词的大小与英语对应的单词几乎相同,有些相同,有些则更大。为了更清楚,这里是每个单词及其阿拉image.png
    您可能想知道为什么我要谈论字数的差异,因为这是正常的和预期的。考虑以下来自 LinkedIn 的真实示例。
    image.png
    按钮“完成”在阿拉伯语中被翻译为“تم”,这使得按钮太小而且看起来很奇怪。最好有一个min-width按钮来解释这种情况。我在浏览器的开发人员工具中添加了它,以显示它的外观:
    image.png
    这是来自 Twitter 的一个非常相似的例子:
    image.png

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

  1. 文本截断
    我曾经参与过一个内容混合的项目,我遇到了一个与文本截断方向错误相关的问题。考虑以下示例。
    image.png

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

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

image.png
https://codepen.io/shadeed/pe...

  1. 选择一个糟糕的 RTL 字体
    拥有设计的 RTL 版本并不意味着您可以选择系统的默认字体并收工。必须仔细选择字体以确保良好的可读性。一个例子是 Twitter:
    image.png

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

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

根据维基百科:

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

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

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

  1. 线高
    为 RTL 布局设置不同的字体是很常见的。在这种情况下,测试内容在一行和多行上的外观。在以下示例中,阿拉伯语文本的行间距小于英语文本的行间距,即使它们具有相同的line-height.
    image.png
    考虑到这一点并提供适合line-height阿拉伯语的内容非常重要。
    https://codepen.io/shadeed/pe...
    例如,在 Twitter 上,由于 的值不合适,有一个带有截断内容的按钮line-height
    image.png

请注意,在第一个图像中,阿拉伯语变音符号被截断了。它被称为“kasra”,它对于正确阅读这个词至关重要。在相邻的图像中,我已经固定了行高,现在它完全显示而没有被切断。

  1. 带下划线的链接
    与阿拉伯语单词一起使用时,默认文本下划线看起来很糟糕。这与如何用阿拉伯语书写单词和字母有关。请参阅下图:
    image.png
    我用红色圆圈突出显示了奇怪的区域。下划线有点覆盖字母的点。还是不清楚?这是一个特写:
    image.png
    以蓝色突出显示的点与下划线重叠。这不好,而且它使文本难以阅读。解决方案是在 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 中的外观:
image.png

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属性,则需要对其进行测试,因为它可能会破坏阿拉伯语单词。考虑以下:
    image.png

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

  1. 缩写
    在英语中,通常使用缩写来表示星期几。所以,“星期六”变成了“星期六”。
    image.png
    在阿拉伯语中,这根本不可能,因为单词的字母是要连接的。
    image.png

    双向图标

    对称图标不需要在 LTR 和 RTL 布局之间翻转。这里有些例子:
    image.png
    但是,对于某些图标,在 RTL 布局中翻转它们的方向很重要,以便用户可以清楚地理解它们。
    image.png
    然而,总有例外。根据Material Design指南,如果一个图标代表一个人可以用右手握住的对象,那么它就不需要翻image.png

    媒体播放器图标

    大约 15 年前,当我父亲给我买了一个 MP3 播放器时,我回到了过去。它有一个播放按钮,它有一个播放按钮,它的方向指向左边。
    image.png

有些图标是通用的,不需要我们翻转它们。原因是因为那些播放按钮代表的是正在播放的磁带的方向,而不是时间的方向。以下是 Spotify 应用程序在英语和阿拉伯语中的外观:
image.png
请注意,播放图标不会翻转,因为它们是通用图标。

消息应用程序

在一个有趣的Twitter 讨论中,我被问到是否要翻转消息应用程序的发送图标。我为 Facebook Messenger、WhatsApp 和 Twitter 做了一些研究。
image.png
发送图标被翻转,在我个人看来,这是正确的做法,因为我觉得这更合乎逻辑。此外,发送和“+”按钮的位置应该翻转以使其更正确。见下面的样机:
image.png
另一方面,Facebook 和 Twitter 都没有翻转发送图标。
image.png

翻转组件

在处理某些组件时,我需要一种快速翻转它们的方法。在 Sketch 应用程序中,我将复制一个组件,然后使用“翻转”命令翻转它。Adobe XD 和 Figma 中提供了相同的功能。

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

image.png

RTL 设计注意事项

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

按钮图标

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

image.png

表单输入

某些表单输入应在 RTL 中保持左对齐 - 例如,电子邮件和手机号码输入。
image.png

值得注意的是,如果占位符内容是阿拉伯语或其他 RTL 语言,则占位符应向右对齐。一旦输入被聚焦并且用户开始输入,对齐将向左翻转。
image.png
感谢蒋元浩让我知道上面的用例。

面包屑

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

页眉

页眉组件包含开始和结束部分。它们中的每一个都应该在 RTL 中翻转。
image.png

桌子也应该翻转。
image.png

标签

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

image.png

卡片

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

image.png

警告

正如您所料,“关闭”和警告图标应该翻转。

image.png

块引用

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

image.png

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
image.png
现在您已经对它的工作原理有了基本的了解,让我们探索更多 CSS 逻辑属性的示例和用例。

逻辑填充

image.png

假设我们有一个搜索输入,右侧有一个搜索图标。我们应该在左侧和右侧添加填充。右边的填充会大一点,以防止文本落在搜索图标下方。

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

image.png

此图标右侧的边距需要符合逻辑,因此我们将使用margin-inline-start

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

逻辑边界

image.png

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

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

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

逻辑边界半径

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

.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中的支持表:
image.png
image.png
尽管支持并不完美(并且永远不会完美),但我建议您使用带有回退的 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 样式。下面的设计模型有一个部分有两个孩子。
image.png
我没有给元素命名,比如.c-page-header__left.c-page-header__right,而是将它们命名为.c-page-header__startand .c-page-header__end。这更具前瞻性,并且不会假设网站只是 LTR 或 RTL。

双向垂直滚动条

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

考虑下图。
image.png

但是,对于操作系统,浏览器的滚动条不会改变,无论操作系统语言如何,它都保持在右侧。但是对于操作系统本身,滚动条会根据其语言而变化。

自动化工具

当我们需要将设计从 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 布局。
image.png

让我们从标题组件开始。为了正确编码,我概述了一个通用框架。请注意,我已将标题分为主要部分和子部分。另外,我为这些部分添加了开始和结束类。

image.png

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

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

image.png

接下来是标志和导航之间的分界线。起初,我考虑使用border-right. 它有效但并不理想。使用伪元素会更好,因为它会根image.png

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

这是到目前为止的结果:

image.png

接下来,我将处理主题组件(带有标签和计数器的子标题中的组件)。这是主题组件在 LTR 和 RTL 中的外观设计模型。请注意,计数器的位置是不同的。
image.png
乍一看似乎很简单,但是需要在 LTR 和 RTL 之间处理多个 padding 和 margin 声明。
image.png

.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对我来说更直接。

image.png

接下来是搜索输入。以下是要求:

  • 搜索图标必须出现在输入元素的末尾。
  • 搜索图标的位置必须是动态的。

    .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;
    }

    此外,当用户在搜索框中键入时,文本不应在图标下方滑动。为避免这种情况,请在右侧或左侧添加填充。
    image.png

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

    这是迄今为止 LTR 和 RTL 的结果:
    image.png

接下来是移动菜单。我将使用一个汉堡包图标来指示菜单。图标的位置将在 LTR 和 RTL 之间更改。translate动画的方向也是如此。
image.png

查看CodePen 上的演示

资源和相关文章


seasonley
607 声望693 粉丝

一切皆数据