背景

最近因为多邻国 App 的 Bug,我正在考虑切换到 Web 版本。但没想到移动端 Web 版本体验那么差,每次打开首页都会弹出 App 下载推广,这真的太烦人了。我第一时间就想去写个 UserScript 彻底删除它,但没想到还碰到一些有趣的问题。

1767703519864.jpg

分析

从 DevTools > Elements 中很容易就找到了弹窗元素的稳定选择器。

1
#overlays:has([href*="adj.st"])

页面遮罩也很容易定位。

1
[data-test="drawer-backdrop"]

然后我就可以正常点击了,但我仍然无法自由滚动,而滚动条锁定又不在 HTML/body 上,所以这种情况下应该如何找到是哪个 HTML 元素导致的滚动条锁定呢?

1767713512009.jpg

解决

想要解决这个问题需要一些简单的启发式的方法。首先,一般如何实现滚动条锁定?
通常只需要给 body 元素增加一些样式即可,例如

1
2
3
body {
overflow: hidden;
}

或者使用 position: fixed

1
2
3
document.body.style.position = 'fixed'
document.body.style.top = `-${scrollPosition}px`
document.body.style.width = '100%'

按照这种思路,我们可以找到一个在无法滚动区域内的元素,然后递归向上查找,直到找到 overflow: hidden; 或者 position: fixed 的元素即可认为它就是阻止滚动的罪魁祸首,实现起来相当简单。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function findScrollBlocker(element) {
const style = getComputedStyle(element)
// 检查当前元素是否设置了阻止滚动的样式
if (style.overflow === 'hidden' || style.position === 'fixed') {
return element
}
// 继续检查父元素
if (element.parentElement && element !== element.parentElement) {
return findScrollBlocker(element.parentElement)
}
return null
}

// 在 DevTools > Console 中调用,传入当前选中的元素
findScrollBlocker($0)
// 找到锁定元素后,可以通过以下方式恢复滚动
// const blocker = findScrollBlocker($0)
// if (blocker) blocker.style.overflow = 'auto'

视频演示

现在,我们可以通过 CSS 恢复正常的滚动条了。

tip: $0 在 DevTools > Console 中代表在 DevTools > Elements 面板中选中的元素。

总结

如果你也想尝试开发 Extension 或者 UserScript 来改善你的 Web 体验,不妨一试,JavaScript 提供了相当多 trick 的技巧,如果只是编写普通的 Web App,可能永远不会有机会尝试。

相关资源