Rik Schennink 文档 一个系统,可以编写 CSS 选择器,在页面滚动到某个位置时对页面进行样式设置。如果您像我一样,您已经在寻找 document.addEventListener('scroll' ...
并对性能感到恐惧。Rik 通过 防抖 函数以及将事件标记为 passive
来立即解决这个问题。
最终结果是在 <html>
元素上添加一个 data-scroll
属性,该属性可以在 CSS 中使用。这意味着如果您向下滚动页面 640px,则有 <html data-scroll="640">
,并且可以编写类似的 选择器
html:not([data-scroll='0']) {
padding-top: 3em;
}
html:not([data-scroll='0']) header {
position: fixed;
}
查看 Pen
编写 Dumb JS 🧟♂️ 和 Smart CSS 👩🔬 by Rik Schennink (@rikschennink)
在 CodePen 上。
不幸的是,我们在 CSS 中没有大于 (>
) 小于 (<
) 选择器来处理诸如编号属性之类的事情,因此 CSS 样式设置的潜力在这里相当有限。您可能最终需要更新 JavaScript 函数,使其根据您的数学运算应用其他类或数据属性。但是您已经为这里良好的性能做好了准备。
“当用户从顶部滚动时应用样式” 是一个合法的用例。这让我想到一个 once 函数(就像我们在 jQuery 中拥有的一样),其中任何滚动事件只会触发一次,然后不再触发。他们滚动过!因此,根据定义,他们不再处于顶部!但这并不能解决他们何时返回到顶部的問題。
我发现使用 IntersectionObserver
来根据滚动位置对事物进行样式设置通常更有用。使用它,您可以执行类似“此元素是否已滚动到视图中或超出视图”的操作,这通常很有用,并且可以用于从顶部滚动的物品。
这是一个示例,如果用户滚动到页面下方 500px 处的隐藏像素位置,则添加或删除一个类。
查看 Pen
使用 IntersectionObserver 固定标题 by Chris Coyier (@chriscoyier)
在 CodePen 上。
这也是高效的,完全避免了任何滚动事件处理程序。
说到 IntersectionObserver
,请查看 “信任是好的,观察是更好的——Intersection Observer v2”.
我认为在滚动侦听器上使用 passive 选项是多余的,因为无论如何您都无法阻止它。原因是滚动事件在浏览器中滚动发生后才触发。但是,轮盘事件可以被阻止,因此当我们可以时,最好在其侦听器上使用 passive 选项。
IntersectionObserver - 嗯,确实很酷……但没有 IE11 支持使其在生产中无法使用。
仅供参考:将来我们将有范围查询,请参见 https://drafts.csswg.org/mediaqueries-4/#mq-range-context
想到的问题是,我们应该在 css 中走多远?可以使用 JavaScript 并只设置类来轻松添加逻辑。这可能更有意义。就像使用 IntersectionObserver 的示例一样。
我相信设置一次类比始终更新 html 属性的性能更高。
我也很好奇这种防抖多久实际进行防抖,在我的开发机器上它没有任何作用。我仍然更喜欢在回调内部使用时间基防抖进行一次 requestAnimationFrame。或者在这种情况下使用节流。
我的滚动位置逻辑错误,因为它超过了 100%,但我做了一个简单的演示,使用 css 变量来真正更改任何滚动位置的样式。请注意,它在 Chrome 的稳定版本中有效,但将 css 变量和 calc 结合在 css 值中仍然有风险。(上次我在 Firefox 中测试类似的东西时,它不起作用)
似乎“在窗口中”是一个有效地持续的侦听器,那么它与用 requestAnimationFrame 替换滚动事件如何比较,就像 https://gist.github.com/Warry/4254579 一样?
实际上,IntersectionObserver 有一个官方的 w3c 垫片:https://github.com/w3c/IntersectionObserver/tree/master/polyfill
在此处查看它的实际示例:https://200.cravath.dev/industrialization-civil-war
我更喜欢使用粘性元素和 IO 作为间谍。
https://developers.google.com/web/updates/2017/09/sticky-headers#introducing_the_sticky-change_event
学习了一些新东西,谢谢。通常我使用 document.addEventListener('scroll' …) 进行动画,但我很好奇了解这种方法的性能问题。
第二个示例(使用 IntersectionObserver)是打算独立工作吗?还是它需要第一个示例中的代码?无论哪种方式,我都会收到一个错误:
无法在 'IntersectionObserver' 上执行 'observe':参数 1 不是 'Element' 类型。
谢谢。管理员编辑
确保 DOM 首先就绪;)
对于任何对游戏还比较陌生的人来说,示例中的标记是 SCSS,而不是 CSS。但是,即使将 SCSS 转换为 CSS 后,我也遇到了同样的错误。
我能够通过在文档中将 JavaScript 直接添加到它引用的元素下方来解决 JavaScript 错误(并使其正常工作)。如果有人知道如何在将 JavaScript 保留在其自己的外部文件中(在 head 元素中引用)的同时实现此功能,我很乐意听到它。谢谢。