ライトボックスを使用している間は、親のhtml/bodyスクロールバーを無効にしようとしています。ここでの主な言葉は無効です。私はそうしますではないoverflow: hidden;
でそれを隠したいです。
これの理由は、overflow: hidden
がサイトをジャンプさせて、スクロールがあった領域を占めることです。
スクロールバーを表示したままスクロールバーを無効にすることが可能かどうかを知りたいです。
オーバーレイの下のページを上部に「固定」できる場合は、オーバーレイを開くときに設定できます。
body { position: fixed; overflow-y:scroll }
それでも右側のスクロールバーが表示されるはずですが、コンテンツはスクロールできません。オーバーレイを閉じるときにこれらのプロパティを元に戻すだけです。
body { position: static; overflow-y:auto }
この方法を提案したのは、スクロールイベントを変更する必要がないからです。
更新
また、少し改善することもできます。レイヤーを開く直前にJavaScriptを介してdocument.documentElement.scrollTop
プロパティを取得する場合は、body要素のtop
プロパティとしてその値を動的に割り当てることができます。上にいるか、すでにスクロールしている場合.
Css
.noscroll { position: fixed; overflow-y:scroll }
JS
$('body').css('top', -(document.documentElement.scrollTop) + 'px')
.addClass('noscroll');
選択したソリューションに4つの小さな追加:
ほとんどのブラウザで動作すると思われる完全な解決策:
CSS
html.noscroll {
position: fixed;
overflow-y: scroll;
width: 100%;
}
スクロールを無効にする
if ($(document).height() > $(window).height()) {
var scrollTop = ($('html').scrollTop()) ? $('html').scrollTop() : $('body').scrollTop(); // Works for Chrome, Firefox, IE...
$('html').addClass('noscroll').css('top',-scrollTop);
}
スクロールを有効にする
var scrollTop = parseInt($('html').css('top'));
$('html').removeClass('noscroll');
$('html,body').scrollTop(-scrollTop);
FabrizioさんとDejanさん、私を正しい方向に導いてくれたBrodoと、ダブルスクロールバーの解決方法 に感謝します
$.fn.disableScroll = function() {
window.oldScrollPos = $(window).scrollTop();
$(window).on('scroll.scrolldisabler',function ( event ) {
$(window).scrollTop( window.oldScrollPos );
event.preventDefault();
});
};
$.fn.enableScroll = function() {
$(window).off('scroll.scrolldisabler');
};
//disable
$("#selector").disableScroll();
//enable
$("#selector").enableScroll();
これは私にとって本当にうまくいった…。
// disable scrolling
$('body').bind('mousewheel touchmove', lockScroll);
// enable scrolling
$('body').unbind('mousewheel touchmove', lockScroll);
// lock window scrolling
function lockScroll(e) {
e.preventDefault();
}
これら2行のコードを、スクロールをロックするタイミングを決定するものでラップするだけです。
例えば.
$('button').on('click', function() {
$('body').bind('mousewheel touchmove', lockScroll);
});
Scrollイベントを無効にすることはできませんが、mousewheelやtouchmoveのように、スクロールにつながる関連アクションを無効にすることができます。
$('body').on('mousewheel touchmove', function(e) {
e.preventDefault();
});
私はOPです
Fcalderanからの回答の助けを借りて、私は解決策を形成することができました。使い方を明確にし、非常に重要な詳細width: 100%;
を追加するので、私はここに私の解決策を残します。
このクラスを追加します
body.noscroll
{
position: fixed;
overflow-y: scroll;
width: 100%;
}
これは私のために働いたと私はFancyappを使用していました。
あるいは、overflow: hidden
で本文のスクロールバーを非表示にし、同時に余白を設定してコンテンツがジャンプしないようにすることもできます。
let marginRightPx = 0;
if(window.getComputedStyle) {
let bodyStyle = window.getComputedStyle(document.body);
if(bodyStyle) {
marginRightPx = parseInt(bodyStyle.marginRight, 10);
}
}
let scrollbarWidthPx = window.innerWidth - document.body.clientWidth;
Object.assign(document.body.style, {
overflow: 'hidden',
marginRight: `${marginRightPx + scrollbarWidthPx}px`
});
そして、ギャップを埋めるために無効なスクロールバーをページに追加することができます。
textarea {
overflow-y: scroll;
overflow-x: hidden;
width: 11px;
outline: none;
resize: none;
position: fixed;
top: 0;
right: 0;
bottom: 0;
border: 0;
}
<textarea></textarea>
私は自分自身のライトボックスの実装のためにまさにこれをしました。これまでのところうまくいっているようです。
これが私たちが行った解決策です。オーバーレイを開いたときにスクロール位置を保存し、ユーザーがページをスクロールしようとしたときはいつでも保存位置にスクロールバックし、オーバーレイを閉じたときにリスナーをオフにします。
IEではちょっととんでもないですが、Firefox/Chromeでは魅力的です。
var body = $("body"),
overlay = $("#overlay"),
overlayShown = false,
overlayScrollListener = null,
overlaySavedScrollTop = 0,
overlaySavedScrollLeft = 0;
function showOverlay() {
overlayShown = true;
// Show overlay
overlay.addClass("overlay-shown");
// Save scroll position
overlaySavedScrollTop = body.scrollTop();
overlaySavedScrollLeft = body.scrollLeft();
// Listen for scroll event
overlayScrollListener = body.scroll(function() {
// Scroll back to saved position
body.scrollTop(overlaySavedScrollTop);
body.scrollLeft(overlaySavedScrollLeft);
});
}
function hideOverlay() {
overlayShown = false;
// Hide overlay
overlay.removeClass("overlay-shown");
// Turn scroll listener off
if (overlayScrollListener) {
overlayScrollListener.off();
overlayScrollListener = null;
}
}
// Click toggles overlay
$(window).click(function() {
if (!overlayShown) {
showOverlay();
} else {
hideOverlay();
}
});
/* Required */
html, body { margin: 0; padding: 0; height: 100%; background: #fff; }
html { overflow: hidden; }
body { overflow-y: scroll; }
/* Just for looks */
.spacer { height: 300%; background: orange; background: linear-gradient(#ff0, #f0f); }
.overlay { position: fixed; top: 20px; bottom: 20px; left: 20px; right: 20px; z-index: -1; background: #fff; box-shadow: 0 0 5px rgba(0, 0, 0, .3); overflow: auto; }
.overlay .spacer { background: linear-gradient(#88f, #0ff); }
.overlay-shown { z-index: 1; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<h1>Top of page</h1>
<p>Click to toggle overlay. (This is only scrollable when overlay is <em>not</em> open.)</p>
<div class="spacer"></div>
<h1>Bottom of page</h1>
<div id="overlay" class="overlay">
<h1>Top of overlay</h1>
<p>Click to toggle overlay. (Containing page is no longer scrollable, but this is.)</p>
<div class="spacer"></div>
<h1>Bottom of overlay</h1>
</div>
私は同様の問題を抱えていました:それが現われるとき、スクロールを妨げる左側のメニュー。高さが100vhに設定されるとすぐにスクロールバーは消え、コンテンツは右に急に動きました。
スクロールバーを有効にしたままにしておけば(しかし実際にはどこにもスクロールされないようにウィンドウをフルハイトに設定して)、もう1つの可能性は小さな下余白を設定することです。
body {
height: 100vh;
overflow: hidden;
margin: 0 0 1px;
}
基本的ではあるがうまくいく方法はスクロールを強制的に上に戻すことで、スクロールを事実上無効にすることです。
var _stopScroll = false;
window.onload = function(event) {
document.onscroll = function(ev) {
if (_stopScroll) {
document.body.scrollTop = "0px";
}
}
};
ライトボックスを開くとフラグが上がり、閉じるとフラグが下がります。
<div id="lightbox">
は<body>
要素の内側にあるため、ライトボックスをスクロールすると本体もスクロールします。解決策は、<body>
要素を100%以上拡張せずに、長いコンテンツを別のdiv
要素内に配置し、必要に応じてこのdiv
要素にスクロールバーをoverflow: auto
で追加することです。
html {
height: 100%
}
body {
margin: 0;
height: 100%
}
#content {
height: 100%;
overflow: auto;
}
#lightbox {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
<html>
<body>
<div id="content">much content</div>
<div id="lightbox">lightbox<div>
</body>
</html>
現在、ライトボックス(およびbody
)をスクロールしても、本体は画面の高さの100%以下であるため、効果はありません。
オーバーレイの下のページを上部に「固定」できる場合は、オーバーレイを開くときに設定できます。
.disableScroll { position: fixed; overflow-y:scroll }
このクラスをスクロール可能な本体に指定しても、右側のスクロールバーは表示されますが、コンテンツはスクロールできません。
ページの位置を維持するためにjqueryでこれを行います
$('body').css('top', - ($(window).scrollTop()) + 'px').addClass('disableScroll');
オーバーレイを閉じるときにこれらのプロパティを元に戻すだけです。
var top = $('body').position().top;
$('body').removeClass('disableScroll').css('top', 0).scrollTop(Math.abs(top));
この方法を提案したのは、スクロールイベントを変更する必要がないからです。
すべてのモーダル/ライトボックスのJavaScriptベースのシステムは、モーダル/ライトボックスをHTMLタグまたはボディタグに表示するときにオーバーフローを使用します。
ライトボックスが表示されているとき、jsはhtmlまたはbodyタグに隠されたオーバーフローをプッシュします。ライトボックスが隠れているときは、隠れているものを削除するものもありますhtmlまたはbodyタグにオーバーフローオートをプッシュします。
Macで作業する開発者は、スクロールバーの問題を見ません。
スクロールバーの削除のモーダルでコンテンツがスリップしないように、hiddenをunsetに置き換えます。
ライトボックスを開く/表示する
<html style="overflow: unset;"></html>
ライトボックスを閉じる/隠す
<html style="overflow: auto;"></html>
私は "overflow:hidden"メソッドを使い続け、スクロールバーの幅に等しいpadding-rightを追加するのが好きです。
lostsource でスクロールバー幅関数を取得します。
function getScrollbarWidth() {
var outer = document.createElement("div");
outer.style.visibility = "hidden";
outer.style.width = "100px";
outer.style.msOverflowStyle = "scrollbar"; // needed for WinJS apps
document.body.appendChild(outer);
var widthNoScroll = outer.offsetWidth;
// force scrollbars
outer.style.overflow = "scroll";
// add innerdiv
var inner = document.createElement("div");
inner.style.width = "100%";
outer.appendChild(inner);
var widthWithScroll = inner.offsetWidth;
// remove divs
outer.parentNode.removeChild(outer);
return widthNoScroll - widthWithScroll;
}
オーバーレイを表示するときは、htmlに "noscroll"クラスを追加し、bodyにpadding-rightを追加します。
$(html).addClass("noscroll");
$(body).css("paddingRight", getScrollbarWidth() + "px");
非表示にするときは、クラスとパディングを削除します。
$(html).removeClass("noscroll");
$(body).css("paddingRight", 0);
Noscrollスタイルはちょうどこれです:
.noscroll { overflow: hidden; }
Position:fixedの要素がある場合は、それらの要素にもパディングを追加する必要があります。
あなたはオーバーフローを保つことができます:隠されているが手動でスクロール位置を管理します:
実際のスクロール位置を追跡表示する前に:
var scroll = [$(document).scrollTop(),$(document).scrollLeft()];
//show your lightbox and then reapply scroll position
$(document).scrollTop(scroll[0]).scrollLeft(scroll[1]);
うまくいくはずです