如何防止浏览器在水平滚动时返回/前进历史记录?

21

如何使用JQuery或本地JS禁用现代浏览器的默认功能,以防止在水平滚动时向后或向前滚动?

当使用触摸板并滚动到可滚动div的末尾或开头时,通常会发生这种情况。


2
驱动程序和触摸板软件是您的霸主。请参阅此已回答的问题 - AmbrosiaDevelopments
5个回答

23
history.pushState(null, null, location.href);
window.onpopstate = function(event) {
    history.go(1);
};

演示: http://jsfiddle.net/DerekL/RgDBQ/show/

除非您疯狂点击后退按钮或按住后退按钮并选择先前的条目,否则您将无法返回上一个网页。

注:在iOS上似乎不起作用onpopstate(或事件onbeforeunload)。


4
没有冒犯的意思,但像那样操纵浏览器历史记录对用户体验来说非常不好。这样做会让人感到困惑和恼怒。不过我能理解你的意图。 - Steve C
4
如果你按住返回按钮,你仍然可以回到之前的页面。 - thdoan
1
@steve 如果没有必要的话,这样做确实很糟糕。但是,有些合法的情况需要这样操作,至少是暂时的。我想应用这种方式的一个案例是为了跳过使用CSS [:target](https://developer.mozilla.org/en-US/docs/Web/CSS/:target)伪类时产生的不必要的历史记录路径。或者,禁用历史记录,并提供自定义的“返回按钮”。 - hexalys
或者当有人在支付过程中使用后退按钮来使整个支付无效,而使用页面内的后退按钮则可以正常工作。我无法更改该流程,因为它由支付提供商管理,但我可以尝试帮助防止用户无意中搞砸它! - Luke Cousins

8

既然我创建了一个Web应用程序,为什么不提示用户是否存在未保存的更改呢?这样可以防止用户丢失任何未保存的更改,也可以防止用户浏览器历史记录中回到上一页或下一页。

如果其他人遇到了这个问题,这里是解决方案:

window.onbeforeunload = function(e) {
    return 'Ask user a page leaving question here';
}; 

1
可以使用e.preventDefault(); return false; - Jacksonkr

5
如果你使用的是Mac电脑,这是由于触控板手势引起的。
System Preferences -> Trackpad -> More Gestures. 

虽然这不是你要找的 JS 解决方案,但如果你只是想防止它影响到自己,你可以关闭该功能。


你说得很对,为什么他们要在浏览器中实现这样一个让人烦恼的来回跳转方式呢?我认为当你试图在水平滚动窗格中查找某些内容时,这对任何用户都是非常烦人的。 - Steve C

5

这里有一个使用 CSS 的 overscroll-behavior-x 属性 可能(或可能不)适用于您的东西。链接的 MDN 文章详细介绍了使用示例和浏览器支持信息。

尝试使用值 containnone 进行实验。引用自 MDN 链接,

contain:在设置此值的元素内观察默认滚动溢出行为(例如“弹跳”效果或刷新),但不会对相邻的滚动区域进行滚动链接,例如底层元素不会滚动。

none:不会对相邻的滚动区域进行滚动链接,并且防止默认的滚动溢出行为。

我猜测历史导航是否属于“默认滚动行为”类别取决于特定的浏览器/用户代理。最安全的选择可能是使用 none,除非您需要保留其他“默认滚动行为”。

Javascript

document.body.style.overscrollBehaviorX = "none";

CSS

body {
    overscroll-behavior-x: none;
}

请查看MDN链接中的浏览器支持表,并在您想要支持的浏览器和设备上进行测试。


4

适用于Chrome和Safari(即已在Chrome和Safari上测试):

// el === element on which horizontal scrolling is done 
// (can be container of scrolled element or body or any other ancestor)
var preventHistoryBack = function (e) {
  var delta = e.deltaX || e.wheelDeltaX;

  if (! delta) {
    return;
  }

  window.WebKitMediaKeyError /*detect safari*/ && (delta *= -1);

  if (((el.scrollLeft + el.offsetWidth) === el.scrollWidth && delta > 0) || (el.scrollLeft === 0 && delta < 0) ) {
    e.preventDefault();
  }
};
el.addEventListener('mousewheel', preventHistoryBack);

1
请注意,“wheel”和“mouseweel”的操作略有不同:https://dev59.com/0l8e5IYBdhLWcg3w7-Fz。 - Jacksonkr
它可以工作,但自Chrome 51以来,您将在控制台中看到“[Violation] Added non-passive event listener to a scroll-blocking 'wheel' event”消息。但我们需要非被动事件,因为我们调用了“preventDefault”,而不清楚如何抑制该消息。 - Klimashkin

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