Skip to content

CSS 中有很多功能模块是带有方向性的,比如文本对齐浮动定位框对齐 等,它们有着 TRBL 的顺序规则(即 toprightbottomleft)。这些带有方向性的属性或值常会出现在你的 CSS 代码中。

假设你正在开发一个多语 Web 应用或网站,那么这些带有方向性的属性或值就很有可能给你的应用带来很多麻烦。主要原因是 Web 开发者习惯性在代码中使用 CSS 的物理属性。

换句话说,如果你正在或开发一个多语言版本 Web 应用或网站时,应该使用 CSS 逻辑属性,它能帮助你开发一个更健壮、更灵活的应用,减少不必要的麻烦。接下来,我们就围绕着这方面的话题来展开。

多语言 Web 应用

世界上有很多种语言(简称世界语言),比如汉语、英语、印度斯坦语、西班牙语、阿拉伯语、俄语、葡萄牙语、德语和法语等。

img

为每一种语言都提供相应的 UI 界面的应用,称为多语言 Web 应用多语言 Web 网站 。例如 Facebook 就是这样的一个应用:

img

虽然世界语言有很多种类型,但它们大致可为分为三大类:

img

  • 汉语体系,比如中文、日文和韩文等;
  • 拉丁语体系,比如英语、德语和法语等;
  • 阿拉伯语体系,比如阿拉伯语和希伯来语等。

与语言相匹配的书写模式和阅读模式

每一种语言体系都有着自己的书写模式和阅读模式,比如汉语体系和拉丁语体系的书写模式和阅读模式是从左到右,即 LTR (Left-To-Right);阿拉伯语体系的书写模式和阅读模式刚好与其相反,是从右到左,即 RTL (Right-To-Left)。其中汉语体系有时候还有垂直模式,即竖排。

有意思的是,在 HTML 和 CSS 中都有着相应的特性,可以对应着不同语言体系的书写模式和阅读模式。比如,在 HTML 中,我们可以在元素标签上使用 dir 属性来指定它们:

  • dir="ltr" :对应着 LTR 模式,汉语体系和拉丁语体系都是这种模式;
  • dir="rtl" :对应着 RTL 模式,阿拉伯语体系都是该模式。
HTML
<!-- RTL -->
<html lang="ar" dir="rtl">
    <body>
        <h1>مياه للجميع، مستقبل مشترك</h1>
    </body>
</html>

<!-- LTR -->
<html lang="zh" dir="ltr">
    <body>
        <h1>人人有水、共享未来</h1>
    </body>
</html>

CSS 中的 direction 和 HTML 的 dir 是完全相同的。我们可以在 CSS 中使用 direction 来改为阅读模式,比如:

CSS
[lang="ar"] {
    direction: rtl;
}

[lange="zh"] {
    direction: ltr;
}

img

汉语、日语、韩语和蒙古语既可以从左到右水平书写,也可以从上到下垂直书写。大多数这些语言的网站都是水平的,和英语一样。

img

相比之下,垂直书写在日本网站上更为常见。有些网站同时使用垂直和水平文本。

img

URL: http://www.baroku.co.jp/

对于垂直书写(从上到下且从右到左或从上到下且从左到右)模式,HTML 的 dir 和 CSS 的 direction 是无法实现的。庆幸的是,CSS 中有一个名为书写模式的模块,即 writting-mode ,它可以做到:

  • horizontal-tb :定义了内容从左到右水平流动(内联流),从上到下垂直流动(块流)。下一条水平线位于上一条线下方;
  • vertical-rl :定义了内容从上到下垂直流动(内联流),从右到左水平流动(块流)。下一条垂直线位于上一行的左侧;
  • vertical-lr :定义了内容从上到下垂直流动(内联流),从左到右水平流动 (块流)。下一条垂直线位于上一行的右侧;
  • sideways-rl :定义了内容从上到下垂直流动,所有字形,甚至是垂直脚本中的字形,都设置在右侧;
  • sideways-lr :内容从上到下垂直流动,所有字形,甚至是垂直脚本中的字形,都设置在左侧。

img

Demo 地址:https://codepen.io/airen/full/rNZbYbe

这里所说的块流和文本流,主要指的是 HTML 块元素的流动方向和文本内容的流动方向,其中文本流也常称“内联方向”:

img

在 Web 中除了文档有流方向一说之外,对于文本同样有流的概念,比如说英文,一般是从左到右,阿拉伯文是从右到左,而日文(古代的中文)从上到下,从右到左:

img

不管是文档流还是文本流,它们都具有相应的物理特性,比如从左到右,从右到左,从上到下,从下到上。即,它们都没有离开 toprightbottomleft 方向。这也是 CSS 中为什么有那么多属性和值都与方向有着紧密联系的原因所在。比如:

  • text-align 属性:用于指定文本的对齐方式,属性值包括 left(左对齐)、right(右对齐)和 center(居中对齐)。
  • vertical-align 属性:用于指定元素内容的垂直对齐方式,属性值包括 top(顶端对齐)、bottom(底端对齐)和 middle(居中对齐)。
  • position 属性:用来设置元素的定位方式,取值 relativeabsolutefixedsticky,配合 toprightbottomleft 值,可以对元素进行精确定位。
  • margin-topmargin-rightmargin-bottommargin-left 属性:用于设置元素的外边距,四个方向的值可以单独设置。
  • padding-toppadding-rightpadding-bottompadding-left 属性:用于设置元素的内边距,四个方向的值可以单独设置。
  • border-topborder-rightborder-bottomborder-left 属性:用于设置元素的边框,四个方向的值可以单独设置,还可以结合 border-style(边框样式)、border-width(边框宽度)等属性一起使用。
  • border-top-left-radiusborder-top-right-radiusborder-bottom-right-radiusborder-bottom-left-radius 属性:用于设置元素的圆角,四个顶点的值可以单独设置。
  • linear-gradient()repeating-linear-gradient() 属性:to rightto leftto topto bottom 可以设定渐变的方向、起点和终点颜色。
  • float 属性的值可以设置为 leftright ,分别表示浮动在左边、右边。
  • clear 属性的值可以设置为 leftright,分别表示清除浮动元素在左边、右边。
  • CSS Flexbox 布局中的 flex-direction 和 CSS Grid 布局中的 grid-auto-flow
  • CSS 框对齐相关的属性。

这些与 toprightbottomleft 方向有关联的属性和值,都被统称为 CSS 物理属性或值,它们最终在浏览器的呈现都会受到 HTML 的 dir 、CSS 的 direction (指定文本方向)、writing-mode (控制文本排列方式)、text-orientation (控制文本方向)和 unicode-bidi (设置双向文本的方向)等属性的影响。

CSS 物理属性在多语言 Web 应用中的缺陷

正如上面所述,CSS 中有很多属性和值是遵循 TRBL (Top、Right、Bottom 和 Left ) 模式的:

img

它们带有明确的方向性。只不过,针对多语言布局时,它给布局带来很大的局限性,比如下面这个简单的示例:

CSS
.thumb {
    margin-right: 1rem;
}

ltr 模式(比如语文)和 rtl 模式(比如阿拉伯文),效果将会是像下图一样:

img

这个效果并不是我们所期待的,如果希望达到预期的效果,在以往编码的时候,需要做额外的处理:

CSS
.thumb {
    margin-right: 1rem;
}

[dir="rtl"] .thumb {
    margin-left: 1rem;
}

img

就上面这个示例而言,现代 Web 布局 中的 Flexbox 布局和 Grid 布局可以很轻易的实现,但在一些场景中它们是无法做到的。所以,对于 Web 开发者来说,需要一个新的功能,它没有物理性的方向概念,只有开始和结束的概念,并且能自动匹配语言自身的书写模式或阅读模式。换句话说,它是带有逻辑性的,在 CSS 中称之为逻辑属性或值

什么是 CSS 逻辑属性?

在 CSS 中,逻辑属性是一种与文本书写方向有关的属性,它们提供了一种依赖于元素语义而不是物理方向的方式来定义元素的样式。这使得在从左到右(LTR)和从右到左(RTL)等不同方向书写的语言环境下,更容易地控制元素的布局和样式。

通过使用逻辑属性,可以在左到右(LTR)和右到左(RTL)等不同的书写或阅读模式下,使用相同的样式代码实现正确的布局。而传统的物理属性如 marginpaddingborder 等,在不同书写或阅读模式中可能需要区别对待。

一些常用的逻辑属性,包括 inline-size (元素在行轴上的大小)、 block-size (元素在块轴上的大小)、margin-inline-start (元素在行轴上开始的外边距大小) 和 margin-inline-end (元素在行轴上结束的外边距大小)等,这些属性的实际表现形式将根据文本书写方向自动调整。

利用这些属性,可以更轻松地开发面向全球的多语言 Web 应用或网站,使其在不同语言环境下拥有相同的布局,而无需特意修改样式。

使用 CSS 逻辑属性的优势是什么?

在 CSS 中,传统的物理属性制定了文本在文本流中的默认行为,而逻辑属性则提供了一种更加灵活的控制布局的方式,这种方式相对于语言文本的书写方向进行自适应布局。例如,逻辑属性 margin-inline-startmargin-inline-end 的值,在 LTR 和 RTL 文本书写方向下分别表示元素左侧和右侧的外边距。

使用逻辑属性的好处在于,它可以使开发者更快速地在 CSS 布局中应用全球多语言环境的基本排版规则,而无需考虑物理定位的许多繁琐细节。例如,当处理从右到左书写的阿拉伯语时,由于其文本书写方向不同,许多元素需要在布局上进行特殊处理。但是如果使用逻辑属性,就可以根据布局所在的文本方向自动创建正确的布局和样式。

比如,你可以使用逻辑属性 marign-inline-end 来设置用户头像与内容之间的间距:

CSS
.thumb {
    margin-inline-end: 1rem;
}

img

正如你所看到,在使用逻辑属性时,间距和布局取决于文本书写方向和阅读方向(无论是由 CSS 还是 HTML 设置)。因此,在不同的语言中可以重复使用 CSS 样式。例如,使用 CSS 逻辑属性重构建之后的 BBC 新闻网站,这比让用户依赖自动翻译的体验更好,这也意味着它们可以更好地满足不同地区的需求。不过,视觉样式在不同地区仍然保持相同。

img

URL 地址:https://www.bbc.com/arabic

简而言之,Web 开发者在开发多语言 Web 应用或网站时,使用 CSS 逻辑属性的优势包括:

  • 更好的代码可维护性 :使用逻辑属性,可以将不同语言环境下的布局和样式都包含在一个样式表中,无需使用多个样式表处理各种语言环境。这简化了网站的代码结构,使代码更易于维护。而在使用传统的物理属性时,可能需要为每种语言环境维护多个版本的样式表,这将增加代码的复杂性。
  • 更加精确的布局和样式 :使用逻辑属性,可以自动适应文本的书写方向并调整 Web 布局和 UI 样式,无需进行人工处理。这确保了界面的一致性,并可以避免因处理哪种语言而导致的布局问题。
  • 更高的可读性 :使用逻辑属性可以使代码更具可读性,因为代码中的属性名称可以更直接地反映元素在文本方向上的布局。而在使用传统的物理属性时,代码需要进行语言或书写方向的调整,这可能会导致代码的可读性变差。
  • 更具可扩展性 :逻辑属性适用于各种语言环境,无论是从左到右还是从右到左,都可以精确的控制 Web 布局。这为 Web 开发者提供了更广泛的可扩展性,因为他们可以使用相同的代码为不同的语言环境创建布局,并且也更容易添加新的语言支持。

总之,使用 CSS 逻辑属性可以为多语言 Web 应用或网站开发带来更高的效率和可维护性,更加精确的布局和样式,更好的代码可读性和可扩展性

逻辑属性给 CSS 带来哪些变化?

在使用 CSS 逻辑属性之前,Web 开发者首先要了解的就是 CSS 引入逻辑属性之后,对 Web 带来哪些改变。简单地划分为两个部分:坐标系属性与属性值的变化。

CSS 的坐标系的变化

在默认情况下,CSS 元素的内容是从左到右排列。但是对于某些语言或特定的排版需求,需要从右到左排列,或从上到下排列等。通常这种从左到右、从上到下的排列方向分别是沿着 Web 坐标轴的 x 轴(水平方向)和 y 轴(垂直方向)排列的。

我们都知道,在 Web 中有一个坐标系统,它分为 x 轴和 y 轴:

img

CSS 中的任一元素可以在这个坐标系统中沿着 x 轴向左或向右移动位置,也可以沿着 y 轴向上或向下移动位置。它们具有明确的物理方向:

  • x 轴方向有 leftright
  • y 轴方向有 topbottom

除此之外,CSS 中还有一个的概念,也就是我们常说的文档流(Document Flow) ,它指的是元素在 HTML 文档中的流动方向。在 HTML 文档中,元素通常从上到下(块元素)、从左到右(内联元素)依次排列。而且 Web 布局也是基于这个顺序进行排列的。

img

如果你想改变元素在文档流中的位置,就需要使用一些 Web 布局技巧,例如浮动(float)、定位(position)、Flexbox 和 Grid 布局等。

同样的,Web 中的文本也存在流的概念。在拉丁语体系中(比如英文),字母和单词从左到右流动,而段落从上到下垂直排列;在阿拉伯语体系中(比如阿拉伯语),字母和单词从右到左流动,而段落从上到下垂直排列;在传统的汉语体系中(比如中文和日文),字和词从上到下排列,而段落从右到左水平排列。

img

正如上图所示,在一个多语言 Web 应用或网站中,页面的内容和布局应该能随着 HTML 文档方向更改而自动更新。换句话说,CSS 中的流意味着方向,字母、单词和内容以及布局都需要沿着流移动。这将引导我们进入块和内联逻辑方向。

也就是说,随着 CSS 的逻辑属性的出现,CSS 的坐标系就不再以 x 轴 和 y 轴来定义,而是以 内联 (Inline)和 (Block)来区分:

  • 内联维度是在使用的书写模式中运行的文本行(文本流)所在的维度。即,对应于文本流(阅读方式)的轴线。例如,英文是从左到右的文本流(或阿拉伯文从右到左),因此内联轴是水平的;对于日文,它的阅读方式是自上而下,因此内联轴是垂直的。
  • 块维度是另一个维度,以及块(如段落)相继显示的方向。在英语和阿拉伯语中,这些是垂直的,而在任何垂直书写模式中,这些是水平的。

它们随着 CSS 的书写模式改变,如下图所示:

img

我们可以换过一种方式来理解:

  • 块轴 :主要定义网站文档(元素块)流,CSS 的书写模式 writing-mode 会影响块轴的方向;
  • 内联轴 :主要定义网站的文本流方向,也就是文本的阅读方式,CSS 的 direction 或 HTML 的dir 会影响内联轴的方向。

简单地说,writing-mode 能很好地和块轴、行内轴、阅读模式以及书写模式结合起来

img

为了更好地匹配书写模式或者说多语言的 Web 布局,我们需要从一些理念上做出改变。

首先是用“开始”和“结束”来替代以往的 TRBL(即 toprightbottomleft ):

  • 开始(start 这对应于文本的方向,并反映了文本的侧边,你将从哪里开始阅读。对于英文,开始对应于左。对于阿位伯文来说,对应于右。
  • 结束(end 这也对应于文本的方向,并反映了文本的侧边,你将在哪里结束阅读。对于英文,结束对应于右。对于阿拉伯文来说,对应于左。

img

另一个就是“逻辑维度”来替代“物理维度”。前面的内联轴、块轴、开始和结束结合起来可以构建 CSS 逻辑属性中的流相对值。即 block-startblock-endinline-startinline-end 。这几个属性也被称为逻辑维度 ,其实就是用来指定在对应轴上的开始和结束位置。它们对应的就是我们熟悉的 toprightbottomleft 几个物理方向。

img

换句话说,在 CSS 逻辑中,使用流相对值来代替相应的物理值。正如前面所述,流相对值(逻辑维度)和 CSS 的书写模式 writing-mode 或阅读方式 direction 有关。

接下来,我们通过几种典型的语言为例,来向大家阐述逻辑维度和物理维度的映射关系。 首先来看英文,英文的阅读方式一般是从左往右(即 dirction: ltrwriting-mode:horizontal-tb ),这种模式常称为 LTR (Left-To-Right)。它的内联轴是水平的,块轴是垂直的,相应的逻辑维度和物理维度映射关系如下:

img

逻辑维度物理维度
inline-startleft
inline-endright
block-starttop
block-endbottom

接着来看阿拉伯文,它的阅读方式是从右往左(即 direction: rtlwriting-mode:horizontal-tb),这种模式常称为 RTL (Right-To-Left)。它的内联轴是水平的,块轴是垂直的,相应的逻辑维度和物理维度映射关系如下:

img

逻辑维度物理维度
inline-startright
inline-endleft
block-starttop
block-endbottom

再来看日文,竖排(有点类似中国古代的汉字书写模式),对应的 writing-mode: vertical-rl 。它的内联轴是垂直的,块轴是水平的,相应的逻辑维度和物理维度映射关系如下:

img

逻辑维度物理维度
inline-starttop
inline-endbottom
block-startright
block-endleft

最后再来看蒙文,也是竖排,和日文不同的是 writing-mode: vertical-lr 。它的内联轴是垂直的,块轴是水平的,相应的逻辑维度和物理维度映射关系如下:

img

逻辑维度物理维度
inline-starttop
inline-endbottom
block-startleft
block-endright

如果你对 CSS Flexbox 和 CSS Grid 两种布局有过深入的探究的话,那么你就能轻易的发现,在 Flexbox 和 Grid 布局中流的概念比方向的概念重要得多。比如,在 Flexbox 中,不再关注方向,而是更关注主轴和侧轴:

img

上图展示的是 Flexbox 容器的 flex-direction 值为 row 时,LTR 和 RTL 相应的流方向。也就是说,使用 CSS Flexbox 构建 Web 布局时,我们不需要针对 LTR 和 RTL 提供不同的样式,它可以根据 dirdirection 自动翻转。这是一个巨大的好处!

尤其是在 CSS Grid 布局中,方向变得更无意义了。因为,网格布局中的内联轴(Inline Axis)和块轴(Block Axis)可以和网格中的行与列相映射,比如书写模式和阅读模式是 ltr(Left-To-Right)时,内联轴也称为行轴(Row Axis),块轴也称为列轴(Column Axis):

img

需要注意的是,虽然内联轴(Inline Axis)和块轴(Block Axis)会因 CSS 的书写模式或文档的阅读模式改变,但网格中的行轴和列轴是始终不变的:

img

所以,你在 Flexbox 或 Grid 布局中设置项目对齐方式时,会有 flex-startflex-endstartend 等值。

CSS 的属性和值的变化

CSS 逻辑属性给 CSS 带来的第二个方面变化是 CSS 的属性和属性值。简单地说:

  • display 随着块轴和内联轴的出现,可以设置两个值。
  • 使用 inline-sizeblock-sizemin-inline-sizemax-inline-sizemin-block-sizemax-block-size 等属性来设置容器尺寸大小。
  • 盒模型的变化,物理盒模型中以 -top-right-bottom-left 后缀结合的属性相应地被使用 -inline-start-inline-end-block-start-block-end 为后缀的逻辑属性替代。
  • toprightbottomleft 等偏移属性分别被 inset-block-startinset-inline-endinset-block-endinset-inline-start 等逻辑属性替代。
  • border-radius 的子属性 border-top-left-radiusborder-top-right-radiusborder-bottom-right-radiusborder-bottom-left-radius 等物理属性分别被 border-start-start-radiusborder-start-end-radiusborder-end-end-radiusborder-end-start-radius 等逻辑属性替代。
  • overflow-xoverflow-y 物理属性分别被 overflow-inlineoverflow-block 逻辑属性替代。
  • overscroll-behavior-xoverscroll-behavior-y 物理属性分别被 overscroll-behavior-inlineoverscroll-behavior-block 等逻辑属性替代。
  • floatclear 属性的 leftright 物理值分别被 inline-startinline-end 逻辑值替代。
  • text-align 属性的 leftright 物理值分别被 startend 逻辑值替代。
  • resize 属性的 horizontalvertical 特理值分别被 inlineblock 逻辑值替代。

下图中罗列出常见的物理属性对应的逻辑属性:

img

接下来,我们针对几个重要部分来展开阐述。

首先来看 CSS 的 display 属性,自从 CSS 中引入 inlineblock 逻辑轴的概念之后,CSS 的 display 属性可以根据它们(inlineblock)设置两个值:

img

比如:

CSS
.element {
    display: inline-flex;
    
    /* 等同着 */
    display: inline  flex;
}

你可以用下图来映射出 display 属性现有的值:

img

需要特别声明的是,CSS 的 display 的值并没有逻辑值一说,只是使用双值可以更好理解值与文档流之间的对应关系。我们曾在小册的第一节课中有过详细的阐述,这里就不再重复阐述。

接着来看 CSS 的逻辑尺寸。即:

  • widthmin-widthmax-width 分别对应的逻辑属性是 inline-sizemin-inline-sizemax-inline-size
  • heightmin-heightmax-height 分别对应的逻辑属性是 block-sizemin-block-sizemax-block-size

在多语言的 Web 应用或网站的开发中,我们应该使用逻辑尺寸来指定元素容器的尺寸。元素容器能随文本方向的改变自动调整容器的尺寸。例如:

CSS
/* 物理尺寸 */
.element--physical {
    width: 300px;
    height: 100px;
}

/* 逻辑尺寸 */
.element--logical {
    inline-size: 300px;
    block-size: 100px;
}

img

Demo 地址:https://codepen.io/airen/full/rNZgOdB

正如你所看到的,当 writing-mode 的值从 horizontal-tb 变成 vertical-lrvertical-rl 时,设置了物理尺寸的元素会自动调整容器尺寸。如下图所示:

img

再来看 CSS 的盒模型。可以说,CSS 逻辑属性对盒模型的变化是最大的,物理盒模型中的所有属性都有对应的逻辑属性。因此,在 CSS 中又有逻辑盒模型一说,它和物理盒模型是映射关系,如下图所示:

img

也就是说,在构建多语言 Web 应用或网站时,只要是用于定义容器盒子相关的样式时,都应该使用相对应的逻辑属性。比如下面这个示例:

CSS
.card {
    display: flex;
    background-color: #fff;
    border-radius: 4px;

    /* CSS 逻辑属性 */
    padding-block-start: 2rem;
    padding-block-end: 2rem;
    padding-inline-start: 2rem;
    padding-inline-end: 4rem;
    border-inline-start: 8px solid #fd622b;
}

.card img {
    border-radius: 50%;
    
    /* CSS 逻辑属性 */
    inline-size: 80px;
    block-size: 80px;
    margin-inline-end: 1.5rem;
}

.card p {
    /* CSS 逻辑属性 */
    margin-block-end: .5rem;
}

.card h4 {
    /* CSS 逻辑属性 */
    margin-block-end: 1.5rem;
}

/* RTL */
[dir="rtl"] {
    direction: rtl;
    font-family: 'Cairo', sans-serif;
}

img

Demo 地址:https://codepen.io/airen/full/QWVRyGL

同样的,CSS 逻辑盒模型中的相关属性都会因 dirdirectionwriting-mode 属性的值有所差异,具体的如下图所示:

img

有了这些基础,你就可以使用 CSS 逻辑属性来开发一个多语言的 Web 应用或网站,例如 @Alaa Abd El-Rahim 在 Codepen 分享的一个示例。我在他的基础上 Fork 了一份,并在该示例的“英文”、“日文”、“阿拉伯文”的基础上新增了“中文”。这样就构建了一个四国语言的 Web 页面:

img

Demo 地址:https://codepen.io/airen/full/LYJoGQd (详细解读可以阅读《Web 中的向左向右:Web 布局中 LTR 切换到 RTL 常见错误》一文!)

示例代码就不在这里展示了,感兴趣的同学可以查看 Demo 的源码!

CSS 逻辑属性的简写属性

在 CSS 中有很多属性具有简写属性(子属性),比如我们熟悉的 marginpaddingborderborder-radiusoverflowoverscroll-behavior 等。拿 margin 为例吧,它可以拆分出 margin-topmargin-rightmargin-bottommargin-left 四个子属性。

其实,在 CSS 逻辑属性中也有这样的概念。

margin 和 padding 简写属性

CSS 逻辑属性中 margin 的简写属性有 margin-blockmargin-inline

CSS
.margin--logical {
    margin-block: 4ch 2ch;
    margin-inline: 2ch 4ch;
    
    /* 等同于 */
    margin-block-start: 4ch;
    margin-block-end: 2ch;
    
    margin-inline-start: 2ch;
    margin-inline-end: 4ch;
}

如果 -start-end 对应的属性值相同,那么使用简写属性时,可以只设置一个值,比如:

CSS
.margin--logical {
    margin-block: 2ch;
    margin-inline: 4ch;
    
    /* 等同于 */
    margin-block-start: 2ch;
    margin-block-end: 2ch;
    
    margin-inline-start: 4ch;
    margin-inline-end: 4ch;
}

逻辑属性 paddingmargin 类似:

  • padding-inlinepadding-inline-startpadding-inline-end 的简写属性;
  • padding-blockpadding-block-startpadding-block-end 的简写属性。

border 简写属性

我们知道物理属性 border 可以拆分为:

  • 边框粗细:border-width ,它又可以拆分为 border-top-widthborder-right-widthborder-bottom-widthborder-left-width
  • 边框颜色:border-color ,它又可以拆分为 border-top-colorborder-right-colorborder-bottom-colorborder-left-color
  • 边框样式:border-style ,它又可拆分为 border-top-styleborder-right-styleborder-bottom-styleborder-left-style

它相对于 paddingmargin 要复杂得多。

逻辑属性 border 也可以根据颜色(color)、粗细(width)和样式(style)进行拆分,即:

  • 边框粗细:border-block-widthborder-inline-width ,它们又分别可以拆分出 border-block-start-widthborder-block-end-widthborder-inline-start-widthborder-inline-end-width
  • 边框颜色:border-block-colorborder-inline-color ,它们又分别可以拆分出 border-block-start-colorborder-block-end-colorborder-inline-start-colorborder-inline-end-color
  • 边框样式:border-block-styleborder-inline-style ,它们又分别可以拆分出 border-block-start-styleborder-block-end-styleborder-inline-start-styleborder-inline-end-style

来看一个边框颜色的示例:

CSS
.border-color--logical {
    border-block-color: #09f #f36;
    
    /* 等同于 */
    border-block-start: #09f;
    border-block-end: #f36;
}

但需要注意的是,逻辑边框和逻辑内外、逻辑外边距有一点不同,使用逻辑边框 border-blockborder-inline 子属性设置元素边框时,只能设置同一方向相同的边框样式。例如:

CSS
.border--logical {
    border-block: 2px solid orange;
    border-inline: 4px dashed;
}

如果每条边框样式规则不同,则需要分别使用 border-block-startborder-block-endborder-inline-startborder-inline-end 。例如:

CSS
.border--logical {
    border-block-start: 4ch solid red;
    border-block-end: 3ch dashed yellow;
    border-inline-start: 4ch double;
    border-inline-end: 3ch groove orange;
}

img

Demo 地址:https://codepen.io/airen/full/MWqdybO

简写的 border-radius 属性

从小册的《你不知道的 border-radius》课程中可以得知,border-radius 的子属性有:

  • 左上角:border-top-left-radius
  • 右上角:border-top-right-radius
  • 右下角:border-bottom-right-radius
  • 左下角:border-bottom-left-radius

例如:

CSS
.border-radius {
    border-radius: 30px 50px 50px 100px;
    
    /* 等同于 */
    border-top-left-radius: 30px;
    border-top-right-radius: 50px;
    border-bottom-right-radius: 50px;
    border-bottom-left-radius: 100px;
}

.border-radius {
    border-radius: 30px 50px 100px 50px / 100px 50px 50px 50px;
    
    /* 等同于 */
    border-top-left-radius: 30px 100px;
    border-top-right-radius: 50px 50px;
    border-bottom-right-radius: 100px 50px;
    border-bottom-left-radius: 50px 50px;
}

img

但对于逻辑属性 border-radius 的子属性,并不像 marginpaddingborder 等属性,它没有 border-block-radiusborder-inline-radius 子属性。逻辑属性 border-radius 的子属性:

  • border-start-start-radius
  • border-start-end-radius
  • border-end-end-radius
  • border-end-start-radius

img

你可能会对 -start-start-start-end 等感到困惑。其实它和物理属性中的 -top-left-top-right 等是相似的:出现在前面的 startend 是指块轴(Block Axis)的起始和结束位置;出现在后面的 startend 是指内联轴(Inline Axis)的起始和结束位置。

CSS
/* 物理 CSS border-radius */
.border-radius--physical {
  border-top-left-radius: 5rem 10rem;
  border-top-right-radius: 2rem 1rem;
  border-bottom-right-radius: 4rem 2rem;
  border-bottom-left-radius: 3rem 5rem;
}

/* 逻辑 CSS border-radius */
.border-radius--logical {
  border-start-start-radius: 5rem 10rem;
  border-start-end-radius: 2rem 1rem;
  border-end-end-radius: 4rem 2rem;
  border-end-start-radius: 3rem 5rem;
}

img

Demo 地址:https://codepen.io/airen/full/KKxLMxE

需要注意的是,在 CSS 中逻辑属性 border-radius 并没有简写属性。因此,在开发多语言 Web 应用或网站时,最好是使用拆分后的逻辑 border-radius 属性,尤其是四个角的圆角半径不同之时。

inset 简写属性

对于定位元素(即 position 设置非 static 的元素)可以使用 toprightbottomleft 来设置偏移量。这四个属性有一个简写属性 inset

CSS
.inset {
    position: absolute;
    inset: 10px 20px 30px 40px;
    
    /* inset 等同于 */
    top: 10px;
    right: 20px;
    bottom: 20px;
    left: 40px;
}

看起来很方便。只不过,inset 属性是一个物理属性。相应的 CSS 逻辑属性是:

  • top 映射 inset-block-start
  • right 映射 inset-inline-end
  • bottom 映射 inset-block-end
  • left 映射 inset-inline-start

img

不过,CSS 逻辑属性中可以使用 inset-blockinset-inline 来设置偏移量,它们分别是:

  • inset-blockinset-block-startinset-block-end 的简写属性;
  • inset-inlineinset-inline-startinset-inline-end 的简写属性。

例如:

CSS
.inset {
    position: absolute;
    
    inset-block: 20px 30px;
    inset-inline: 40px 50px;
    
    /* 等同于 */
    inset-block-start: 20px;
    inset-block-end: 30px;
    inset-inline-start: 40px;
    inset-inline-end: 50px;
}

避免使用简写属性

如果你正在开发一个多语言 Web 应用或网站,那么应该尽可能地在代码中不使用 CSS 的简写属性,尤其是四个方向的值不相等的情况下。比如 bordermarginpaddingborder-radius 等属性。因为它们始终会代表着物理方向,例如下面这段代码:

CSS
.element {
    border: 1px solid #f36;
    border-width: 1ch 2ch 3ch 4ch;
    margin: 1rem 2rem 3rem 4rem;
    padding: 1rem 2rem 3rem 4rem;
    border-radius: 1rem 2rem 3rem 4rem;
}

img

Demo 地址: https://codepen.io/airen/full/PodvGbX

你会发现,改变 writing-mode 时,元素的 borderborder-radiusmarginpadding 并不会受到任何影响。这对于多语言 Web 应用或网站是非常危险的。反之,如果换成拆分后的子属性(逻辑属性),结果就完全不一样:

CSS
.element--physical {
    border: 1px solid #f36;
    border-width: 1ch 2ch 3ch 4ch;
    margin: 1rem 2rem 3rem 4rem;
    padding: 1rem 2rem 3rem 4rem;
    border-radius: 1rem 2rem 3rem 4rem;
}

.element--logical {
    border: 1px solid #f36;
    border-block-width: 1ch 3ch;
    border-inline-width: 4rem 2rem;
    margin-block: 1rem 3rem; 
    margin-inline: 4rem 2rem;
    padding-block: 1rem 3rem;
    padding-inline: 4rem 2rem;
    border-start-start-radius: 1rem;
    border-start-end-radius: 2rem;
    border-end-end-radius: 3rem;
    border-end-start-radius: 4rem; 
}

img

Demo 地址:https://codepen.io/airen/full/dyqEpdK

简而言之,在开发多语言 Web 应用或网站时,虽然简写的 CSS 属性的使用能使你的代码更干净,但不建议直接使用,因为我们所熟悉的简写 CSS 属性都是物理属性,它和相对应的简写逻辑属性是完全不同的

换句话说,在开发多语言 Web 应用或网站时,请尽量不要使用盒模型相关的简写属性,即 borderpaddingmarginborder-radius 等,同时也包括 inset 属性。

小结

如果在构建 Web 应用或页面时,面对的仅是单一语言,那么使用 CSS 物理属性并无大碍,而且也不会影响整个 Web 应用的布局。你使用 CSS 逻辑属性来替代物理属性也可以实现同等效果。如果你构建的 Web 应用是要处理多语言,那么物理属性带来的局限性就非常的明显,而且也会造成阅读上的不便,这个时候 CSS 逻辑属性起到的作用就非常大。

逻辑属性的主要优点是,它是一组用于根据文本流方向动态处理布局的属性,它们使得在不同的书写模式之间切换更加容易,并且它们是相对于流而不是固定方向来工作的,这使得布局更具灵活性和可重用性。但它们也可能会给开发者带来一定的学习曲线和混淆。

总之,CSS 逻辑属性是一种强大的工具,可以帮助开发者轻松处理国际化网站的布局,并保持代码的简洁和易读性。