Highlight
Safari 19 引入 scroll-driven animations、cross-document view transitions 和 anchor positioning,让滚动联动动画、跨页过渡、弹层定位都可以纯 CSS 实现。
核心内容
做一个滚动进度条,过去得监听 scroll 事件再用 JavaScript 改 transform。Saron Yitbarek 在 Session 开头点出问题:JavaScript 能做的事很多,但只要能省掉,用户就能拿到更好的性能和续航(03:24)。Safari 19 把这件事推到了 CSS 里。
她以「A-School of Code」站点为例,演示了四类新能力。动画上,scroll-driven animations 让 CSS 直接绑到滚动进度,view transitions 让同源页面跳转时拥有平滑过渡。布局上,anchor positioning 把弹层、菜单这类常见交互所需的定位计算交给浏览器。视觉上,background-clip: border-area 让边框可以填渐变,shape() 函数取代 path() 写出响应式形状。媒体上则补齐了 SVG favicon、HDR 图片和 Ogg Opus/Vorbis。
详细内容
Scroll-driven animation 的最小例子(06:18)。把页脚的 ::after 伪元素做成进度条,用 animation-timeline: scroll() 把动画绑到滚动容器:
footer::after {
content: "";
height: 1em;
width: 100%;
background: var(--yellow);
left: 0;
bottom: 0;
position: fixed;
transform-origin: top left;
animation: progress-scale linear;
animation-timeline: scroll();
}
@keyframes progress-scale {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
关键点:
position: fixed+bottom: 0把进度条钉在视口底部。transform-origin: top left决定缩放从左侧开始。animation: progress-scale linear声明动画曲线为线性,时长不写。animation-timeline: scroll()把时间轴换成最近滚动容器的滚动进度,必须写在animation之后才能覆盖默认时间轴。@keyframes仍然是熟悉的 CSS,从scaleX(0)到scaleX(1)横向铺满。
view() 时间轴 + animation-range(12:20)。当动画希望随元素进出视口而触发时,用 view() 而不是 scroll():
.topic-item {
animation-fill-mode: both;
animation-timeline: view();
animation-range: 0% 50%;
&:nth-child(3n + 1) { animation-name: in-from-left; }
&:nth-child(3n + 2) { animation-name: in-from-middle; }
&:nth-child(3n + 3) { animation-name: in-from-right; }
}
关键点:
animation-fill-mode: both让元素在动画前后都保留对应帧的样式。animation-timeline: view()把进度绑到「元素相对视口」的位置。animation-range: 0% 50%限定动画只在元素从进入视口到滚到视口一半的过程中播放,剩下的滚动里元素就静止可读(12:00)。:nth-child(3n + 1/2/3)让三列分别命中三种不同的@keyframes,做出错落的入场效果。
Cross-document view transitions(14:20)。同源页面之间的导航,最少只要一行:
@view-transition {
navigation: auto;
}
@media not (prefers-reduced-motion) {
@keyframes slide-in {
from { translate: 100vw 0; }
}
@keyframes slide-out {
to { translate: -100vw 0; }
}
}
关键点:
@view-transition { navigation: auto }在两个页面都加上,浏览器就会自动给同源跳转套上淡入淡出。@media not (prefers-reduced-motion)把自定义滑动效果包起来,尊重系统的「减少动态效果」开关(16:00)。- 给具体元素声明
view-transition-name,再用::view-transition-old(...)和::view-transition-new(...)控制各自的进出动画。
Anchor positioning(21:58 → 23:25)。配合 popover API,菜单从此不用 JS 算位置:
.profile-button {
anchor-name: --profile-button;
}
.profile-menu {
position-anchor: --profile-button;
position-area: top right;
}
关键点:
anchor-name: --profile-button把按钮注册为锚点,名字是 CSS 自定义标识符。position-anchor: --profile-button让菜单选定锚点,建立绑定关系。position-area: top right用关键字声明菜单出现在锚点的右上区域;可换bottom center、span-right、span-left等值。- 需要更细粒度时改用
top: anchor(bottom); left: anchor(left),anchor()函数返回锚点对应边的坐标,可以放进calc()(28:26)。
border-area 渐变边框(31:05):
.primary-btn {
background: border-area linear-gradient(to bottom right in hsl, yellow, orange);
border-color: transparent;
}
关键点:
background简写中的border-area关键字让背景图延伸到边框区域。border-color: transparent把边框本色挖空,显示底下的渐变。- 这是过去用伪元素或 SVG 才能做出的渐变描边的纯 CSS 写法。
核心启发
-
把滚动进度条迁回 CSS:站点页脚或文章顶部的进度条,用
animation-timeline: scroll()替换原有的 scroll listener。值得做的理由是去掉 JS 后主线程不再被滚动事件唤醒,移动端续航和帧率都更稳。开始的方式:先在 Safari Technology Preview 打开演示页面,把现有进度条组件改写成position: fixed伪元素,再加上一行animation-timeline: scroll()验证。 -
用 view() + animation-range 做卡片入场:列表、卡片网格、长文档的小标题区,过去用 IntersectionObserver 触发动画。值得做的理由是
view()把「元素相对视口的位置」直接喂给动画进度,反向滚动时还能自然回放。开始的方式:选一个现有的 IntersectionObserver 入场动画,删掉 JS,改用animation-timeline: view(),把animation-range设成0% 50%让动画只占视口前半段,确保信息可读。 -
用 anchor positioning 替换 popper.js:所有依赖 popper.js / floating-ui 算位置的下拉菜单、tooltip。值得做的理由是
anchor-name+position-area+position-try把翻转逻辑交给浏览器,包体积、bug、键盘焦点都顺带解决。开始的方式:挑一个最简单的头像菜单,HTML 加popover+popovertarget,CSS 给按钮anchor-name、给菜单position-anchor与position-area: bottom center,再用@supports给老浏览器留旧路径。 -
prefers-reduced-motion当作硬约束:所有 scroll-driven 和 view-transition 代码都包进@media not (prefers-reduced-motion)。值得做的理由是 Saron 在 Session 中明确把 motion discomfort 列为常见症状,且包含眩晕、恶心等真实生理反应。开始的方式:在团队 CSS lint 里加一条规则,凡animation-timeline或@view-transition的所在选择器必须出现在prefers-reduced-motion媒体查询内,否则告警。
关联 Session
- Discover Apple-Hosted Background Assets — 利用 Apple 托管的 Background Assets 在用户首次启动前预下载大体积资源。
- Dive deeper into Writing Tools — 把 Writing Tools 接入文本控件,让校对、重写、转换在系统层完成。
- Dive into App Store server APIs for In-App Purchase — App Store Server API 与通知 V2 的最新更新,处理订阅与退款回调。
- Enhance child safety with PermissionKit — 用 PermissionKit 给儿童账号在通讯类应用里搭一层家长可控的安全门。
评论
GitHub Issues · utterances