本文将盘点与解析 CSS 的实用新特性,结合技术原理、应用场景和开发实践。从重塑交互体验,到强化组件功能,再到全面优化开发流程,这些新特性不仅显著提升了开发者的工作效率,还为用户带来了更加流畅、互动性更强的网页体验。
animation-timeline
属性,实现滚动操作与动画效果的深度绑定,同时支持时间轴的分段控制,如 scroll()
和 view()
方法。@keyframes appear {
from {
opacity: 0;
scale: 0.8;
}
to {
opacity: 1;
scale: 1;
}
}
.block {
animation: appear linear;
animation-timeline: view();
animation-range: entry 25% cover 50%;
}
上述代码 通过 animation-timeline: view()
实现了图片在视口中滚动到特定范围时,自动触发淡入和放大的动画效果。这种动画方式不仅可以突出重要内容、引导用户浏览,还能为网页增添动态活力,提升用户的沉浸感。
@view-transition
和 document.startViewTransition
来定义跨页面或组件的过渡动画,同时支持通过伪元素 ::page-transition-container
进行精细化控制。::view-transition-old(.card):only-child {
animation: fade-out ease-out 0.5s;
}
document.querySelectorAll('.delete-btn').forEach(btn => {
btn.addEventListener('click', () => {
document.startViewTransition(() => {
btn.closest('.card').remove();
});
})
});
在这个示例中,列表视图在用户交互时会自动更新。借助视图转换特性,可以轻松实现动画效果。若要在单页应用中快速启用视图转换,只需使用 document.startViewTransition
封装交互逻辑,并确保每个参与转换的元素都有 view-transition-name
(可内嵌),或者在创建 DOM 节点时使用 JavaScript 动态创建 view-transition-name
。
技术核心:通过在元素上设置 popover
属性,并使用 popovertarget
将其与按钮等调用元素关联,浏览器会自动处理弹出式窗口的诸多关键行为。
场景案例:适用于表单验证提示、上下文帮助菜单、快捷操作面板等轻量级非模态弹层。
开发价值:简化了传统弹层开发的复杂逻辑,提升了性能和可访问性,减少了对第三方库的依赖。
<button popovertarget="my-popover">弹出式窗口</button>
<div id="my-popover" popover>
<p>Popover API<br>按 <kbd>esc</kbd> 或空白处关闭<p>
</div>
[popover]:popover-open {
translate: 0 0;
}
[popover] {
transition: translate 0.7s ease-out, display 0.7s ease-out allow-discrete;
translate: 0 -22rem;
}
@starting-style {
[popover]:popover-open {
translate: 0 -22rem;
}
}
下面示例利用原生 Popover API 实现了交互性的动画弹窗。点击按钮时,弹窗会缓动滑入;按下 Esc 键或点击空白处,弹窗会自动反向滑出关闭。核心在于利用 popovertarget
和 popover
属性声明触发器与弹窗的绑定关系,结合 @starting-style
规则定义动画初始状态,解决了首次渲染问题,同时依赖浏览器原生机制自动处理弹窗置顶、焦点锁定及关闭逻辑。
技术核心:position-anchor
属性允许开发者更精准地控制元素相对于其锚定元素的位置,而 inset-area
则提供了更灵活的定位区域控制。
场景案例:适用于工具提示(Tooltip)跟随按钮、下拉菜单对齐输入框、悬浮卡片吸附图表节点等需要动态定位的场景。
开发价值:减少了手动计算位置的代码冗余,提升了交互组件的响应精度和跨分辨率适配能力。
2.1. 基础锚点定位:通过 position-anchor
和 anchor-name
属性,可以将定位元素锚定到特定的锚点元素上。
ul::before {
content: "";
position: absolute;
left: anchor(var(--target) left);
right: anchor(var(--target) right);
bottom: anchor(var(--target) bottom);
...
}
li:nth-child(1) { --anchor: --item-1 }
ul:has(:nth-child(1) a:is(:hover, :focus-visible)) {
--target: --item-1;
--color: pink;
}
以下演示 展示了当用户将光标悬停在列表项上或按 Tab 键浏览列表项时,下划线样式会自动锚定到列表项。使用锚点函数,根据 left
、right
和 bottom
的物理属性设置锚点位置。当鼠标悬停在其中一个链接上时,目标锚点会发生变化,浏览器会自动移动目标以应用定位,同时还会为颜色添加动画效果,呈现出简洁而美观的效果。
2.2. inset - area 定位:提供了一种更精细的定位方式,它适用于 9 个单元格的网格布局,其中锚定元素位于中心。结合容器查询样式的卡片元素,当卡片界面大小发生变化时,固定的菜单等定位元素也能随新布局一起动态移动,保持与锚点元素的正确位置关系。
.anchor {
anchor-name: --my-anchor;
}
.positioned {
position: absolute;
position-anchor: --my-anchor;
inset-area: bottom;
}
例如,inset - area: top
会将定位元素放置在锚点元素的顶部。可以将这些位置值与 span
关键字组合使用,以从中心位置开始,向左、向右或全部范围,占据全部列或行的可用空间。还可以使用 逻辑属性,如 position-area: block-end span-inline-end
。为了更直观地了解和掌握布局机制,可以查看 工具 demo。
技术核心:field-sizing: content
使表单项能够根据输入内容动态调整尺寸,结合 interpolate-size()
或 calc-size()
实现平滑过渡。
场景案例:表格列宽根据字段内容自动收缩、标签栏宽度随文本动态扩展、编辑器输入框随内容增长自动调整高度等。
开发价值:消除了因内容长度不确定导致的布局错位问题,提升了动态数据场景下 UI 的健壮性。
1.1. 调整尺寸:field-sizing: content
****允许表单字段根据其内容自动调整大小,无需手动预估或使用 JavaScript 动态调整。这使得表单字段的大小更加灵活和合理,能够适应不同的内容长度。详细了解 字段大小调整,展示了不同表单元素在受影响之前和之后的表现。
textarea, select, input {
field-sizing: content;
}
在下面的示例中,随着用户输入,输入内容会沿行内方向增大,直到达到最大行内大小,此时文本会换行,输入内容的块大小会增大以适应新行。这种基于内容的大小调整样式不仅适用于 textarea
,还适用于其他元素,例如 select
和 input
元素等等。
1.2. 平滑过度:从 Chrome 129 开始,还可以使用 interpolate-size
属性或 calc-size()
函数,实现从长度到固有尺寸关键字(如 min-content
、max-content
、fit-content
)的平滑过渡和动画效果,为表单元素的动态展示增添了更多可能性。
:root {
interpolate-size: allow-keywords;
}
nav a {
width: 80px;
overflow-x: clip;
transition: width 0.35s ease;
&:hover,
&:focus-visible {
width: max-content;
}
}
由于 interpolate-size
属性是可继承的,因此可以在 :root
上声明该属性。在以下演示中,标签在用户悬停在图标上时能够以流畅的动画效果调整宽度。如果需要进行更精细的控制,可以改用 calc-size()
函数,例如 width: calc-size(fit-content, size + 1em)
。
技术核心::user-valid
和 :user-invalid
伪类,其行为与 :valid
和 :invalid
伪类类似,但只有在用户与输入内容进行了显著互动后,才会与表单控件匹配。
场景案例:适用于注册表单中,用户输入无效邮箱并点击提交后,提示错误信息,而非初始加载即报错。
开发价值:替代 :invalid
和 :valid
逻辑,避免过早干扰用户,提升表单交互的友好性。
input:user-invalid,
select:user-invalid,
textarea:user-invalid {
--state-color: red;
--bg: linear-gradient(15deg in oklch, #ea00ff, #ffb472);
}
以下示例中,当用户首次聚焦输入框时内容为空,不符合验证规则因此过早匹配 :invalid
的样式,易造成干扰。而 :user-invalid
初始时即使内容为空也不会匹配,需用户交互(提交 / 失焦)后生效,仅在明确操作后反馈错误,精准且克制。
技术核心:使用 <details>
与 <summary>
标签实现折叠 / 展开功能,结合 <details>
展开状态样式(如 [open]
属性)及伪类(如 ::details-content
)。
场景案例:适用于动态内容分层展示,如教程步骤、折叠文档章节,可精细控制展开动画。
开发价值:原生支持高可访问性,可定制交互效果,兼顾性能优化与视觉表达灵活性。
details {
display: flex;
flex-direction: row;
&[open] summary img {
filter: brightness(0.5);
}
}
::details-content {
transition: width 0.5s ease, content-visibility 0.5s ease allow-discrete;
width: 0;
}
[open]::details-content {
width: var(--open-size);
}
下面例子中手风琴组件横向排列多个可折叠区块,图片嵌入 <summary>
,点击区块时触发动画,关闭时收缩隐藏文字。其中 [open]
控制展开状态,::details-content
为内容区添加宽度过渡动画(width
从 0 到预设值)。
技术核心:基于父容器尺寸(而非视口)动态应用样式的响应式设计,通过 @container
定义容器上下文,实现组件级自适应。
场景案例:适用于卡片组件在网格布局中随容器宽度变化切换图文排版(如水平→垂直布局),或侧边栏折叠时内部按钮隐藏图标仅保留文字。
开发价值:解耦组件样式与全局视口依赖,提升 UI 模块的复用性与维护效率。
@container layout (inline-size > 800px) {
.grid {
grid-template-columns: repeat(2, 1fr);
}
.article-container:first-child {
grid-column: span 2;
}
}
@container layout (inline-size > 1000px) {
.grid {
grid-template-columns: repeat(4, 1fr);
}
.article-container:first-child {
grid-column: span 4;
}
.article-container:nth-child(2),
.article-container:nth-child(3) {
grid-column: span 2;
}
}
普通媒体查询是依据视口的宽度来应用样式的,而 @container
是基于容器元素自身的尺寸来应用样式。在下面的 demo 中,文章列表的样式变化是基于容器的尺寸,即便视口大小不变,只要容器尺寸因调整上下文空间而改变,样式就会相应调整,这让布局能实现更精细的响应式设计。
技术核心:text-wrap
属性得到了增强,新增了 balance
和 pretty
关键字。text-wrap: balance
用于使文本块更统一,而 text-wrap: pretty
则侧重于减少文本最后一行的单独字符。
场景案例:balance
适合标题/导航项等短文本对齐,pretty
适用于文章正文/产品详情等长段落排版优化。
开发价值:减少手动换行干预,适配动态内容场景(如多语言/响应式布局)。
h1 {
text-wrap: balance
}
过去设计师和内容编辑者更改文本长度平衡的方式,是使用 <br>
换行标签 或 \n
换行符 来辅助文本布局。而浏览器知道所有因素,例如字体大小、语言和分配区域,通过 text-wrap: balance
可以请求浏览器为文本找出最平衡的换行解决方案,效果如下所示:
技术核心:align-content
无需依赖 flex 或 网格布局,就能实现元素在块级 div 中的垂直居中。
场景案例:适用于多行文本垂直居中(支持输入框)。
开发价值:简化多行布局对齐逻辑,避免了 flex 或 网格布局 可能带来的边际效应,如边距收缩等问题。
textarea {
align-content: center;
}
textarea
是可替换元素,即使设置 flex 也无法实现内部文本垂直居中。align-content
支持默认占位符以及输入内容未超出时居中,超出后才正常滚动:
技术核心:CJK 文本功能的排版布局(中日韩)有了许多不错的更新,如 word-break: auto-phrase
可以在自然词组边界处换行,text-spacing-trim
用于在标点符号之间应用字距调整。
场景案例:auto-phrase
适用于多语言内容的断行优化,text-spacing-trim
用于出版级网页(如书籍、报刊)标点对齐。
开发价值:提升跨语言文本排版专业度与可读性,适配全球化内容的高标准视觉呈现需求。
4.1. 日语词组换行: 中文或日语等某些东亚语言不使用空格来分隔字词,并且行可以在任何字符处换行,即使是在字词中间也是如此。word-break: auto-phrase
指定应在这些边界处进行换行,从 Chrome 119 开始可用。
<html lang="ja">
<style>
h1 {
word-break: auto-phrase;
}
</style>
<h1>窓ぎわのトットちゃん<h1>
word-break: auto-phrase
提高了日文文本的可读性,对于标题或诗歌等简短文本,最好在自然短语边界处换行(在日语中,此边界称为“Bunsetsu”),如下面示例中的文本 窓ぎわ の トットちゃん。注意:需要 lang="ja"
来声明文本为日语。
4.1. CJK 标点字符间距: text-spacing-trim
控制 CJK 标点符号相邻字符之间(字距调整)以及文本行开始或结束处的内部间距设置。
.trim-start {
text-spacing-trim: trim-start;
}
在中文、日语和韩语中,在标点字符之间应用排版间距可提高可读性,并产生更具视觉吸引力的排版效果。目前,大多数印刷材料和文字处理器都采用这种排版方式。默认情况下是以下示例中 normal
的呈现结果,可以使用 text-spacing-trim
选择不同的样式。
技术核心:light-dark()
函数结合 color-scheme
属性,可根据系统主题自动切换明暗模式,保持页面主题与系统设置的一致性。
场景案例:适用于需要适配系统主题的网页,确保页面主题和控件样式与用户的系统偏好一致。
开发价值:简化了主题切换的逻辑,提升了组件与系统的视觉统一性,增强了用户体验。
:root {
color-scheme: light dark;
--primary-color: light-dark(black, white);
--primary-background: light-dark(white, black);
--highlight-color: light-dark(hotpink, lime);
&:has(input[name="color-scheme"][value="light dark"]:checked) {
color-scheme: light dark;
}
&:has(input[name="color-scheme"][value="light"]:checked) {
color-scheme: light;
}
&:has(input[name="color-scheme"][value="dark"]:checked) {
color-scheme: dark;
}
}
CSS 中的系统颜色能够对当前使用的 color-scheme
值(light/dark)做出反应,在以下演示中,单选按钮控制 color-scheme
的值。结合 light-dark()
函数,允许设置两个颜色值,如果用户设置了浅色主题,则返回第一个值;如果用户设置了深色主题,则返回第二个值。这种机制使得页面能够根据系统主题自动调整样式,为用户提供了一致的视觉体验。
技术核心:oklch()
在 Oklch 颜色空间中表示颜色,通过调整 L
(明度)、C
(色度)和 H
(色相),使颜色的调整更加精确和灵活。
场景案例:适用于动态生成和谐的配色方案,如按钮和背景的色阶,以及创建平滑过渡的渐变动效,如悬停效果。
开发价值:简化复杂的配色逻辑,增强视觉一致性,更好地适配现代广色域屏幕和动态主题的需求。
:root {
--hue: 230;
--primary: oklch(70% .2 var(--hue));
}
li {
--_bg: oklch(from var(--primary)
calc(l - (var(--i) * .05))
calc(c - (var(--i) * .01))
calc(h - (var(--i) + 5)));
}
在下面的示例中,颜色使用基于 Oklch 的主题设置。随着色相值根据滑块进行调整,整个主题也会随之变化。这是通过相对颜色语法实现的,背景和列表根据色相使用主色,并调整亮度、色度和色相通道以调整其值。这种方式使得颜色的调整更加高效,为开发者提供了更大的创作空间。
技术核心::has()
选择器允许开发者检查子元素是否具有特定子元素或处于特定状态,通过父选择器逻辑实现逆向匹配,突破了传统 CSS 单向层级的限制。
场景案例:适用于动态 DOM 节点的场景,例如为包含特定图标列表项设置独特的样式。
开发价值:减少了对 JavaScript 进行样式控制的依赖,实现了纯 CSS 的复杂交互反馈。
h1,
h2 {
margin: 0 0 1rem 0;
}
h1:has(+ h2) {
margin: 0 0 0.25rem 0;
}
下面示例并排显示了两个排版:左侧的带有 H1
标题,并紧跟一个段落,而右侧的带有 H1
标题,并紧跟一个 H2
副标题和一个段落。:has()
可以帮助选择 H1
元素后紧跟的 H2
元素(由兄弟选择器 +
指示),并通过 CSS 规则来减少标题的间距。
技术核心:@property
为 CSS 自定义属性(CSS 变量)提供了语义含义,并支持类型检查、默认值和回退值等功能,增强了 CSS 变量的可靠性和灵活性。
场景案例:适用于为渐变添加丰富丝滑的过渡动画效果,例如实现饼图的悬停动画。
开发价值:使得 CSS 变量更加可靠和强大,提升 CSS 动画的灵活性,减少运行时计算开销。
@property --per {
syntax: '<percentage>';
inherits: false;
initial-value: 25%;
}
div {
background: conic-gradient(pink, pink var(--per), transparent var(--per), transparent 100%);
transition: --per 300ms linear;
&:hover {
--per: 60%;
}
}
下面的演示实现了饼图的悬停动画,饼图为 conic-gradient
渐变背景的圆形节点。过去 conic-gradient
不支持 transition
过渡动画,现在借助 @property
自定义变量,使用 percentage
百分比类型改变渐变的角度就可以轻松达成。
未来,可以预见 CSS 将会更加强大和易用,可以构建出更高性能、高交互性和视觉表现力的页面。但我们也要注意应用需平衡 兼容性适配(如采用渐进式增强策略,结合特性检测和优雅降级方案)与可访问性设计,以实现新特性的稳健落地。
https://chrome.dev/css-wrapped-2024/
https://developer.chrome.google.cn/blog/new-in-web-ui-io-2024?hl=zh-cn
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。