出现无溢出情况下的空滚动条

4

我想知道有没有一种干净的方法来“重置”滚动条。

在下面的图片系列中,您可以看到相同大小的body和HTML之间的区别,其中一个有滚动条,而另一个没有。

有趣的是,最后一张图中没有滚动条,只有滚动条滚动的区域仍然存在。

我不想设置max-height属性为599px以避免溢出。我正在寻找任何见过这个bug并知道一种很好的方法来重置滚动条区域的人。

1. 第一张图片将chrome扩展程序扩展到最大的600px高度。

Initial Display (no overflow)

2.第二张图片将表格扩展到超出600像素的高度,产生了滚动条。

Extend table for overflow

3. 第三张图片将表格折叠并恢复显示到原始的600像素高度;然而,现在存在一个空的“滚动区域”?

Collapse table but overflow appears


1
我在想这是否是DOM的某种舍入误差... 我找不到任何记录表明出现过这样的错误,所以我很想知道其他人的想法。 - splch
1
对于 Blink 和 WebKit 浏览器,您可以通过 ::-webkit-scrollbar{ display:none; } 创建一个不可见的滚动条。 - lastr2d2
@lastr2d2,你的评论实际上激发了我尝试通过更改元素属性来强制刷新某些元素。由于某种原因,隐藏的溢出不会解决问题,但将溢出设置为自动或叠加,然后恢复到其他显示方式将刷新该元素。我会在我的答案中发布更多内容,但感谢你的评论,它帮助了我。 - splch
很高兴它在某种程度上有所帮助。 - lastr2d2
1个回答

1

使用requestAnimationFrame — 更新

通过使用requestAnimationFrame(),滚动条会在DOM重绘时得到精确刷新:

function scrollRefresh(element) {
    // initial overflow attribute
    element.style.overflow = "auto";
    requestAnimationFrame(() => {
        // final overflow attribute
        element.style.overflow = "overlay";
    });
}

使用requestAnimationFrame的好处是用户不会看到滚动条的变化,而是DOM会平滑地重绘。这种方法比setTimeout()更加流畅和高效。

使用setTimeout

一个强制DOM刷新滚动条的函数将会起作用:

function scrollRefresh(element) {
    // initial overflow attribute
    element.style.overflow = "auto";
    setTimeout(() => {
        // final overflow attribute
        element.style.overflow = "overlay";
    }, 17); // 17 ms timeout
}

这个解决方案有两点需要注意:

  1. 溢出切换必须包括auto溢出属性。以autooverlay开头并不重要,但是最终溢出属性与初始属性不同是必要的。
  2. 超时时间与成功率成比例。0毫秒的超时时间不起作用,而5毫秒的超时时间可以达到约30%的成功率。20毫秒的超时时间对我来说一直有效。

我认为超时时间与DOM刷新率有关。从快速搜索中得知,它大约是60 fps(或16.6̅毫秒),因此20毫秒已经足够了。17毫秒的超时时间应该足够缓慢,以使DOM始终呈现溢出更改。



这里有一个演示函数的工作方式:

working overflow refresh

我想感谢@lastr2d2的评论,因为它帮助我找到了解决方案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接