到底滚动了没有?用 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 代码会更轻、更稳定;
  • 状态可由浏览器内部实现,避免滚动事件带来的性能与时序问题;
  • 但要大规模依赖,还需要更完整的跨浏览器支持。

进一步阅读:

相关推荐
badhope33811 小时前
当所有AI都在抄同一份作业:前端模板的趋同、困局与破局
前端·ai·ai编程·前端开发·tailwind·ui设计
光影少年12 小时前
RN的Fabric 渲染流程
运维·前端·javascript·react native·react.js·fabric
__zRainy__12 小时前
React开始:直接在网站中使用React.js
前端·react.js·前端框架
用户0595401744613 小时前
大模型长记忆评测踩坑实录:2000条错位记忆,让我排查了整整3小时
前端·css
码林鼠13 小时前
webpack的基本配置
前端·webpack·node.js
用户9385156350714 小时前
React Router 进阶:路由守卫、登录鉴权与状态传递
前端·javascript·全栈
kyriewen14 小时前
我重写了自己用了两年的防抖节流Hook——发现里面藏着3个隐藏bug
前端·javascript·面试
阿祖zu14 小时前
芝士就是力量!开源私有化部署与 GitHub 双向同步的个人知识笔记 App
前端·后端·ios
漂流瓶jz14 小时前
Webpack开发环境:观察模式/webpack-dev-server/HMR热更新
前端·javascript·webpack
IT_陈寒14 小时前
SpringBoot自动配置失效?这个隐藏配置坑了我一整晚
前端·人工智能·后端