到底滚动了没有?用 CSS @container scroll-state 查询判断

原文:Is it scrolled? Is it not? Let's find out with CSS @container scroll-state() queries

翻译:TUARAN

欢迎关注 {{前端周刊}},每周更新国外论坛的前端热门文章,紧跟时事,掌握前端技术动态。

过去几年里,我们经常需要用 JavaScript(滚动事件、Intersection Observer)来回答一些看似简单的问题:

  • 这个 sticky 头部现在真的"贴住"了吗?
  • 这个 scroll-snap 列表现在"吸附到哪一项"了?
  • 这个容器是否还能继续滚?左边/右边还有没有内容?

@container scroll-state(本文简称"scroll-state 查询")提供了一种 CSS 原生的状态查询方式:容器可以根据自己的滚动状态,去样式化子元素。

快速回顾:scroll-state 查询怎么用

先把某个祖先设置为 scroll-state 容器:

css 复制代码
.scroll-ancestor {
  container-type: scroll-state;
}

然后用容器查询按状态应用样式:

css 复制代码
@container scroll-state(stuck: top) {
  .child-of-scroll-parent {
    /* 只有"贴住顶部"时才生效 */
  }
}

Chrome 133:三件套(stuck / snapped / scrollable)

1) stuck:sticky 是否真的"贴住"了

当你用 position: sticky 做吸顶 header 时,常见需求是:只有在 header 真的贴住时才加背景、阴影。

css 复制代码
.sticky-header-wrapper {
  position: sticky;
  inset-block-start: 0;
  container-type: scroll-state;
}

@container scroll-state(stuck: top) {
  .main-header {
    background-color: var(--color-header-bg);
    box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
  }
}

2) snapped:当前吸附项

对于 scroll-snap 画廊,你往往想高亮当前吸附项,例如放大当前卡片、改变滤镜。

css 复制代码
.horizontal-track li {
  container-type: scroll-state;
}

@container scroll-state(snapped: inline) {
  .card-content img {
    transform: scale(1.1);
    filter: sepia(0);
  }
}

3) scrollable:某个方向上是否"还能滚"

这类需求过去常靠 JS 读 scrollLeft/scrollWidth/clientWidth。现在可以按方向做样式:

css 复制代码
@container scroll-state(scrollable: left) {
  .scroll-arrow.left {
    opacity: 1;
  }
}

@container scroll-state(scrollable: right) {
  .scroll-arrow.right {
    opacity: 1;
  }
}

Chrome 144:新增 scrolled(最近一次滚动方向)

写作时 Chrome 144 带来了 scrolled,用于判断"最近一次滚动的方向"。这让一些常见的 UI 模式可以不写 JS:

经典的"hidey-bar" 头部

css 复制代码
html {
  container-type: scroll-state;
}

@container scroll-state(scrolled: bottom) {
  .main-header {
    transform: translateY(-100%);
  }
}

@container scroll-state(scrolled: top) {
  .main-header {
    transform: translateY(0);
  }
}

"滚动提示"只在第一次交互后消失

例如横向滚动容器:用户一旦横向滚过,就隐藏提示。

css 复制代码
@container scroll-state(scrolled: inline) {
  .scroll-indicator {
    opacity: 0;
  }
}

小结

scroll-state 查询把一部分"滚动状态机"的能力下放给 CSS:

  • 能做渐进增强时,UI 代码会更轻、更稳定;
  • 状态可由浏览器内部实现,避免滚动事件带来的性能与时序问题;
  • 但要大规模依赖,还需要更完整的跨浏览器支持。

进一步阅读:

相关推荐
Languorous.2 分钟前
C++数据结构进阶|堆(Heap)详解:从手写实现到面试高频实战
数据结构·c++·面试
ricardo197338 分钟前
手写一个虚拟列表,万级数据滚动 FPS 稳定 60 帧
前端
小KK_40 分钟前
新手必看:一篇文章带你搞懂JavaScript作用域
前端
万邦科技Lafite41 分钟前
如何通过 item_search_img API 接口获取淘宝商品信息
java·前端·数据库
Jx65744 分钟前
初学者视角下的JavaScript作用域理解
javascript
雨辰AI44 分钟前
面试题:人大金仓事务隔离级别、MVCC 机制详解(与MySQL差异对比)
数据库·后端·mysql·面试·政务
AlbertZein1 小时前
干了三年全栈才悟到:TS + React 这套组合,真不是堆技术堆出来的
前端
化为五月1 小时前
我把 Hermes 接进了飞书,结果卡在“能发消息但就是不回”
前端
ClouGence1 小时前
豆包收费之后,我找到了更好用的 AI 工具
前端·人工智能·后端·ai·ai编程·ai写作
aircrushin1 小时前
音乐节结束前,拿手机📱搓了一个工具
前端·后端