新年新气象:探索全新的 CSS 语法

发表时间: 2024-02-19 11:53

本期共享的是 —— CSS 的发展速度比以往都快。自从几年前有了 Flexbox 和 Grid 以来,随着所有现在可用的和即将推出的新功能,我们编写 CSS 的方式也在与时俱进。本文共享了了哪些功能对当前的 CSS 写法影响最大,以及哪些功能没有。

CSS 所有花里胡哨的野蛮生长真的改变了我们编写 CSS 的方式吗?新功能无疑改变了本人今天编写 CSS 的方式,但没有完全改变。

我记得当 SCSS 开始蚕食 CSS 时,它经常被用作代码示例的首选语法。我并没有看到同样的有机采用发生在原生 CSS 的逻辑属性上,因为大部分 CSS 爱好者并不知道这些新功能,而我们已经为它们提供了全面的浏览器支持已有大约两年了。

就本人而言,CSS 的演变让我十分鸡冻。一大坨最新功能都是我们多年来梦寐以求的,这足以让我现在比以往任何时候都更喜欢编写 CSS。

容器查询

本人郑重声明:我从不喜欢为响应式布局编写媒体查询。内容对视口宽度的响应不同,具体取决于其所在的组件。平衡一个组件中的内容一直是​一种与平衡其他组件中的内容的整活行为,在看似任意的断点处增加了一堆媒体查询。使用 SCSS 将媒体查询嵌套在选择器中已经勉为其难,但也只是差强人意。

容器查询对我而言是正确的选择。现在,我们可以将子元素的范围限定为父容器,并依靠容器的大小来定义布局的移动位置,而无需考虑其他周围的组件。

.parent {  container-type: inline-size;}/* 容器查询 */@container (min-width: 600px) {  .child {    align-self: center;  }}


我仍使用媒体查询来实现响应式布局,但倾向于将它们保留用于由组装容器组成的更大布局。当不需要考虑每个单独容器内发生的情况时,断点更可预测,这实际上可以更明确地针对特定设备。

图层样式组

我喜欢图层这种管理级联样式的方案!现在,如果我有一个重置或来自框架的某些第三方 CSS,我可以将它们包装在级联层中,并将它们放在文件底部,这样我自己的样式就位于前面和中间。

浏览器已经开始支持级联层,所以兼容性不是大问题。更重要的是,我在项目上仍依赖 SCSS 来获得某些功能,并且在部分文件中维护样式对我而言感觉良好,至少对于此类工作而言是如此。

body {  display: grid;  gap: 3rem;  place-items: center;}/* 级联层 */@layer base {  body {    font-size: 1.25rem;    line-height: 1.35;    padding: 3rem;  }}c


:is()/:where()

我肯定会寻求 is()/:where 这些较新的关系伪类选择器,但并不是真正为了基于关系按条件地选择元素的好处。

相反,我最常使用它们来管理特异性。为什么?因为对于 :is(),特异性不是由主选择器决定的,而是由其参数列表中最具体的选择器决定的。

/* 特异性权重: 0 1 1 */:is(ol, .list, ul) li {}/* 特异性权重: 0 0 2 */ol li {}


.list 选择器为第一个规则集提供了更高的特异性权重,这意味着,它优先于第二个规则集,即使第一个规则集在级联中更高。

另一方面,:where() 的特异性得分为 0,因此它不会增加其所在选择器的总体得分。它的参数列表中的内容根本无关痛痒。出于同样的原因,我使用 :is() 来添加特异性,我使用 :where() 将其删除。我喜欢保持较低的特异性,因为我仍希望级联以尽少的摩擦操作,而 :where() 使这成为可能,尤其是在定义全局样式时。

举个栗子,将 :not() 包裹在 :where() 内,防止 :not() 提高特异性:

/* 特异性权重: 0 0 0 */:where(:not(.some-element)) {}


我仍是 BEM 语法的虔信徒之一。但命名是最头大的事情之一。我经常发现没有足够的名称来辅助描述元素的功能及其与周围元素的关系。:is()/:where() 的特异性争论能力意味着,我可以更少地依赖复杂的类名,而更多地依赖元素选择器。

新型颜色函数语法

rgb() 和 hsl() 等颜色函数的更新语法(以及不断发展的 oklch() 和 oklab())并没有得到太多关注,但它确实可以更好地定义颜色值。

其一,当我需要 alpha 值时,我永远不必触及 rgba() 或 hsla() 。事实上,无论我是否需要 alpha,我总是使用这些版本,因为我不想费心决定使用哪个版本。

color: hsl(50deg, 100%, 50%);/* 等效 */color: hsla(50deg, 100%, 50% / 1);


这里编写额外的 a、/ 和 1 是值得的,因为不必考虑使用哪个函数。

但更新后的颜色语法不关心函数名称中额外的 a。它甚至不关心逗号。

color: hsl(50deg 100% 50% / 0.5);


我十分鸡冻地开始使用更新的 oklch() 和 oklab() 颜色空间,因为它们具有完整的浏览器支持!

定义调色板

自从采用 SCSS 以来,我一直使用变量来定义和分配颜色,且当 CSS 自定义属性出现时,我感到十分鸡冻。在将调色板中的颜色传递给具有更多功能名称的变量之前,我会为它们指定通用名称。

/* 调色板 */--red: #ff0000;/* 颜色类型 */--color-primary: var(--red);


我仍然这样做,但现在我将在具有大调色板的项目上使用颜色函数进一步抽象事物:

:root {  /* 主颜色 HSL */  --h: 21deg;  --s: 100%;  --l: 50%;  --color-primary: hsl(var(--h) var(--s) var(--l) / 1);}.bg-color {  background: var(--color-primary);}.bg-color--secondary {  --h: 56deg;  background: hsl(var(--h) var(--s) var(--l) / 1);}


这种调色板是不是有点太抽象了?或许是的。但对于那些可能有十种不同颜色的项目来说,拥有这种级别的细粒度控制来操纵它们乃一大幸事。也许我还没有探索过 color-mix() 的更多控制。

我没用的功能

我想我写 CSS 的方式和以前有点不一样了!这可能与我尚未使用的一大坨其他新功能有关。我正在使用的新功能数量比我尚未使用的功能数量要少得多,无论是因为浏览器支持,还是因为我还没有接触到它。

CSS 嵌套:我真的很期待 CSS 嵌套,因为这可能是我完全弃用 SCSS,而完全拥抱纯 CSS 的转折点。在撰写本文时,它正在等待 Firefox 支持,因此它可能近在咫尺。

样式查询:根据其他元素的样式将样式应用于元素是我真正感兴趣的事情。也许随着它们获得浏览器支持,这种情况将会改变。

has():当 Firefox 支持时,我肯定会使用它。在那之前,我只会小试牛刀,并欣赏他者如何使用它。尽管没有完全支持,:has() 并没有改变我编写 CSS 的方式。不过,我希望它可以改变,因为能够根据其包含的子元素选择父元素怎么可能是一件坏事,对不?

动态视口单位:自从动态视口单位在 2022 获得广泛支持以来,我就开始在样式中加入它们。因此,我不再使用 height: 100vh,而是开始越来越多地编写 height: 100dvh。我想这影响了我编写 CSS 的方式,即使它很微妙。

OKLCH/OKLAB 色彩空间:oklch() 绝对是我的首选颜色函数。它在去年获得广泛支持,我语言它会成为 CSS 中定义颜色的最广泛使用的方法。

其他功能:过去五年发布的每一个新 CSS 功能都一言难尽。当谈到我在日常工作中没有使用哪些功能时,主要的主题是它们太新,或者缺乏浏览器支持。这并不意味着,我不会使用它们,但目前我只是偷偷关注它们,或者享受沉浸式体验它们的乐趣。

这些功能包括但不限于:

  • 三角函数
  • 锚点位置
  • 滚动链接动画
  • initial-letter
  • <selectmenu>/<popover>
  • 视图过渡
  • 作用域样式


作者:人猫神话
链接:
https://juejin.cn/post/7334755783751794724