仅当模式打开 IOS 时如何禁用正文滚动
Posted
技术标签:
【中文标题】仅当模式打开 IOS 时如何禁用正文滚动【英文标题】:How to disable body scrolling when modal is open IOS only 【发布时间】:2019-07-14 04:13:43 【问题描述】:仅限ios / iPhone X / iPhone 7等
即使是 jquery 模态库也不起作用! https://jquerymodal.com/ - 在 iPhone 上打开模态框,您将能够滚动正文。
我发现很难找到一种解决方案,可以在每次打开模式时停止正文滚动而不使页面跳转到顶部(这与页面滚动一样糟糕)
这似乎是一个很多人都遇到过的大问题。正如你在这里看到的:
How to prevent body scrolling on iOS 12 when modal opened? https://***.com/questions/49760984/stopping-body-scroll-on-modal-open-bootstrap-4我在网上搜寻了没有运气,有人有解决办法吗?!
【问题讨论】:
【参考方案1】:经过多次尝试,我想出了:
/* Default (phone) */
body.modal-open
left: 0;
position: fixed;
right: 0;
/* Prevent scrolling of body */
overflow-y: hidden !important;
/* Small and above e.g. not a phone */
@media (min-width: 576px)
body.modal-open
/* Keep scrollbar */
overflow-y: scroll !important;
在默认模式(电话)下,我只是删除了垂直滚动条。由于它在手机上,它位于顶部,并且没有宽度。没有overflow-y,手机无法滚动。
但在桌面上,我喜欢永久的水平滚动,所以我在模态时强制打开它以防止屏幕移动 17px 宽度。
如果在桌面(全宽滚动条)上,如果用户将浏览器缩小到小于 576 像素,你会得到一个转变,但我可以忍受。
另外——我允许在模式中滚动。这样,模态不会在移动设备上从屏幕底部跑出。
【讨论】:
【参考方案2】:export default class BackgroundScroll
private scrollPosition = 0;
disable = (isDisable) =>
if (isDisable)
this.scrollPosition = window.pageYOffset;
document.body.classList.add('block-body-scroll');
document.body.style.top = `-$this.scrollPositionpx`;
if (this.checkIos())
document.body.classList.add('ios');
else
document.body.classList.remove('block-body-scroll');
window.scrollTo(0, this.scrollPosition);
;
private checkIos(): boolean
return (
['iPad Simulator', 'iPhone Simulator', 'iPod Simulator', 'iPad', 'iPhone', 'iPod'].includes(
navigator.platform
) ||
(navigator.userAgent.includes('Mac') && 'ontouchend' in document)
);
body.block-body-scroll
overflow: hidden;
width: 100%;
&.ios
position: fixed;
我们只为 ios 处理 position: fixed
。因为position: fixed
会影响其他浏览器如火狐。这是我在 typescript 上处理的代码,但纯 JS 或其他任何东西与我的基本相同。
【讨论】:
【参考方案3】:我创建了以下解决方案,适用于 iOS 12!
虽然下面的嵌入式演示使用的是 Bootstrap 4,但同样的解决方案也适用于 Bootstrap 3,因为所有模式类或事件名称都不同。
第 1 步:在模态打开时使用固定定位将body
冻结到位
当一个 Bootstrap 模态打开时,一个名为 .modal-open
的类被添加到 body
中。将以下附加样式添加到此类:
body
&.modal-open
bottom: 0;
left: 0;
position: fixed;
right: 0;
top: 0;
现在,每当打开模式时,body
将固定在适当的位置,并调整为与视口本身相同的尺寸。这完全阻止了滚动,因为没有任何地方可以滚动!
但是:这也意味着打开模态框会导致页面跳转到顶部,因为body
不再超出视口的底部边缘(假设页面内容更高)。
第 2 步:在模态打开时模拟之前的滚动距离
Bootstrap 公开在打开或关闭模式时触发的事件。我们可以使用这些来解决“跳到顶部”的问题,方法是在打开模式时拉动body
up 的顶部,这样看起来滚动位置没有改变:
$(function()
var $window = $(window),
$body = $("body"),
$modal = $(".modal"),
scrollDistance = 0;
$modal.on("show.bs.modal", function()
// Get the scroll distance at the time the modal was opened
scrollDistance = $window.scrollTop();
// Pull the top of the body up by that amount
$body.css("top", scrollDistance * -1);
);
);
但是,当模态框关闭时页面仍然会跳转到顶部,因为window
的scrollTop
值仍然是0
。
第 3 步:关闭模式时重置所有内容
现在我们只需要挂钩在模式关闭时触发的事件,并将所有内容恢复原状:
移除body
上的固定定位和负上限值
将窗口的滚动位置设置回原来的位置
$modal.on("hidden.bs.modal", function()
// Remove the negative top value on the body
$body.css("top", "");
// Set the window's scroll position back to what it was before the modal was opened
$window.scrollTop(scrollDistance);
);
无需手动移除body
上的固定定位,因为这是通过.modal-open
类设置的,Bootstrap 会在模态关闭时移除该类。
演示
将它们放在一起,现在您可以在模式打开时阻止 iOS 上的背景滚动,而不会丢失滚动位置!
在 iOS 设备上打开以下链接:https://daguy.github.io/ios-modal-fix/
【讨论】:
我已经在我的 iPhone 上用这个 codepen 尝试过这个代码:codepen.io/bkdigital/pen/YBbpvN - 它似乎不起作用,请在你的 iPhone 设备上尝试一下?您只能看到页面顶部,无论模态是否打开,正文都会被切断。 您有使用过此解决方案的网站吗? @daGuy @BennKingy – 看起来 Codepen 本身以某种方式干扰了它。它在我在独立页面上运行 iOS 12 的 iPhone XR 上完美运行:daguy.github.io/ios-modal-fix 在页面的顶部和底部都有打开模态的按钮,这样你就可以看到它在不同的滚动位置是如何工作的。 我已经在那里测试了你的链接并且它的工作完美!血腥的代码笔:P 我今天将实现这个 TYVM!【参考方案4】:嗯,我看到关于 SO 的主题很少。 试试这个吧?
@supports (-webkit-overflow-scrolling: touch)
/* CSS specific to iOS devices */
@supports not (-webkit-overflow-scrolling: touch)
/* CSS for other than iOS devices */
CSS media query target only iOS devices
【讨论】:
我不需要 IOS 特定的样式 hack,我需要在 IOS 上打开模式时停止正文滚动。以上是关于仅当模式打开 IOS 时如何禁用正文滚动的主要内容,如果未能解决你的问题,请参考以下文章
加载 twitter 引导模式对话框时,如何防止正文滚动条和移位?
Ipad iOS 滚动不一致:禁用正文滚动但允许在某些元素上滚动