使用流相关简写的逻辑布局增强

Chromium 的新逻辑属性简写和新的 inset 属性。

自 Chromium 69(2018 年 9 月 3 日)起,逻辑属性和值已帮助开发者通过逻辑而非物理方向和尺寸样式来保持对其国际布局的控制。在 Chromium 87 中,简写和偏移已发布,使这些逻辑属性和值更易于编写。这使 Chromium 赶上了 Firefox,后者自 66 版本以来就支持简写 since 66。Safari 已在其 技术预览版中准备就绪。

Latin, Hebrew and Japanese are shown rending placeholder text within a device frame. Arrows and colors follow the text to help associate the 2 directions of block and inline.

文档流

如果您已经熟悉逻辑属性、内联轴和块轴,并且不需要复习,则可以 跳过。否则,这里有一个简短的复习。

在英语中,字母和单词从左到右流动,而段落从上到下堆叠。在繁体中文中,字母和单词从上到下,而段落从右到左堆叠。仅在这两种情况下,如果我们编写 CSS 将“margin top”放在段落上,我们仅适当地间隔 1 种语言样式。如果页面从英语翻译成繁体中文,则边距很可能在新垂直书写模式下没有意义。

因此,盒子的物理侧在国际上不是很有用。因此开始了支持多种语言的过程;了解盒子模型的物理侧与逻辑侧。

您是否曾在 Chrome DevTools 中检查过 p 元素?如果是这样,您可能已经注意到,默认的用户代理样式不是物理的,而是逻辑的。

p {
  margin-block-start: 1em;
  margin-block-end: 1em;
  margin-inline-start: 0px;
  margin-inline-end: 0px;
}

来自 Chromium 用户代理样式表的 CSS

边距不像英语读者可能认为的那样在顶部或底部。它是 block-startblock-end!这些逻辑属性类似于英语读者的顶部和底部,但也类似于日语读者的右侧和左侧。编写一次,即可在任何地方工作。

正常流是指网页有意成为这种多方向性的一部分。当页面内容根据文档方向更改而更新时,布局及其元素被认为在流中。在 MDN 上或在 CSS Display Module 规范中阅读有关“在流中”和“不在流中”的更多信息。虽然逻辑属性不是必须在流中,但当方向性改变时,它们会为您完成大部分繁重的工作。流意味着方向,字母、单词和内容需要沿着该方向行进。这使我们了解了块和内联逻辑方向。

块方向是新内容块遵循的方向,就像问自己“下一个段落放在哪里?”一样。您可以将其视为“内容块”或“文本块”。每种语言都安排其块并沿着各自的 block-axis 对其进行排序。block-start 是段落首先放置的边,而 block-end 是新段落流向的边。

例如,在传统日语手写中,块方向从右到左流动

内联方向是字母和单词的方向。考虑您书写时手臂和手的移动方向;它们沿着 inline-axis 移动。inline-start 是您开始书写的边,而 inline-end 是书写结束或换行的边。在上面的视频中,inline-axis 是从上到下,但在下一个视频中,inline-axis 从右到左流动。

所谓 flow-relative 流相关,意味着为一种语言编写的样式将是上下文相关的,并适当地应用于其他语言。内容将相对于其交付的语言流动。

新的简写

以下一些简写不是浏览器的新功能,而是通过利用能够一次在块或内联边缘上设置值来更轻松地编写样式的方法。inset-* 逻辑属性确实带来了新功能,因为以前没有使用逻辑属性指定绝对位置的长手方法。不过,插页和简写非常自然地结合在一起(呵呵),我将立即告诉您所有在 Chromium 87 中推出的新逻辑属性功能。

外边距简写

没有推出新功能,但推出了一些非常方便的简写
margin-blockmargin-inline

完整写法
margin-block-start: 2ch;
margin-block-end: 2ch;
新简写
margin-block: 2ch;
/* or */
margin-block: 2ch 2ch;

以前没有“顶部和底部”或“左侧和右侧”的简写……直到现在!您可能使用 margin: 10px; 的简写引用所有 4 个边,而现在您可以使用逻辑属性简写轻松引用 2 个互补边。

完整写法
margin-inline-start: 4ch;
margin-inline-end: 2ch;
新简写
margin-inline: 4ch 2ch;

内边距简写

没有推出新功能,但推出了更多非常方便的简写
padding-blockpadding-inline


完整写法
padding-block-start: 2ch;
padding-block-end: 2ch;
新简写
padding-block: 2ch;
/* or */
padding-block: 2ch 2ch;

以及 inline 内联互补简写集

完整写法
padding-inline-start: 4ch;
padding-inline-end: 2ch;
新简写
padding-inline: 4ch 2ch;

Inset 和简写

物理属性 toprightbottomleft 都可以写为 inset 属性的值。position 的任何值都可以从使用 inset 设置边中受益。

.cover {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  inset: 0;
}


物理完整写法
position: absolute;
top: 1px;
right: 2px;
bottom: 3px;
left: 4px;
新物理简写
position: absolute;
inset: 1px 2px 3px 4px;

这应该看起来非常方便!Inset 是物理边的简写,它的工作方式与 margin 和 padding 完全相同。

新功能

尽管物理边简写令人兴奋,但额外的 inset 简写带来的逻辑功能更加出色。这些简写为开发者带来了编写便利性(它们更短),但也增加了布局的潜在范围,因为它们是流相关的。

物理完整写法
position: absolute;
top: 10px;
bottom: 10px;
逻辑简写
position: absolute;
inset-block: 10px;


物理完整写法
position: absolute;
left: 10px;
right: 20px;
逻辑简写
position: absolute;
inset-inline: 10px 20px;

更多阅读材料和 inset 简写和完整写法的完整列表可在 MDN 上找到。

边框简写

边框及其嵌套的 colorstylewidth 属性也都获得了新的逻辑简写。


物理完整写法
border-top-color: hotpink;
border-bottom-color: hotpink;
逻辑简写
border-block-color: hotpink;
/* or */
border-block-color: hotpink hotpink;


物理完整写法
border-left-style: dashed;
border-right-style: dashed;
逻辑简写
border-inline-style: dashed;
/* or */
border-inline-style: dashed dashed;


物理完整写法
border-left-width: 1px;
border-right-width: 1px;
逻辑简写
border-inline-width: 1px;
/* or */
border-inline-width: 1px 1px;

更多阅读材料和边框简写和完整写法的完整列表可在 MDN 上找到。

逻辑属性 <figure> 示例

让我们在一个小示例中将所有内容放在一起。逻辑属性可以布局带有标题的图像,以处理不同的书写和文档方向。

或尝试一下!

您无需做太多操作即可使用 <figure> 和一些逻辑属性使卡片在国际上具有响应能力。如果您好奇所有这些国际化的 CSS 如何协同工作,我希望这是一个有意义的简短介绍。

Polyfill 和跨浏览器支持

级联或构建工具是可行的选择,可以使新旧浏览器都使用更新的逻辑属性正确间隔。对于级联回退,请在物理属性之后跟随一个逻辑属性,浏览器将使用在样式解析期间找到的“最后一个”属性。

p {
  /* for unsupporting browsers */
  margin-top: 1ch;
  margin-bottom: 2ch;

  /* for supporting browsers to use */
  /* and unsupporting browsers to ignore and go 🤷‍♂️ */
  margin-block: 1ch 2ch;
}

但这并不是适合所有人的完整解决方案。这是一个手写的后备方案,它利用 :lang() 伪选择器来定位特定语言,适当地调整其物理间距,然后在最后为支持的浏览器提供逻辑间距

/* physical side styles */
p {
  margin-top: 1ch;
  margin-bottom: 2ch;
}

/* adjusted physical side styles per language */
:lang(ja) {
  p {
    /* zero out styles not useful for traditional Japanese */
    margin-top: 0;
    margin-bottom: 0;

    /* add appropriate styles for traditional Japanese */
    margin-right: 1ch;
    margin-left: 2ch;
  }
}

/* add selectors and adjust for languages all supported */
:lang(he) {}
:lang(mn) {}

/* Logical Sides */
/* Then, for supporting browsers to use */
/* and unsupporting browsers to ignore #TheCascade */
p {
  /* remove any potential physical cruft.. */
  margin: 0;
  /* explicitly set logical value */
  margin-block: 1ch 2ch;
}

您还可以使用 @supports 来确定是否提供物理属性后备方案

p {
  margin-top: 1ch;
  margin-bottom: 2ch;
}

@supports (margin-block: 0) {
  p {
    margin-block: 1ch 2ch;
  }
}

SassPostCSSEmotion 和其他工具具有自动化的捆绑器和/或构建时产品,这些产品具有广泛的回退或解决方案。查看每个工具,了解哪个工具与您的工具链和整体站点策略相匹配。

下一步是什么

CSS 的更多部分将提供逻辑属性,但这尚未完成!不过,仍然缺少一组重要的简写,并且此 GitHub issue 中仍在等待解决方案。草案中有一个临时解决方案 in a draft。如果您想使用简写来设置框的所有逻辑边样式怎么办?

物理简写
margin: 1px 2px 3px 4px;
margin: 1px 2px;
margin: 2px;
逻辑简写
margin: logical 1px 2px 3px 4px;
margin: logical 1px 2px;
margin: logical 2px;

当前的草案提案意味着您必须在每个简写中编写 logical 才能应用逻辑等效项,这对某些人来说听起来不是很 DRY

还有其他提案可以在块或页面级别更改它,但这可能会将逻辑用法泄漏到仍然假设物理边的样式中。

html {
  flow-mode: physical;
  /* or */
  flow-mode: logical;
  /* now all margin/padding/etc references are logical */
}

/* hopefully no 3rd/1st party code is hard coded to top/left/etc ..? */

这是一个难题!请投出您的一票,表达您的意见,我们希望听到您的声音。

想了解或学习更多逻辑属性吗?这是 MDN 上提供的详细参考,以及指南和示例 🤓

反馈