2024年的CSS革命

本文最后更新于 2025年1月7日 上午

align-centent 革新

以前,居中元素需要使用各种方法,比如 Flexbox 属性、margin 甚至绝对定位。这意味着开发者需要花费大量时间进行调整和尝试,最终结果可能在某些屏幕尺寸或浏览器类型下失效。

align-content 属性的美妙之处在于它的简洁性。你无需手动将所有元素包裹在容器 div 中,也无需费力地解读复杂的 Flexbox 选项。只需要在你的元素上使用这个属性,它就能根据父容器的显示模式自动进行对齐。

这个新属性对于响应式设计来说是一场革命。它能在任何屏幕尺寸上实现完美的居中对齐,无需额外的媒体查询或布局调整。这意味着“更少的代码,更好的性能,以及更少的样式系统潜在故障点。”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/* 使用 Flexbox 的旧方法 */
.old-center {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height100vh;
}

/* 新方法——更简洁! */
.new-center {
  align-content: center;
  min-height100vh;
}

/* 适用于任何内容 */
.center-text {
  align-content: center;
}

/* 甚至适用于多个元素 */
.center-group {
  align-content: center;
  gap1rem;
}

@property 的威力:类型安全的 CSS 变量

CSS 变量(自定义属性)已经存在一段时间了,但它们有一个局限性:浏览器总是将其值解释为字符串。新的 @property 规则(CSS Houdini 的一部分)解决了这个问题,使得可缩放矢量图形 (SVG) 更加强大。

在使用普通的 CSS 变量时,动画和过渡可能存在问题或根本无法实现,因为浏览器无法理解变量的类型。例如,我尝试动画化一个基于百分比的渐变,但这行不通,因为对于浏览器来说,它只是一个字符串,而不是一个数字。

@property 规则通过指定变量的类型来消除这个限制。这意味着你的网站将拥有更流畅的界面、更具响应性的功能,以及更少的样式表异常行为。想象一下,为你的 CSS 带来类型安全,就像你在 JavaScript 中使用 TypeScript 一样。

仅仅是构思一个主题系统,在不同模式之间切换时能够实现颜色混合,就令人兴奋不已。这样,你可以定义浏览器可以原生识别的颜色变量,从而获得必然的平滑过渡,而这在以前要么是不可能的,要么需要调用 JS

现在你可以:

  • 为你的变量定义特定类型(数字、颜色、百分比
  • 创建更安全、更可预测的代码
  • 使用类型化值实现流畅动画
  • 通过更好的浏览器优化来提高性能

这个特性在处理以下情况时非常有用:

  • 渐变
  • 动画
  • 动态配色方案
  • 响应式布局
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
29
30
31
32
/* 旧方法——浏览器将所有内容视为字符串 */
:root {
  --gradient-stop50%;
  --theme-color#ff0000;
}

/* 使用 @property 的新方法 */
@property --gradient-stop {
  syntax: '<percentage>';
  inherits: false;
  initial-value: 0%;
}

@property --theme-color {
  syntax: '<color>';
  inherits: true;
  initial-value: #ffffff;
}

/* 现在你可以为这些属性添加动画了! */
.gradient-background {
  backgroundlinear-gradient(
    90deg,
    blue var(--gradient-stop),
    red var(--gradient-stop)
  );
  transition: --gradient-stop 0.3s ease;
}

.gradient-background:hover {
  --gradient-stop75%;
}

@starting-style:为隐藏元素打造更好的动画

之前我们初始化动画 display:none 实现, 曾经是开发者永恒的痛点之一。现在我们可以使用 @starting-type 规则优雅地解决这个问题。

举例子:模态对话框,它从顶部进入屏幕。以前,为了获得流畅的动画,你必须在 JavaScriptCSS 中进行大量的复杂操作。元素要么突然出现,要么需要额外的包装元素和状态来进行过渡。

使用 @starting-style,你可以设置元素加载并准备使用时的样式,以便从隐藏状态过渡平滑无缝。这使得 UI 更精细,但代码更少。浏览器负责处理动画的编程以及页面外观和行为方式的所有问题。

这个特性在构建适合残疾人士使用的应用程序界面方面尤其有用。这些过渡修复能够被屏幕阅读器和辅助技术理解,从而提高网站的可访问性,同时还能以视觉上更具吸引力的方式呈现它们。它提供以下功能:

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
29
30
31
32
33
34
35
36
/* 模态对话框示例 */
.modal {
  display: none;
  opacity1;
  transformtranslateY(0);
  transition: transform 0.3s ease, opacity 0.3s ease;
}

@starting-style {
  .modal {
    opacity0;
    transformtranslateY(-20px);
  }
}

/* 显示模态框时 */
.modal.show {
  display: block;
}

/* 下拉菜单示例 */
.dropdown-menu {
  display: none;
  transformscaleY(1);
  transition: transform 0.2s ease;
}

@starting-style {
  .dropdown-menu {
    transformscaleY(0);
  }
}

.dropdown-menu.open {
  display: block;
}

增强的数学函数:CSS 变得更强大

增加函数功能。

这些函数意味着在普通的 HTML 中,通常可以省略预处理器或 JavaScript,尽管当然在许多情况下预处理器仍然有用。例如,使用原生数学函数可以更容易地管理诸如计算网格列宽度或设计响应式间距系统等任务。有了它,你就可以在 CSS 中进行复杂的数学运算。

round 类型(floorceilingtrunk)的存在允许设计以前似乎不可能实现的改进布局精度。在任何情况下,当你处理网格系统或难以用预设的基于像素的宽度管理的内容时,这些函数都能提供你所需的控制,而无需离开你的样式表。新的数学函数证明了这一点:

  • round(): 选择不同的入舍策略(向下取整、向上取整、截断)
  • rem():余数运算
  • mod():模运算, 类似于 JavaScript

上面这些函数为以下这些方面提供了新的特性:

  • 动态布局
  • 响应式设计计算
  • 复杂的动画
  • 网格系统
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
29
/* 网格列计算 */
.grid {
  --columns3;
  --gap20px;

  display: grid;
  gapvar(--gap);
  grid-template-columnsrepeat(
    var(--columns),
    calc(100% / var(--columns) - round(var(--gap) * (var(--columns) - 1) / var(--columns)))
  );
}

/* 使用 mod 实现交替样式 */
.list-item {
  paddingmod(var(--index), 2) * 1rem;
}

/* 舍入示例 */
.element {
  /* 四舍五入到最接近的整数 */
  widthround(calc(100vw / 3));

  /* 向下取整 */
  heightround(down, calc(100vh / 4));

  /* 向上取整 */
  marginround(up, calc(2.1rem));
}

使用 light-dark() 简化明/暗模式

管理明暗模式一直是一件比较麻烦的事情。新的 light-dark() 特性极大地简化了这个过程。

在真正的暗模式概念出现之前,只有两种创建它的方法,第一种是使用两种 CSS 样式,另一种是使用具有媒体查询的 CSS 变量。上述方法导致代码重复,从而导致代码重复和更高的维护成本。HTML5 的新 light-dark() 函数简化了同时设置这两者的过程。

此特性还增强了浏览器的性能,因为浏览器能够修改主题之间切换的性质。无需加载样式表或等待 JavaScript 更改那些变量,它根本不需要。它是无缝的并且快速发生,从而为用户提供比标准方法更好的体验。

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
29
30
31
/* 旧方法 */
:root {
  --bg-color: white;
  --text-color: black;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg-color: black;
    --text-color: white;
  }
}

/* 使用 light-dark() 的新方法 */
.element {
  background-colorlight-dark(#ffffff#121212);
  colorlight-dark(#121212#ffffff);
  border1px solid light-dark(#ddd#333);
  box-shadow0 2px 4px light-dark(rgba(0,0,0,0.1), rgba(0,0,0,0.4));
}

/* 与 CSS 变量结合使用 */
.button {
  --button-bglight-dark(#007bff#0056b3);
  --button-textlight-dark(white, #e1e1e1);

  background-colorvar(--button-bg);
  colorvar(--button-text);
  padding0.5rem 1rem;
  border-radius4px;
}

使用用户伪类增强表单验证

!()[https://mmbiz.qpic.cn/sz_mmbiz_jpg/HLN2IKtpicicE6uqDgA0bpTyoibQvsjdeecvBrlmTGgTCDXMK0HNpknLyagPmN4icgXOj2FCM6wicCDLgg35Gvhxovw/640?wx_fmt=jpeg&from=appmsg&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1]

借助 :user-valid:user-invalid 伪类的引入,表单验证变得更加用户友好。

登录表单,你需要仅在用户尝试提交表单或离开输入字段时显示错误消息。以前,这只能通过使用 Javascript 事件监听器或复杂的 CSS hacks 来实现。新的伪类自然地实现了这一点,增强了页面的可用性,而无需额外的代码。

此特性还方便了访问;很容易。以前,表单验证状态对于某些屏幕阅读器来说难以识别,而现在它们更改表单的方式对每个人都更有用。显示错误消息的时间变得更有逻辑,表单未完成的实例减少了。这些新特性:

  • 仅在用户交互后触发
  • 防止过早显示错误消息
  • 改善用户体验
  • 降低代码复杂度

这比传统的 :valid:invalid 伪类有了显著的改进,传统的伪类会立即触发,通常会导致糟糕的用户体验。

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/* 基本输入样式 */
.input-field {
  border2px solid #ccc;
  padding0.5rem;
  border-radius4px;
}

/* 旧方法——立即显示 */
.input-field:invalid {
  border-color: red;
}

/* 新方法——仅在用户交互后显示 */
.input-field:user-invalid {
  border-color: red;
  animation: shake 0.3s ease-in-out;
}

.input-field:user-valid {
  border-color: green;
}

/* 错误消息样式 */
.error-message {
  display: none;
  color: red;
  font-size0.875rem;
  margin-top0.25rem;
}

.input-field:user-invalid + .error-message {
  display: block;
}

/* 成功样式 */
.success-icon {
  display: none;
}

.input-field:user-valid ~ .success-icon {
  display: inline-block;
}

@keyframes shake {
  0%100% { transformtranslateX(0); }
  25% { transformtranslateX(-5px); }
  75% { transformtranslateX(5px); }
}

interpolate-size:为自动高度实现流畅动画

一个手风琴组件在展开时添加了内容。在此特性之前,动画高度的唯一方法是具有挑战性的,尤其是在处理动态内容时。主要问题在于开发者如何依赖 JavaScript 解决方案,或者使用固定高度动画,当内容较长时,这些动画就会停止工作。

因此,interpolate-size 属性可以轻松应对这些情况。浏览器会平滑地确定动画的正确路径,从而使过渡无缝,而不管内容的大小如何。即使你没有定义最终高度,它也能正常工作,这使得它更适合用于动态内容区域。现在你可以:

  • 平滑地动画化 height: auto
  • 创建流畅的下拉菜单动画
  • 优雅地处理动态内容变化
  • 实现更平滑的 UI 过渡

这个特性特别适用于:

  • 下拉菜单
  • 可展开部分
  • 手风琴组件
  • 动态内容区域
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/* 手风琴示例 */
.accordion {
  overflow: hidden;
}

.accordion-content {
  height: auto;
  padding1rem;
  background#f5f5f5;
  interpolate-size: allow;
  transition: height 0.3s ease;
}

.accordion-content.closed {
  height0;
  padding0 1rem;
}

/* 下拉菜单示例 */
.dropdown {
  overflow: hidden;
}

.dropdown-menu {
  height: auto;
  interpolate-size: allow;
  transition: height 0.3s ease;
}

.dropdown-menu.collapsed {
  height0;
}

/* 卡片展开示例 */
.card {
  interpolate-size: allow;
  transition: all 0.3s ease;
}

.card.expanded {
  height: auto;
  padding-bottom2rem;
}

2024年的CSS革命
https://dev.dgdream.online/2024年的CSS革命/
作者
执念
发布于
2025年1月6日
更新于
2025年1月7日
许可协议