What's new in Safari and WebKit
App Services 进阶 1m

Safari 与 WebKit 新特性

What's new in Safari and WebKit

2025年6月9日

在 Apple 官方观看视频

一句话判断

Safari 19 一口气补齐了 scroll-driven animations、anchor positioning 和 cross-document view transitions 这三个 CSS 大特性,终于不用再为这些写一堆 JavaScript polyfill 了。

这场 Session 讲了什么

这场 Session 按四个类别介绍了 Safari 近期(18.2 到 19)的大量 CSS 和媒体更新。

动画方面,scroll-driven animations 让你可以纯 CSS 把动画绑定到滚动进度,不再需要 JavaScript 监听 scroll 事件。两种时间线:scroll() 绑定到最近的滚动容器,view() 绑定到元素进出视口的过程。Cross-document view transitions 在 Safari 18.2 已经发布,只需一行 @view-transition { navigation: auto; } 就能让同源页面之间的导航拥有平滑过渡效果。

布局方面,anchor positioning 让一个元素可以锚定到另一个元素并根据视口自动调整位置,配合 popover API 使用堪称完美。视觉效果方面,background-clip: border-area 让边框也能用渐变或图片填充;shape() 函数替代 path() 创建响应式形状;text-wrap: pretty 优化排版的断行效果。媒体方面新增 SVG favicon 支持、HDR 图片支持(配合 dynamic-range-limit CSS 属性控制 SDR/HDR 混排效果),以及 Ogg Opus/Vorbis 音频格式支持。

值得深挖的点

Scroll-driven animations 的两种时间线模型

scroll() 时间线绑定到最近的滚动祖先,值域 0-100% 对应滚动条从头到尾。view() 时间线则绑定到元素在视口中的可见性——0% 是元素进入视口底部,100% 是元素完全离开视口顶部。配合 animation-range 属性,你可以精确控制动画在滚动过程中的起止点。

Session 中的课程网格动画是一个典型用例:方块从不同方向”组装”成网格。用 view() 时间线,把 animation-range 设为 0% 50%,意味着动画在元素进入视口时开始、到达视口中间时结束。这样用户有足够的阅读时间,方块不会在整页滚动过程中一直晃动。

这个设计的 trade-off 很明确:animation-range 设得太短,动画可能一闪而过用户没看到;设得太长,元素长时间处于运动状态影响可读性。Session 中建议动画在元素到达视口中间位置时就结束,这个经验值得参考。另外要注意 prefers-reduced-motion 媒体查询——即使是 scroll-driven animation 也需要考虑无障碍,特别是旋转、视差、缩放等容易引发眩晕的动画类型。

Anchor positioning 的两套 API

Anchor positioning 实际上有两套 API:position-areaanchor() 函数。position-area 把锚点周围的区域抽象为九宫格(左/中/右 × 上/中/下),用 bottom center 这样的关键字描述目标元素的位置。当空间不足时,position-try 属性可以定义备选位置,比如从 bottom span-right 切换到 bottom span-left,或者用 flip-inline 自动翻转。

anchor() 函数更底层,直接把目标元素的边缘对齐到锚点的边缘:top: anchor(bottom) 让目标的顶部对齐锚点的底部。对于需要精确偏移的场景(比如考虑 padding),anchor() 配合 calc() 更灵活。

WebKit 团队在标准制定过程中贡献了 position-area 这个更直观的 API。实际使用建议:简单场景用 position-area,需要动画或多锚点的复杂场景用 anchor() 函数。

代码片段

纯 CSS 实现滚动进度条,零 JavaScript:

.progress-bar {
    position: fixed;
    bottom: 0;
    left: 0;
    height: 4px;
    background: linear-gradient(to right, #ff6b35, #ffd700);
    transform-origin: left;
    animation: grow linear both;
    animation-timeline: scroll();
}

@keyframes grow {
    from { transform: scaleX(0); }
    to { transform: scaleX(1); }
}

一行 CSS 实现同源页面之间的过渡效果:

@view-transition { navigation: auto; }

用 anchor positioning 把下拉菜单锚定到头像按钮下方,自动响应视口变化:

.profile-button { anchor-name: --profile; }

.profile-menu {
    position: absolute;
    position-anchor: --profile;
    position-area: bottom span-right;
    position-try: flip-inline;
}

最佳实践

建议对 scroll-driven animation 和 view transition 始终包裹 prefers-reduced-motion 媒体查询。Crossfade 是相对安全的动画类型,但滑动、旋转等效果应该在 reduced motion 模式下禁用。

优先使用 position-area 而不是手动计算位置,因为它是 WebKit 团队推动的标准化方案,浏览器兼容性更好。需要响应式布局时,用 position-tryflip-inlineflip-block 而不是写 JavaScript 检测空间。

避免在不需要响应式的场景使用 shape() 函数——如果你的形状不需要随视口缩放,path() 函数的语法更简单直接。

还有什么值得关注

  • Safari 响应式设计模式回归了 viewport presets,可以从预设的设备尺寸中选择,支持一键旋转横竖屏。
  • HDR 图片支持 AVIF 和 HEIC 格式,dynamic-range-limit: constrained 值可以让 HDR 和 SDR 内容和谐共存(后续版本支持)。
  • 新增 Ogg Opus 和 Ogg Vorbis 音频格式支持,加上之前的支持,Safari 现在共支持 15 种媒体格式。WebM 也已支持 MediaRecorder API。
应用服务 Safari与Web