状态、逻辑与原生能力:2025年CSS年度总结

本文深入解析了2025年CSS领域的重大发展,从原生可定制选择框、纯CSS轮播到滚动状态查询与CSS逻辑函数,探讨了CSS如何逐步承担以往由JavaScript处理的交互与状态逻辑,正在重塑现代Web应用的构建方式。

State, Logic, And Native Power: CSS Wrapped 2025 — Smashing Magazine

CSS Wrapped 2025 已经发布!我们正在进入一个CSS能够越来越多地处理逻辑、状态和复杂交互的世界,而这些以往是JavaScript的专属领域。CSS不再仅仅关乎文档样式,而是关乎使用比以往任何时候都更强大的原生工具包来构建动态、符合人体工程学且健壮的应用程序。以下是其中的亮点以及它们如何与现代CSS更广泛的演进联系起来。

如果我必须将CSS的演进分类,那么我们已经远远超越了那个仅仅要求border-radius就感觉生活在未来的时代。我们正处在一个平台为我们提供工具的时刻,这些工具不仅仅是调整视觉层,而是从根本上重新定义了我们如何构建界面。我曾以为2024年宣布的功能数量无法被超越。我从未如此高兴地发现自己错了。

Chrome团队的"CSS Wrapped 2025"不仅仅是一个功能列表;它是一份关于动态、原生Web的宣言。作为一个花费了数年时间记录这些演进的人——从定义"CSS5"时代到现代布局工具集的复杂性——我发现自己在以巨大的兴奋感看待今年的总结。我们正看到一种向"优化的人体工程学"和"下一代交互"的转变,这让我们能够停止与代码斗争,并开始以其自然状态塑造界面。

在本文中,您将通过我最近的实验和对平台未来的展望,全面了解Chrome报告中的突出功能。

组件革命:终于,一个原生的可定制选择框

多年来,我们一直依赖笨重的JavaScript库来为下拉框设置样式,这是一个"存在了数十年的问题",平台终于解决了。正如我在深入探讨可定制选择框的历史(及相关文章)中所详述的那样,这是一条漫长的道路,涉及Open UI、关于<selectmenu><selectlist>等名称的争论,最终落地了一个重用现有<select>元素的解决方案。

appearance: base-select的引入是一个坚实的基础。它允许我们使用标准CSS完全自定义<select>元素——包括按钮和下拉列表(通过::picker(select))。关键的是,这是在考虑渐进增强的情况下构建的。通过将我们的样式包装在特性查询中,我们确保了跨所有浏览器的无缝体验。

我们可以在不破坏旧版浏览器的情况下选择启用这个新行为:

1
2
3
4
5
6
7
8
select {
  /* Opt-in for the new customizable select */
  @supports (appearance: base-select) {
    &, &::picker(select) {
      appearance: base-select;
    }
  }
}

允许在选项内使用丰富内容(如图像或国旗)的绝妙新增功能非常有趣。我们现在可以创建各种选择框:

演示:我创建了一个Poké-adventure演示,展示了新的<selectedcontent>元素如何将丰富内容(如Pokéball图标)从选项直接克隆到按钮中。 https://codepen.io/smashingmag/pen/JoXwwoZ

演示:一个仅使用伪元素来设置选择框样式的全面展示。 https://codepen.io/smashingmag/pen/pvyqqJR

演示:或者,您可以使用这个使用optgroups的菜单选择演示来提升一个档次。 https://codepen.io/smashingmag/pen/myPaaJZ

仅此功能就标志着我们将如何构建表单的巨大转变,减少了依赖性和技术债务。

滚动标记与JavaScript轮播的终结

创建轮播一直是开发人员和客户之间的一个摩擦点。客户喜欢它们,开发人员则害怕为使其可访问和性能良好而需要的JavaScript。::scroll-marker::scroll-button()伪元素的出现完全改变了这种动态。

这些功能允许我们仅用CSS创建导航点和滚动按钮,并原生链接到滚动容器。正如我在博客上写的,这是一见钟情。无需一行JavaScript就能创建功能齐全、可访问的滑块,不仅方便,更是性能的胜利。围绕此功能存在一些可访问性方面的担忧,虽然这些担忧是合理的,但我们开发人员可能有办法使其正常工作。好处是,所有这些UI更改都比自定义DOM操作和拖拽aria标签要容易得多,不过我得说偏题了…

我们现在可以使用scroll-marker-group自动分组标记,并使用锚点定位(anchor positioning)来精确放置按钮样式。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
.carousel {
  overflow-x: auto;
  scroll-marker-group: after; /* Creates the container for dots */

  /* Create the buttons */
  &::scroll-button(inline-end),
  &::scroll-button(inline-start) {
    content: " ";
    position: absolute;
    /* Use anchor positioning to center them */
    position-anchor: --carousel;
    top: anchor(center);
  }

  /* Create the markers on the children */
  div {
    &::scroll-marker {
      content: " ";
      width: 24px;
      border-radius: 50%;
      cursor: pointer;
    }
    /* Highlight the active marker */
    &::scroll-marker:target-current {
      background: white;
    }
  }
}

演示:我尝试仅用HTML和CSS创建轮播,使用锚点定位来放置按钮。 https://codepen.io/smashingmag/pen/ogxJJjQ

演示:一个使用attr()动态将背景图片拉入标记的Webshop slick slider重制版。 https://codepen.io/smashingmag/pen/gbrZZPY

状态查询:粘性元素粘住了吗?对齐元素对齐了吗?

长期以来,我们一直缺乏在不依赖IntersectionObserver hack的情况下知道"粘性元素是否粘住"或"对齐元素是否对齐"的能力。Chrome 133引入了滚动状态查询,允许我们以声明方式查询这些状态。

通过设置container-type: scroll-state,我们现在可以根据子元素是否粘住、对齐或溢出为其设置样式。这是一个巨大的"生活质量"提升,我从CSS Day 2023以来就一直热切期待着。它甚至已经演进很多,因为我们还可以看到滚动的方向,太棒了!

举个简单的例子:我们终于可以在标题实际粘在视口顶部时才对其应用阴影:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
.header-container {
  container-type: scroll-state;
  position: sticky;
  top: 0;

  header {
    transition: box-shadow 0.5s ease-out;
    /* The query checks the state of the container */
    @container scroll-state(stuck: top) {
      box-shadow: rgba(0, 0, 0, 0.6) 0px 12px 28px 0px;
    }
  }
}

演示:一个仅在真正粘住时才应用阴影的粘性头部。 https://codepen.io/smashingmag/pen/raeooxY

演示:一个使用滚动状态查询结合锚点定位在宝可梦主题列表上移动当前对齐角色框架的演示。 https://codepen.io/smashingmag/pen/vEGvvLM

优化的人体工程学:CSS中的逻辑

CSS Wrapped的"优化的人体工程学"部分突出了使我们的工作流程更直观的功能。三个功能在改变我们编写逻辑的方式方面具有变革性:

if() 语句

我们终于在CSS中获得了条件语句。if()函数就像样式表的三元运算符,允许我们根据媒体、支持或样式查询内联地应用值。这减少了为单个属性更改而使用冗长的@media块的需要。

@function 函数

我们终于可以将一些逻辑移到不同的地方,从而使文件更清晰,这是一个真正的生活质量功能。

sibling-index()sibling-count()

这些树计数函数解决了基于列表大小错开动画或样式化项目的问题。正如我在《用CSS样式化兄弟元素从未如此简单》中探讨的那样,这消除了在HTML中硬编码自定义属性(如--index: 1)的需要。

示例:计算布局

我们现在可以编写简洁的数学公式。例如,为进入屏幕的卡片错开动画变得很简单:

1
2
3
4
5
.card-container > * {
  animation: reveal 0.6s ease-out forwards;
  /* No more manual --index variables! */
  animation-delay: calc(sibling-index() * 0.1s);
}

我甚至尝试了将这些函数与三角函数结合使用,以便在没有任何JavaScript的情况下将项目放置在一个完美的圆中。

演示:动态错开卡片动画。 https://codepen.io/smashingmag/pen/RNaEERz

演示:使用sibling-indexsibling-count和新的CSS @function功能将项目放置在完美的圆中。 https://codepen.io/smashingmag/pen/XJdoojZ

我的CSS待办清单:迫不及待想尝试的功能

虽然我一直忙于打造选择框和过渡效果,但"CSS Wrapped 2025"报告中还包含了其他许多好东西,我还没有机会在CodePen中启动它们。这些是我下次实验的重点:

锚定容器查询

我在轮播演示中使用了CSS锚点定位来放置按钮,但"CSS Wrapped"强调了它的一个演进:锚定容器查询。这解决了我们工具提示都遇到过的问题:如果浏览器因为空间限制将工具提示从顶部翻转到底部,“箭头"通常仍指向错误的方向。使用锚定容器查询(@container anchored(fallback: flip-block)),我们可以根据浏览器实际选择的备用位置来样式化元素。

嵌套视图过渡组

视图过渡是一场革命,但它们伴随着一个特定的权衡:它们扁平化了元素树,这通常会破坏3D变换或overflow: clip。我一直觉得它缺少点什么,而这可能就是答案。通过使用view-transition-group: nearest,我们终于可以在彼此内部嵌套过渡组。

这允许我们在过渡期间保持裁剪效果或3D旋转——这在以前是不可能的,因为元素被提升到了顶层。

1
2
3
4
.card img {
  view-transition-name: photo;
  view-transition-group: nearest; /* Keep it nested! */
}

排版与形状

最后,作为人体工程学爱好者的我,渴望尝试"文本框修剪”,它承诺消除文本内容上方和下方恼人的额外空白,最终实现完美的垂直对齐。对于创意方面,corner-shapeshape()函数正在开放非矩形布局,允许"方圆形"和响应CSS变量的复杂路径。话虽如此,我迫不及待想要一个充满方圆形图案的设计了!

充满希望的未来

我们正在见证一个CSS变得能够处理以往属于JavaScript的逻辑、状态和复杂交互的世界。诸如moveBefore(为iframe/视频保留DOM状态)和attr()(使用字符串以外的类型表示颜色和网格)等功能进一步巩固了这一现实。

虽然其中一些功能目前处于实验阶段或特定于Chrome,但其势头是不可否认的。我们必须希望通过像Interop这样的倡议在所有浏览器中获得持续支持,以确保这些能力成为基准。话虽如此,拥有浏览器引擎与在"Chrome优先"中拥有所有这些令人惊叹的功能同样重要。这些新功能需要在落地于浏览器之前进行讨论、试验和测试。

这是一个学习CSS的绝佳时刻。我们不再仅仅是样式化文档;我们正在使用比以往任何时候都更强大的原生工具包构建动态、符合人体工程学且健壮的应用程序。

让我们开始这个新时代并传播这个消息。

这就是CSS Wrapped!

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计