逻辑属性

CSS 播客 - 012:逻辑属性

一个非常常见的用户界面模式是带有辅助内联图标的文本标签。

图标位于文本的左侧,两者之间有一个小间距,由图标上的 margin-right 提供。但有一个问题,因为这仅在文本方向从左到右时才有效。如果文本方向更改为从右到左(这是阿拉伯语等语言的阅读方式),则图标将紧挨着文本。

如何在 CSS 中解决这个问题?逻辑属性允许您解决这些情况。在许多其他好处中,它们为国际化提供免费的自动支持。它们帮助您构建更具弹性、更具包容性的前端。

术语

top、right、bottom 和 left 的物理属性是指视口的物理尺寸。您可以将这些属性想象成地图上的罗盘玫瑰。另一方面,逻辑属性是指框的边缘,因为它们与内容流相关。因此,如果文本方向或书写模式发生变化,它们也会发生变化。这是与定向样式的一个重大转变,它在样式化我们的界面时给了我们更大的灵活性。

块流

块流是内容块放置的方向。例如,如果有两个段落,块流就是第二个段落将要放置的位置。在英语文档中,块流是从上到下。在段落文本相互跟随(从上到下)的上下文中考虑这一点。

Three blocks, div elements, with a down arrow, labelled 'block flow'

内联流

内联流是文本在句子中流动的方向。在英语文档中,内联流是从左到右。如果要将网页的文档语言更改为阿拉伯语 (<html lang="ar">),则内联流将是从右到左。

Three words, 'she sells seashells', with a left-to-right arrow, labelled 'inline flow'

文本按照文档的书写模式确定的方向流动。您可以使用 writing-mode 属性更改文本的布局方向。这可以应用于整个文档,也可以应用于单个元素。

流相关

在 CSS 的历史中,我们只能相对于其边的方向应用边距等属性。例如,margin-top 应用于元素的物理顶部。使用逻辑属性,margin-top 变为 margin-block-start。这意味着,无论语言和文本方向如何,块流都具有适当的边距规则。

A diagram showing all the different sizes of a box and where each sizing section starts and ends

尺寸调整

为了防止元素超出特定宽度或高度,请编写如下规则

.my-element {
  max-width: 150px;
  max-height: 100px;
}

与流相关的等效项是 max-inline-sizemax-block-size。您也可以使用 min-block-sizemin-inline-size 代替 min-heightmin-width

使用逻辑属性,最大宽度和高度规则将如下所示

.my-element {
  max-inline-size: 150px;
  max-block-size: 100px;
}

起始和结束

不要使用诸如 top、right、bottom 和 left 之类的方向,而要使用 start 和 end。这为您提供了 block-start、inline-end、block-end 和 inline-start。这些允许您应用对书写模式更改做出响应的 CSS 属性。

例如,要将文本向右对齐,您可以使用此 CSS

p {
  text-align: right;
}

如果您的目标不是与物理右侧对齐,而是与阅读方向的起始位置对齐,则这没有帮助。使用逻辑值,有更有效的 startend 值,它们映射到文本方向。文本对齐规则现在看起来像这样

p {
  text-align: end;
}

间距和定位

用于 marginpaddinginset 的逻辑属性使定位元素以及确定这些元素在不同书写模式下如何相互交互变得更容易和更高效。与 margin 和 padding 相关的属性仍然是到方向的直接映射,但关键区别在于,当书写模式更改时,它们也会随之更改。

.my-element {
  padding-top: 2em;
  padding-bottom: 2em;
  margin-left: 2em;
  position: relative;
  top: 0.2em;
}

这通过 padding 添加了一些垂直内部空间,并通过 margin 将其从左侧推出。top 属性也将其向下移动。使用逻辑属性等效项,它将如下所示

.my-element {
  padding-block-start: 2em;
  padding-block-end: 2em;
  margin-inline-start: 2em;
  position: relative;
  inset-block-start: 0.2em;
}

这通过 padding 添加了一些内联内部空间,并通过 margin 将其从内联开始位置推出。inset-block 属性将其从块开始位置向内移动。

inset-block 属性不是逻辑属性中唯一的简写选项。此规则可以使用 margin 和 padding 属性的简写版本进一步简化。

.my-element {
  padding-block: 2em;
  margin-inline: 2em 0;
  position: relative;
  inset-block: 0.2em 0;
}

边框

添加 borderborder-radius 也可以使用逻辑属性来完成。要在底部和右侧添加边框,并在右手侧添加半径,您可以编写如下规则

.my-element {
  border-bottom: 1px solid red;
  border-right: 1px solid red;
  border-bottom-right-radius: 1em;
}

或者,您可以使用如下逻辑属性

.my-element {
  border-block-end: 1px solid red;
  border-inline-end: 1px solid red;
  border-end-end-radius: 1em;
}

border-end-end-radius 中的 end-end 是块结束内联结束。

单位

逻辑属性引入了两个新单位:vivbvi 单位是视口大小在内联方向上的 1%。非逻辑属性等效项是 vwvb 单位是视口在块方向上的 1%。非逻辑属性等效项是 vh

这些单位将始终映射到阅读方向。例如,如果您希望元素占用视口可用内联空间的 80%,则如果书写模式为垂直,则使用 vi 单位将自动将该大小切换为从上到下。

务实地使用逻辑属性

逻辑属性和书写模式不仅仅用于国际化。您可以使用它们来生成更通用的用户界面。

如果您的图表在 X 轴和 Y 轴上都有标签,您可能希望 Y 标签上的文本垂直读取。

由于演示中的 Y 轴标签的 writing-modevertical-rl,因此您可以在两个标签上使用相同的 margin 值。margin-block-start 值适用于两个标签,因为块起始位置对于 Y 轴位于右侧,对于 X 轴位于顶部。块起始侧具有红色边框,以便您可以看到它们。

解决图标问题

既然我们已经介绍了逻辑属性,那么可以将这些知识应用于我们开始的设计问题。

p {
  display: inline-flex;
  align-items: center;
}

p svg {
  width: 1.2em;
  height: 1.2em;
  margin-right: 0.5em;
  flex: none;
}

边距已应用于图标元素的右侧。为了使图标和文本之间的间距支持所有阅读方向,需要改用 margin-inline-end 属性。

p {
  display: inline-flex;
  align-items: center;
}

p svg {
  width: 1.2em;
  height: 1.2em;
  margin-inline-end: 0.5em;
  flex: none;
}

现在,无论阅读方向如何,图标都会正确定位自身和调整间距。

检查您的理解情况

测试您对逻辑属性的知识

当您用手书写时,您的手腕沿着哪个逻辑轴移动?

内联
单词以内联方式流动,因此您的手在书写时也必须移动。
内容以块的形式流动,当您结束一种内容类型并开始另一种内容类型时,您的手腕会沿着此轴移动。

检查所有可以从逻辑属性中受益的项目

颜色
当文档书写模式更改时,颜色不会更改。
对齐
示例:flex-startblock-endinline-start
阴影
当文档书写模式更改时,阴影不会更改。
框边
示例:block-startinline
尺寸
示例:inline-sizemax-block-size
框角
示例:border-end-end-radius

单词的哪个逻辑侧面带有下划线?

内联起始
这会将下划线放在英语单词的左侧。
内联结束
这会将下划线放在英语单词的右侧。
块起始
这会将下划线放在英语单词的顶部。
块结束
CSS 为您完成此定位非常好。