2022年的新CSS功能 — Smashing


2022 年对于 CSS 来说将是非常棒的一年,大量的新功能即将出现。有些已经开始登陆浏览器,有些可能会在 2022 年获得广泛的浏览器支持。
 
container查询
要实现容器查询,我们需要指定一个元素作为我们的容器,使用容器属性(容器类型和容器名称的简写)。
容器类型可以是宽度、高度、inline-size或block-size。inline-size和block-size是逻辑属性,根据文档的书写模式可能产生不同的结果。

假设有一容器:

main, aside {
    container: inline-size;
}

然后我们就可以以类似于媒体查询的方式使用@container ,当容器宽于30rem时,我们使用flexbox切换到水平布局。

@container (inline-size > 30em) {
    .card {
        display: flex;
    }
}

注意在括号内可以用不同的方式来表达这个规则(inline-size > 30em而不是min-width: 30em)。
这是媒体查询第4级规范的一部分。

CSS Containment Level 3 规范目前处于工作草案中,这意味着语法可能随时改变——事实上,自从去年发表了一些关于容器查询的文章以来,它已经改变了。此处的示例与撰写本文时建议的语法一致。
Chrome 声称支持标志后面的容器查询,但工作实现似乎与当前规范不一致。有一个 polyfill,但它不适用于最新的语法。所以简短的回答是“不”,我肯定会敦促你在生产中使用它们之前等待一段时间。但是容器查询背后有很多动力,所以我希望很快会有更多的普遍支持。
 
:has() 
为含有<h2>的<section>元素设计样式:

section:has(h2) {
    background: lightgray;
}

要为<img>设计样式,只有当它的父<section>也包含<h2>时:

section:has(h2) img {
    border: 5px solid lime;
}

尚无主流浏览器支持,但您可以在Safari Technology Preview中尽情发挥。在支持的浏览器中查看这个演示。
 
@when/@else
CSS 中的条件规则,类似于其他编程语言中的 if/else 逻辑。例如,它可以使编写复杂的媒体查询更加合乎逻辑。
选择@when而不是@if语句是避免与 Sass 冲突。

我们可以查询多个媒体条件或支持的功能,例如用户的视口是否超过某个宽度,以及他们的浏览器是否支持子网格。当使用@when/@else时,我们把查询规则中的@去掉:

@when media(min-width: 30em) and supports(display: subgrid) {
    /* Styles for viewports over 30em, where the browser also supports subgrid */
} @else {
    /* Styles for browsers that do not meet the condition */
}
还没有。这是非常早期的事情,而且仍在讨论中。我不期望浏览器的支持在今年被广泛推广,但这绝对是一个值得关注的问题。
 
accent-color
想想复选框、单选按钮、范围输入和进度条,所有浏览器都以略微不同的风格方式呈现它们,accent-color属性可以快速轻松地将我们的品牌颜色推广到某些表单输入。accent-color使我们能够保留浏览器的默认输入,但应用颜色以适合我们的品牌。
使用方法很简单,而且该属性是继承的,所以你可以在根层设置它,以便在所有地方应用它。

:root {
    accent-color: lime;
}

form {
    accent-color: lime;
}

input[type="checkbox"] {
    accent-color: hotpink;
}


是的!accent-color在 Chrome、Edge、Firefox 和 Safari 技术预览版中受支持。不支持它的浏览器将简单地获得默认颜色,并且输入将保持完全可用 - 非常适合渐进增强。
 
新的 CSS 颜色函数
您可能已经熟悉 Hex、RGB 和 HSL 颜色格式。CSS Color Module Levels 45包括一整套新的颜色函数,使我们能够以前所未有的方式在 CSS 中指定和操作颜色。它们包括:

  • hwb():色相、白度、黑度。
  • lab():亮度以及决定色调的 a和b值。
  • lch():亮度、色度、色调。
  • color-mix():将两种颜色混合在一起。
  • color-contrast():从颜色列表中,输出与第一个参数相比对比度最高的颜色。
  • color():指定不同颜色空间中的颜色(例如display-p3)。

还有相对颜色语法,它可以让我们获取一种颜色并对其进行调整以制作另一种颜色。

hwb()、lab()和lch()的使用方式与我们所习惯的rgb()和hsl()函数的使用方式基本相同,都有一个可选的alpha参数:

.my-element {
  background-color: lch(80% 100 50); // opaque color
}

.my-element {
  background-color: lch(80% 100 50 / 0.5);
// color with 50% transparency
}


Safari目前在浏览器支持方面处于领先地位,从15版开始就支持hwb()、lch()、lab()和color()。color-mix()和color-contrast()可以通过一个标志启用。火狐浏览器支持hwb(),也有对color-mix()和color-contrast()的标记支持。令人惊讶的例外是Chrome,它现在不支持任何这些。
 
级联层 
级联层给了我们更多的权力来管理CSS的 "级联 "部分。目前,有几个因素决定了哪些样式会被应用到你的CSS代码中,包括选择器的特殊性和外观顺序。
级联层允许我们有效地将我们的CSS分成几块(或 "层",如果你愿意的话):
在顺序较低的层中的代码将优先于较高层中的代码,即使较高层中的选择器具有较高的特异性。
我喜欢把它看成是一种类似于级联的z-index。如果你理解了z-index的工作原理,你可能会很快掌握级联层的情况。

正如Bramus在他的教程中解释的那样,你可以创建与ITCSS方法一致的级联层:

/* Create the layers, in the desired order */
@layer reset, base, theme;

/* Append the CSS to each of the layers */
@layer reset {
 
/* Append to 'reset' layer */
}

@layer base {
 
/* Append to 'base' layer */
  h1.title {
      font-size: 5rem;
  }
}

@layer theme {
 
/* Append to 'theme' layer */
  h1 {
      font-size: 3rem;
  }
}

最新版本的火狐浏览器支持层叠式图层,在Chrome和Edge中可以通过一个标志启用(Chrome将在99版中全面支持)。看起来所有的主要浏览器都在加入这一规范,所以预计很快会有更广泛的支持。
 
Subgrid
几年前,当CSS网格首次被讨论时,许多开发者认为它可以使我们在一个单一的网格上布置UI的每个部分,就像我们从设计师那里得到的典型的12列布局一样。在实践中,这将涉及到完全扁平化你的标记,破坏语义--不建议这样做!。
作为CSS Grid Layout Module 2规范的一部分,subgrid使一个元素能够继承其父元素的网格,无论是在行轴还是列轴上。
理论上,你可以一路嵌套网格,将每个组件都对准同一个网格。在现实中,我们可能不需要像我们想象的那样经常这样做,因为我们(希望)接受更灵活、更内在的网页设计,优先考虑内容、用户体验和可访问性,而不是僵硬地遵守网格。但是subgrid对于解决各种UI挑战仍然是非常有用的。
 
使用Grid的常规属性指定父元素的网格。在你想继承父网格的嵌套项上的grid-template-columns或grid-template-rows属性中使用关键字subgrid。

.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(2, auto);
}

.grid > figure {
    display: grid;
    grid-template-rows: subgrid;
}

.grid figcaption {
    grid-row: 2;
}

值得注意的是,自2019年以来,subgrid已经在火狐浏览器中得到支持,然而近三年来,没有其他浏览器跟进。有迹象表明,Chromium团队终于开始实施它了,所以我们可能会幸运地看到它在今年登陆Chrome和Edge。 
滚动时间轴
你可能已经看到了很多很酷的网站,它们实现了花哨的滚动链接动画。
 想象一下,如果我们能在CSS中实现所有这些功能呢?有了@scroll-timeline,我们就可以做到了:

  1. 一个关键帧keyframe的动画。
  2. @scroll-timeline 。
  3. 我们要做动画的元素上的animation-timeline属性(或者在简明的animation属性中指定时间线)。


/* Set up keyframe animation */
@keyframes slide {
    to { transform: translateX(calc(100vw - 2rem)); }
}

/* Configure our scroll timeline. Here we're giving it the name `slide-timeline` */
@scroll-timeline slide-timeline {
  source: auto;
/* the scrollable element that triggers the scroll-linked animation (the document by default) */
  orientation: vertical;
/* the scroll orientation (vertical by default) */
  scroll-offsets: 0%, 100%;
/* an array of progress intervals in which the timeline is active */
}

/* Specify the keyframe animation and the scroll timeline */
.animated-element {
  animation: 1s linear forwards slide slide-timeline;
}

我们也可以使用基于元素的偏移量的scroll-offsets属性,在某一特定元素滚动进入视图时触发时间线。

 

@scroll-timeline slide-timeline {
    scroll-offsets: selector(element) end 0, selector(element) start 1;
}

如果你对@scroll-timeline感兴趣,可以在Chrome浏览器中用一个标志启用它。该规范还处于编辑草案阶段,所以在获得推荐状态之前,很有可能会发生变化。 
Nesting嵌套
如果你熟悉Sass,你会知道能够嵌套选择器的便利性--本质上,在父级规则中写一个子规则。嵌套可以帮助我们保持代码的条理性--尽管如果过度使用,有时会成为一种障碍 现在看来,嵌套终于要进入本地CSS了。

在语法上,它与Sass相似,所以不应该感觉到太多的跳跃。这里的嵌套规则针对的是一个类别为card的元素中的h2。
 

.card {
    color: red;

    & h2 {
        color: blue;
    }
}

不是原生的。目前还没有浏览器支持它。