[译]CSS逻辑属性与值

1,197 阅读13分钟

原文链接:CSS Logical Properties and Values | CSS-Tricks

原文作者:Ollie Williams, Author at CSS-Tricks

译者:Giria

个人翻译,如有错误,欢迎指正

现在跨浏览器支持正处于重要转折点,正是查看逻辑属性和值的好时机。如果您使用多种语言创建网站,逻辑属性和值将非常有用。即使没打算这么干,仍然有一些方便的速记内容值得了解。

[译者注]:CSS 逻辑属性与值CSS 的一个模块,其引入的属性与值能做从逻辑角度控制布局,而不是从物理、方向或维度来控制。

--CSS 逻辑属性与值 - CSS(层叠样式表) | MDN (mozilla.org)

PS:推荐一个可以随时查看css属性支持性的网站:Can I use... Support tables for HTML5, CSS3, etc

例如,为了居中某些东西,我早就记不清写过多少次下面的语句了:

.thing {
  margin-left: auto;
  margin-right: auto;
}

我们可以把它合并成一行,比如 margin: 0 auto;

但这样写会导致我们不得不将顶部和底部的边距也混入其中。作为替代,我们可以使用 margin-inline 逻辑属性只选择左右边距。

.thing {
    margin-inline: auto;
    background-color: #4A90E2;
    width: 100px;
    height: 100px;
}

image.png

开始将事物视为“内联”或“块”

上面的演示很整洁,对吧?

设置 margin-inline 属性将同时设置 margin-leftmargin-right

同样,margin-block 属性会同时设置 margin-topmargin-bottom

而且这不仅仅只适用于margin。逻辑属性具有类似的简写方式来设置borderpadding

因此,如果您的设计稿要求仅在侧面有边框,您可以使用 border-inline 而不是单独处理每个物理方向。

p {
  padding-inline: 24px;
  padding-block: 32px;
}

.border-block {
   border-block: 8px solid blue;
}

.border-inline {
  border-inline: 8px solid blue;
}

body {
  display: flex;
  gap: 24px;
  justify-content: space-evenly;
  align-items: center;
  height: 100vh;
  flex-wrap: wrap;
  font-family: system-ui;
  background-color: rgb(220,230,240);
  height: 100vh;
}

image.png

image.png

因此,我们现在知道我们正在处理inlineblock方向而不是物理方向。inline处理左右方向,而block管理顶部和底部。

当写入模式改变时,它们的管理方向将被交换。

注意方向和书写方式

到目前为止,我们看到的都是些 CSS 逻辑属性的示例。它们以一种新的方式编写,被用于像margin和padding这样的CSS属性,放弃了物理方向(即左、右、上和下)。

CSS 是在以英语为核心语言的情况下开发的,英语是从左到右书写和阅读的。不过,并非所有语言都如此。例如,阿拉伯语是从右到左阅读的。这就是 HTML 具有 dir 属性的原因。

<html dir="rtl">

CSS 有一个等效的属性(尽管建议使用 HTML 属性以防 CSS 无法加载):

.foreign-language { direction: rtl; }

Two cards, one in english and one in arabic, Both cards have a subtitle in gray above a main heading in a larger black font. The english goes from left to right and indicates the direction with an arrow below the card. The arabic direction is reverse of the english.

中文、日文、韩文和蒙古文可以从左到右横写,也可以从上到下竖写。这些语言的大多数网站都是横向编写的,与英语相同。

相比之下,垂直书写在日本网站上更为常见。一些站点混合使用垂直和水平文本。

竖写时,中文、日文和韩文以右上角为起点书写,而蒙古文则从左到右阅读。这正是我们在 CSS 中拥有writing-mode 属性的原因,它包括以下值:

  • horizontal-tb: 这是默认值,为英语或法语等语言设置从左到右的方向,以及阿拉伯语等从右到左的语言。 tb 代表“从上到下”
  • vertical-rl: 对于中文、日文和韩文等语言,这将在垂直方向上将方向更改为从右到左,即从右上角开始阅读。
  • vertical-lr:用于从左到右的垂直语言,如蒙古语。

CSS 逻辑属性提供了一种编写上下文 CSS 的方法。

使用逻辑属性时,间距和布局取决于书写模式和方向(无论是由 CSS 还是 HTML 设置)。因此,可以跨不同语言重用 CSS 样式。

例如,BBC 新闻用十多种语言重建了他们的网站。这比让用户依赖自动翻译更好的体验。这也意味着他们可以更好地迎合世界不同地区的内容。不过,不同地区的视觉样式大致相同。

让我们看下面的例子,看看物理属性的缺点。使用物理 margin-left 属性(以红色显示),一切在英文中看起来都不错。

如果您要重用 CSS 但将书写模式更改为 rtl(显示在底部),则文本和图标之间没有空格,并且文本左侧有多余的空白。

我们可以通过使用逻辑属性来避免这种情况。

Two buttons, both with an envelope icon and a label. The left-to-right version of the button on top shows the spacing between the icon and the label. The right-to-left version shows the spacing to the left of both the label and icon.

逻辑属性和值如此有用的原因:它们会自动迎合语言的上下文。

在像英语这样的从左到右的语言中, margin-inline-start 将设置左侧边距。对于像阿拉伯语、乌尔都语或希伯来语这样的从右到左的语言,它会设置右手边距——这解决了上面例子中的布局问题。这是从右到左处理的。

如果您有垂直文本,margin-inline-start 将迎合该上下文,在顶部添加边距,这是您以任何垂直语言开始阅读的地方(这就是它被称为 margin-inline-start 的原因——只要想想看关于你从哪个方向开始阅读)。

inline的方向根据元素的写入模式而变化。当设置了垂直书写模式时,它处理垂直方向的顶部和底部。看看事情是如何转变的?

img

逻辑属性和值的完整列表

这里还有许多具有逻辑替代能力的 CSS 属性。 Adrian Roselli 有一个方便的可视化,你可以在我们所熟悉的物理 CSS 属性和它们的逻辑属性等效之间切换。当方向为 ltr 且写入模式为水平 tb 时,这是一种将逻辑属性和物理属性进行可视化映射的好方法。

Example: Logical Properties Mapping (codepen.io)

image.png

image.png

让我们进一步理解这些,将每个物理 CSS 属性并排映射到其逻辑伙伴。本文中表格在左栏中显示了传统的物理 CSS,在右栏中显示了它们的逻辑等效项(使用从左到右的水平映射)。但请记住,逻辑属性的全部意义在于它们会根据上下文而变化!

调整大小

在水平书写模式下, inline-size 设置元素的宽度,而 block-size 设置高度。

在垂直书写模式下,情况正好相反:inline-size 设置高度,block-size 设置宽度。

Example: block-size & inline-size (codepen.io)

物理属性逻辑属性
widthinline-size
max-widthmax-inline-size
min-widthmin-inline-size
heightblock-size
max-heightmax-block-size
min-heightmin-block-size

调整大小的逻辑属性具有良好的跨浏览器支持

调整边框

下文的一切都在现代浏览器中具有可靠的跨浏览器支持

物理属性逻辑属性
border-topborder-block-start
border-bottomborder-block-end
border-leftborder-inline-start
border-rightborder-inline-end

下面是一个使用 border-inline-start 的示例,文字根据需要显示为英语、阿拉伯语和中文。

Example : border-inline-start (codepen.io)

blockquote {
  border-inline-start: solid 4px #DE354C;
  padding-inline: 16px;
  background-color: rgb(230,230,230);
 padding-block: 8px;
}

.vertical {
  writing-mode: vertical-rl;
  font-size: 20px;
  font-family: Microsoft JhengHei,微軟正黑體,Heiti TC,黑體-繁,sans-serif;
  line-height: 2;
  text-align: justify;
}

image.png

这是一个将 border-block-start 设置为点线和将 border-block-end 设置为虚线的例子:

blockquote {
  border-block-start: dotted 10px #41B3A3;
  border-block-end: dashed 8px #E27D60;
  min-block-size: 50px;
  max-inline-size: 300px;
  margin-block-start: 24px;
  padding-block: 4px;
  font-size: 18px;
}

.vertical {
  writing-mode: vertical-rl;
  font-size: 20px;
  font-family: Microsoft JhengHei,微軟正黑體,Heiti TC,黑體-繁,sans-serif;
  line-height: 2;
  text-align: justify;
}

[dir="rtl"] {
  font-family: 'Tajawal', sans-serif;
}

image.png

还有用于单独设置边框颜色、宽度和样式的逻辑属性:

物理属性逻辑属性
border-top-colorborder-block-start-color
border-top-widthborder-block-start-width
border-top-styleborder-block-start-style

所以再一次重申,我们只要思考"inline"和“block”而不是物理方向,譬如lefttop。对于边框,我们还拥有简化版本的逻辑属性:

物理属性逻辑属性
border-top and border-bottomborder-block
border-left and border-rightborder-inline

调整外边距

这里有一些单独的外边距逻辑属性:

物理属性逻辑属性
margin-topmargin-block-start
margin-bottommargin-block-end
margin-leftmargin-inline-start
margin-rightmargin-inline-end

这些逻辑属性具有全面的现代跨浏览器支持,包括三星 Internet,并且自 12.2 以来就已经在 Safari 中得到支持。

而且,记住,我们同样拥有简化版本:

物理属性逻辑属性
margin-top and margin-bottommargin-block
margin-left and margin-rightmargin-inline

调整内边距

内边距与外边距非常相似。用内边距替换外边距,我们得到了相同的属性对应列表。

物理属性逻辑属性
padding-toppadding-block-start
padding-bottompadding-block-end
padding-leftpadding-inline-start
padding-rightpadding-inline-end
padding-top and padding-bottompadding-block
padding-left and padding-rightpadding-inline

就像外边距一样,内边距的逻辑属性具有良好的跨浏览器支持

调整定位

如果你需要往某个方向偏移某个元素的位置?我们也可以声明这些逻辑。

物理属性逻辑属性
topinset-block-start
bottominset-block-end
leftinset-inline-start
rightinset-inline-end
top and bottominset-block
left and rightinset-inline

在水平书写模式(从左到右,或从右到左)下,inset-block-start 相当于设置 top,而 inset-block-end 相当于设置 bottom。在水平书写模式下,从左到右方向,inset-inline-start 等价于设置left,而 inset-inline-end 等价于设置right,从右到左的语言反之亦然。

相反,对于垂直书写模式,inset-inline-start 相当于设置 top,而 inset-inline-end 相当于设置bottom。如果将writing-mode 设置为vertical-rl,则inset-block-start 相当于right,inset-block-end 相当于left。如果 write-mode 设置为 vertical-lr,则情况相反,因此 inset-block-start 等效于 left。

逻辑属性书写模式等价于
inset-block-startHorizontal LTRtop
inset-block-startHorizontal RTLtop
inset-block-startVertical LTRleft
inset-block-startVertical RTLright

以下是用于绝对定位的相同 CSS 代码在四种不同书写方向中的可视化示例:

Example: inset-inline-end & inset-block-end (codepen.io)

.outer {
  border: solid 4px black;
  block-size: 100px;
  inline-size: 100px;
  position: relative;
}

.inner {
  block-size: 20px;
  inline-size: 20px;
  background-color: #4A90E2;
  position: absolute;
  inset-block-end: 4px;
  inset-inline-end: 20px;
}

.vertical-rl {
  writing-mode: vertical-rl;
}

.vertical-lr {
  writing-mode: vertical-lr;
}

body {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin: 16px;
}

image.png

所有现代浏览器都支持定位的逻辑属性,但最近才在 Safari中使用。

还有一个新的简写,用于在一行代码中设置所有四个偏移量。这是一个使用 inset 作为简写的示例,用于一次性设置顶部、底部、左侧和右侧以创建整页叠加效果:

div {
  background-color: black;
  position: fixed;
  inset: 0;
}

我听说 inset 被错误地称为逻辑属性。但是,在 DevTools 中快速浏览会发现它实际上是物理值的简写,而不是逻辑属性:

img

它实际做的是定义物理偏移(即左、右、上和下)而不是逻辑偏移(即inline、block、start和end)。显然,如果您想为所有四个边设置相同的值,如上例所示,这和逻辑属性没有关系。

inset: 10px 20px 5px 8px; /* 物理属性的简写,而不是逻辑属性的简写  */

调整文字对齐方式

文本对齐的逻辑属性具有良好的浏览器支持,并且已经存在多年。使用英语时, text-align: start text-align: left 相同,而 text-align: endtext-align: right相同。如果将 dir 属性设置为 rtl,它们会切换方向然后 text-align: start 将使文本向右对齐。

物理属性值书写模式等价于
startLTRleft
startRTLright
endLTRright
endRTLleft

调整边框圆角

到目前为止,我们所看到的一切都有不错的浏览器支持。但是,还有一些其他逻辑属性的支持仍在进行中,边框圆角半径就是其中之一。换句话说,我们可以使用逻辑属性为元素的不同角设置不同的 border-radius 值,但浏览器支持并不好

物理属性逻辑属性
border-top-left-radiusborder-start-start-radius
border-top-right-radiusborder-start-end-radius
border-bottom-left-radiusborder-end-start-radius
border-bottom-right-radiusborder-end-end-radius

Example: logical border-radius (codepen.io)

p {
  background-color: rgb(210, 230,250);
  border-start-end-radius: 20px;
  border-end-end-radius: 20px;
  inline-size: fit-content;
  padding-inline: 16px;
  padding-block: 8px;
  font-size: 18px;
}

.vertical {
  writing-mode: vertical-rl;
  font-family: Microsoft JhengHei,微軟正黑體,Heiti TC,黑體-繁,sans-serif;
  line-height: 2;
  text-align: justify;
  font-size: 20px;
}

*[dir="rtl"] {
  font-family: 'Tajawal', sans-serif;
}

image.png

调整浮动

在我写这篇文章的时候,与浮动相关的逻辑属性值的浏览器支持相当糟糕。只有 Firefox 支持 inline-start inline-end 作为浮动值。

物理属性值逻辑属性值
float: leftfloat: inline-start
float: rightfloat: inline-end
clear: leftclear: inline-start
clear: rightclear: inline-end

Example: inline-start logical value for floats (codepen.io)

image.png

其他逻辑属性

有针对overflowresize的逻辑属性,但它们目前的浏览器支持相当不完备。

物理属性值逻辑属性值
resize: verticalresize: block
resize: horizontalresize: inline
overflow-yoverflow-block
overflow-xoverflow-inline

深层挖掘

我们探索了将属性视为“逻辑”意味着什么,然后将所有新的逻辑属性和值映射到对应的物理属性。这难道不炫酷吗!但是如果你想更深入地了解 CSS 逻辑属性和值,这里有很多资源值得一看。

  • “RTL Styling 101”(Ahmad Shadeed):如果您正在处理阿拉伯语或其他从右到左的语言,这是一个很好的资源。 Ahmad 涵盖了所有内容,从逻辑属性到使用特定布局技术(如 flexbox 和 grid)时的注意事项。

  • text-combine-upright (CSS-Tricks):如果您正在处理垂直文本,您是否知道此属性可以旋转文本并将多个字符压缩到单个字符的空间中?在某些字符需要组合在一起,但仍需要以垂直书写模式这样特定情况下,这是一种很好的改进。

如果您想在网络上查看一些真实的垂直排版示例,请查看水平和垂直写作网络奖。里面有很多很棒的东西。

总结

您是否需要急于从代码库中交换所有物理属性?如果不是这样,其实在你的工作中开始使用逻辑属性和值也没有坏处。正如我们所见,浏览器支持几乎已经完备。即使你在一个只有英文的网站上工作,也没有理由不使用它们。