页面想随滚动方向变效果,你还在写 JS 事件监听器?Chrome 144 悄悄把这个需求还给了 CSS
以前写”滚动方向决定 UI 显隐”这类交互,几乎没有不用 JS 的——监听 scroll 事件、比较前后位置、防抖节流、一整套下来小 50 行代码。现在 Chrome 144 悄悄放进来的 @container scroll-state() ,把这个能力用纯 CSS 接走了。
怎么用
核心就两步:给父容器声明 container-type: scroll-state,然后用 @container scroll-state() 查询子元素的滚动状态。
html {
container-type: scroll-state;
overflow: auto;
}
/* 向下滚就藏导航 */
@container scroll-state(scrolled: bottom) {
.site-header {
transform: translateY(-100%);
}
}
/* 滚回顶部就显示 */
@container scroll-state(scrolled: top) {
.site-header {
transform: translateY(0);
}
}
scroll-state() 查的是”最近一次相对滚动的方向”,值可以是 top / bottom / left / right,也可以是 x / y / block / inline 等轴向别名,还有一个 none 表示从未滚动过。这个”最近一次”很关键——它让 CSS 能记住用户最后往哪个方向划了,而不需要 JS 在运行时持续追踪。
能做什么
最经典的就是”hidey-bar”导航栏模式:页面向下滚,导航条自动滑出去;往回滚,导航条又滑回来。之前要靠 IntersectionObserver 或者 scroll 事件手写,现在一个 @container 规则就覆盖了。
另一个场景是滚动指示器:首次访问横向滚动容器时,用户一旦滚过,提示就消失。之前要做这个得在 JS 里 once 监听,用了 scroll-state 之后直接:
@container scroll-state(scrolled: inline) {
.scroll-indicator {
opacity: 0;
}
}
还有 stuck / snapped / scrollable 几个状态,分别对应吸顶元素、轮播吸附点、容器是否可滚动。Chrome 133 就支持了,Chrome 144 加了 scrolled。
跨浏览器现实
目前只有 Chrome/Edge 完整支持(133 基础 + 144 scrolled)。Firefox 和 Safari 还没有明确的时间线。所以生产环境还是得写 JS 降级方案,但可以用作渐进增强——不支持的浏览器导航条始终显示,功能不受影响。
实际上 Google 内部已经在把 Chromium WebUI 的老式 JS 滚动监听(CrScrollObserverMixin)迁移到这套原生 API,说明这个方向是被 Blink 团队自己认可的。
下一步
如果你项目里还在用 JS 做滚动方向检测,可以花十分钟把这个模式迁移过去:只需要一个带 overflow 的父容器声明 container-type: scroll-state,然后写几行 CSS。不用任何依赖,浏览器原生支持,运行时性能也比 JS 监听器干净。主流浏览器全部支持预计还要一段时间,但作为渐进增强现在就能上。
评论区
登录后可评论。