问题描述
在玩了一段时间 position:sticky
之后,我开始为粘性导航实现它,并遇到了这个有趣但令人沮丧的滚动弹跳问题.
After playing with position: sticky
for a while, I started implementing it for sticky navigation and ran into this interesting, but frustrating scroll bouncing issue.
这是在许多网站上常见的导航行为类型,您通常会使用 javascript 来计算页面中相对元素的偏移量.当元素到达窗口顶部时,将添加一个 'stuck' 类,使用 position: fixed
将该元素从文档流中取出,并添加一个相同高度的虚拟元素在它的地方,以防止页面跳跃".此外,通常会看到 javascript 然后缩小导航的高度以在滚动时节省空间.
This is a common type of navigation behaviour seen on many sites, where you would traditionally use javascript to calculate offsets to a relative element in the page. When the element reaches the top of the window, a 'stuck' class would be added, taking the element out of the document flow with position: fixed
, and a dummy element of the same height would be added in it's place to prevent the page from 'jumping'. Additionally, it's common to see javascript then shrink the height of that navigation to save space while scrolling.
CSS 现在似乎用 position:sticky
处理了所有这些,除了(据我所知)检测元素何时卡住".相反,我使用一些 javascript 来进行卡住检测,发现一切正常,直到 粘性元素的高度需要更改.
CSS now seemingly takes care of all this with position: sticky
, apart from (as far as I can tell), detecting when the element is 'stuck'. Instead I used some javascript to do the stuck detection, discovering that everything works great, right up until the height of the sticky element needs to change.
这很难解释,但它会在生产中造成严重破坏 - 所以这里有一个简化的示例,以尽可能简单地说明这个问题.
It's pretty hard to explain, but it wreaks havoc in production - so here's a stripped down example I've made to illustrate the issue as simply as possible.
CSS 粘贴位置高度调整错误
当页面的高度恰到好处的长度时最好说明,所以我在元素上设置了一个固定的高度,以确保每个人都能看到相同的东西.您可以添加更多内容,但滚动过去时仍然存在问题.
It's best illustrated when the height of the page is just the right length, so I've set a fixed height on the element to make sure everyone is able to see the same thing. You can add more content and it's still an issue when scrolling past.
结果是一些非常奇怪的行为.向下滚动时,导航卡住,当它缩小导航栏时,浏览器会自动创建由 position:sticky
提供的虚拟元素",似乎保持同步用它.这意味着,当添加卡住的类时,整个页面变小,几分之一秒后,导航不再卡住,从而导致故障振动循环.
The result is some really weird behaviour. When scrolling down, the navigation sticks, and as it shrinks the navbar, the 'dummy element' the browser is automatically creating courtesy of position: sticky
seems to be kept in sync with it. That means, when the stuck class is added, the whole page gets smaller, and a fraction of a second later, the navigation is no longer stuck, thus resulting in a glitchy vibration loop.
我测试过的每个浏览器的行为也完全不同.在 chrome 中,这种弹跳永远无法解决,它一直处于无限循环中,不断添加/删除卡住的类.更有趣的是,在 Safari 中,滚动位置被推回"到不会出错的状态.然后在 Firefox 中,它会同时执行这两项操作,会出现一两秒钟的故障,然后再次强制滚动位置恢复.
The behaviour is also completely different across every browser I've tested. In chrome, this bouncing can never be resolved, it stays in the infinite loop constantly adding / removing the stuck class. More interestingly in Safari, the scroll position is 'pushed back' to a state where it wont bug out. Then in Firefox, it does both of these, glitching for a second or two, before forcing the scroll position back up again.
我想知道是否有人遇到过这种情况并提出任何解决方案?我想出的任何 js 解决方法都没有真正奏效或非常好!当然,随着人气的增长,更多的人会喜欢这个......
I'm wondering if anyone has experienced this, and come up with any solutions? Any js workaround I've come up with hasn't really worked or been very good! Surely as popularity grows, more people are going to hit this one...
欢迎天才的变通方法、技巧、见解或完美的解决方案!
Genius workarounds, hacks, insights, or perfect solutions all welcome!
推荐答案
在应用会改变其大小(并可能影响窗口大小)的更改时,尝试将 overflow-anchor: none;
添加到粘性元素/元素定位).
Try adding overflow-anchor: none;
to the sticky element when applying changes that would alter its size (and potentially affect window size/element positioning).
更新:最终,我找到的正确解决方案是:拥有一个永远不会改变大小的外部元素(它在任何给定断点处始终保持相同的全高).那个是粘的.但它也应该没有背景/视觉样式,并且它的有效高度应该由高度 + 底部边距定义(这样它就可以在文档中占用适量的初始空间,但实际上不会在视觉导航后阻止点击缩小并提供更多空间.
Update: ultimately, the right solution I've hit on is: have an outer element that NEVER changes size (it's always the same full height at any given breakpoint). That one is made sticky. But it also should have no background/visual styles, and it's effective height should be defined by height + bottom margin (so that it takes up the right amount of initial space in the document, but doesn't actually block clicks once the visual nav shrinks and gives more space.
然后有一个内部元素会改变大小,无论是在现实中还是在视觉上.
Then have an inner element that does change size, either in reality or just visually.
您还可以使用现代属性,例如包含:布局大小;像
You can also use modern properties like contain: layout size; on the inner element like
这篇关于位置:粘性 - 结合 javascript 高度调整时滚动弹跳的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!