私はこれを可能にする「ライトボックス」タイプの解決策を探していましたが、まだそれを見つけていません(あなたが何かを知っているなら提案してください)。
再作成しようとしている動作は、画像をクリックしたときに Pinterest に表示されるのとまったく同じです。オーバーレイはスクロール可能です(オーバーレイ全体はページの上にあるページのように上に移動します)が、本体 後ろ オーバーレイは固定されています。
私はCSS(すなわちA div
overflow: hidden
と全ページの上部と本体上のオーバーレイ)でこれを作成しようとし、それがスクロールされてからdiv
を妨げません。
本文/ページがスクロールしないようにしながらフルスクリーンコンテナ内をスクロールする方法
理論
Pinterestサイトの現在の実装を見ると(将来変更される可能性があります)、オーバーレイを開くと、noscroll
クラスがbody
要素に適用され、overflow: hidden
が設定されるため、body
はスクロールできなくなりました。
オーバーレイ(オンザフライで作成されるか、ページ内に既に作成され、display: block
を介して可視化され、違いはありません)には、position : fixed
およびoverflow-y: scroll
があり、top
、left
、right
、およびbottom
プロパティを0
に設定すると、このスタイルにより、オーバーレイがビューポート全体に表示されます。
オーバーレイ内のdiv
は代わりにposition: static
にあり、表示される垂直スクロールバーはその要素に関連しています。その結果、コンテンツはスクロール可能ですが、オーバーレイは固定されたままです。
ズームを閉じると(display: none
を介して)オーバーレイを非表示にし、javascript(または内部のコンテンツのみ)で完全に削除することもできます。挿入方法はユーザー次第です。
最後のステップとして、noscroll
クラスをbody
から削除する必要があります(したがって、オーバーフロープロパティは初期値に戻ります)
コード
(オーバーレイのaria-hidden
属性を変更して表示および非表示にし、そのアクセシビリティを向上させることにより機能します)。
マークアップ
(ボタンを開く)
<button type="button" class="open-overlay">OPEN LAYER</button>
(オーバーレイと閉じるボタン)
<section class="overlay" aria-hidden="true">
<div>
<h2>Hello, I'm the overlayer</h2>
...
<button type="button" class="close-overlay">CLOSE LAYER</button>
</div>
</section>
CSS
.noscroll {
overflow: hidden;
}
.overlay {
position: fixed;
overflow-y: scroll;
top: 0; right: 0; bottom: 0; left: 0; }
[aria-hidden="true"] { display: none; }
[aria-hidden="false"] { display: block; }
Javascript(Vanilla-JS)
var body = document.body,
overlay = document.querySelector('.overlay'),
overlayBtts = document.querySelectorAll('button[class$="overlay"]');
[].forEach.call(overlayBtts, function(btt) {
btt.addEventListener('click', function() {
/* Detect the button class name */
var overlayOpen = this.className === 'open-overlay';
/* Toggle the aria-hidden state on the overlay and the
no-scroll class on the body */
overlay.setAttribute('aria-hidden', !overlayOpen);
body.classList.toggle('noscroll', overlayOpen);
/* On some mobile browser when the overlay was previously
opened and scrolled, if you open it again it doesn't
reset its scrollTop property */
overlay.scrollTop = 0;
}, false);
});
最後に、transition
プロパティに適用されたCSS opacity
によるフェードイン効果でオーバーレイが開く別の例を示します。また、padding-right
が適用されて、スクロールバーが消えたときに下にあるテキストのリフローが回避されます。
CSS
.noscroll { overflow: hidden; }
@media (min-device-width: 1025px) {
/* not strictly necessary, just an experiment for
this specific example and couldn't be necessary
at all on some browser */
.noscroll {
padding-right: 15px;
}
}
.overlay {
position: fixed;
overflow-y: scroll;
top: 0; left: 0; right: 0; bottom: 0;
}
[aria-hidden="true"] {
transition: opacity 1s, z-index 0s 1s;
width: 100vw;
z-index: -1;
opacity: 0;
}
[aria-hidden="false"] {
transition: opacity 1s;
width: 100%;
z-index: 1;
opacity: 1;
}
Ios上でのオーバースクロールを防ぎたい場合は、.noscrollクラスに固定の位置を追加できます。
body.noscroll{
position:fixed;
overflow:hidden;
}
body
にoverflow: hidden;
を使用しないでください。それは自動的にすべてを一番上までスクロールします。 JavaScriptも必要ありません。 overflow: auto;
を利用してください。このソリューションはモバイルSafariでも動作します。
<div class="overlay">
<div class="overlay-content"></div>
</div>
<div class="background-content">
lengthy content here
</div>
.overlay{
position: fixed;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
background-color: rgba(0, 0, 0, 0.8);
.overlay-content {
height: 100%;
overflow: scroll;
}
}
.background-content{
height: 100%;
overflow: auto;
}
デモ here とソースコード here を参照してください。
更新:
キーボードのスペースバーを使ってページアップ/ダウンしたい場合は、オーバーレイにフォーカスを合わせる必要があります。たとえば、クリックするか、手動でJSのdiv
の一部がキーボードに応答するようにします。オーバーレイが横に移動しているだけなので、オーバーレイが「オフ」になっているときと同じです。それ以外のブラウザでは、これらは2つの通常のdiv
であり、なぜそれらのうちの1つに焦点を合わせるべきかわからないでしょう。
Bodyタグに "overflow:hidden"を追加してもうまくいかないことがあるのは注目に値します。その場合は、htmlタグにもプロパティを追加する必要があります。
html, body {
overflow: hidden;
}
ほとんどの解決策はスクロール位置を維持できないという問題を抱えているので、私はFacebookがそれをどうやって行うかを見ました。基になるコンテンツをposition: fixed
に設定することに加えて、それらはスクロール位置を保持するために動的にトップを設定します。
scrollPosition = window.pageYOffset;
mainEl.style.top = -scrollPosition + 'px';
その後、もう一度オーバーレイを削除するときには、スクロール位置をリセットする必要があります。
window.scrollTo(0, scrollPosition);
私はこの解決策を実演するために小さな例を作成しました
let overlayShown = false;
let scrollPosition = 0;
document.querySelector('.toggle').addEventListener('click', function() {
if (overlayShown) {
showOverlay();
} else {
removeOverlay();
}
overlayShown = !overlayShown;
});
function showOverlay() {
scrollPosition = window.pageYOffset;
const mainEl = document.querySelector('.main-content');
mainEl.style.top = -scrollPosition + 'px';
document.body.classList.add('show-overlay');
}
function removeOverlay() {
document.body.classList.remove('show-overlay');
window.scrollTo(0, scrollPosition);
const mainEl = document.querySelector('.main-content');
mainEl.style.top = 0;
}
.main-content {
background-image: repeating-linear-gradient( Lime, blue 103px);
width: 100%;
height: 200vh;
}
.show-overlay .main-content {
position: fixed;
left: 0;
right: 0;
overflow-y: scroll; /* render disabled scroll bar to keep the same width */
}
.overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.3);
overflow: auto;
}
.show-overlay .overlay {
display: block;
}
.overlay-content {
margin: 50px;
background-image: repeating-linear-gradient( grey, grey 20px, black 20px, black 40px);
height: 120vh;
}
.toggle {
position: fixed;
top: 5px;
left: 15px;
padding: 10px;
background: red;
}
/* reset CSS */
body {
margin: 0;
}
<main class="main-content"></main>
<div class="overlay">
<div class="overlay-content"></div>
</div>
<button class="toggle">Overlay</button>
overscroll-behavior
cssプロパティを使用すると、コンテンツの上部または下部に到達したときにブラウザのデフォルトのオーバーフロースクロール動作をオーバーライドできます。
オーバーレイに以下のスタイルを追加するだけです。
.overlay {
overscroll-behavior: contain;
...
}
現在はChrome、Firefox、IEで動作します( caniuse )
詳細については、 Google開発者向け記事 を確認してください。
選択された答えは正しいですが、いくつかの制限があります。
<body>
をスクロールします<input>
をタップして仮想キーボードを開くと、今後のスクロールはすべて<body>
に移動します。最初の問題に対する修正はありませんが、2番目の問題に焦点を当てたいと思いました。紛らわしいことに、Bootstrapはキーボードの問題を文書化していましたが、修正の例として http://output.jsbin.com/cacido/quiet を引用し、修正されたと主張しました。
確かに、その例は私のテストではiOS上でうまく動作します。しかし、それを最新のBootstrap(v4)にアップグレードすると壊れます。
両者の違いを理解するために、テストケースを短くしてブートストラップに依存しないようにしました、 http://codepen.io/WestonThayer/pen/bgZxBG 。
決定要因は奇妙です。キーボードの問題を回避するには、background-color
ではない modalを含むルート<div>
に設定する and<div>
を設定できる別のbackground-color
にネスティングする必要があります。
テストするには、Codepenの例の下の行のコメントを外します。
.modal {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 2;
display: none;
overflow: hidden;
-webkit-overflow-scrolling: touch;
/* UNCOMMENT TO BREAK */
/* background-color: white; */
}
一般的に言えば、子(この場合はオーバーレイ)がスクロールしたときに親(この場合は本文)がスクロールしないようにするには、子が親の兄弟になるようにします。親。親がボディである場合、これは追加のラッピング要素を必要とします。
<div id="content">
</div>
<div id="overlay">
</div>
ブラウザのメインスクロールバーで特定のDIVコンテンツをスクロールする を参照してください。
タッチデバイスの場合は、オーバーレイのラッパーに幅1px、幅101vh
、高さ最小の透明divを追加してみてください。次にラッパーに-webkit-overflow-scrolling:touch; overflow-y: auto;
を追加します。これは、モバイルサファリをオーバーレイがスクロール可能であると考えさせることによって、身体からのタッチイベントを傍受します。
これがサンプルページです。モバイルサファリで開く: http://www.originalfunction.com/overlay.html
https://Gist.github.com/YarGnawh/90e0647f21b5fa78d2f678909673507f
IpadとIphoneの自分のページで発生した問題を解決しようとしているこの問題を、私は固定divを画像付きポップアップとして表示しているときにスクロールさせていたことに気づきました。
いくつかの答えは良いです、しかしそれらのどれも私の問題を解決しませんでした。 Christoffer Petterssonによる次のブログ投稿を見つけました。そこに提示された解決策は、私がiOSデバイスに関して抱えていた問題を助け、それが私のスクロール背景問題を助けました。
iOS Safariのラバーバンドスクロールについて学んだ6つのこと
それが示唆されたように、私はリンクが時代遅れになる場合に備えてブログ記事の主要なポイントを含みます。
msgstr ""メニューが開いている間にユーザが背景ページをスクロールできることを無効にするためには、JavaScriptとCSSクラスを適用することによって、どの要素がスクロールを許可されるべきかどうかを制御できます。
この Stackoverflow answerに基づいて、disable-scrollingを持つ要素は、touchmoveイベントが発生したときにデフォルトのスクロールアクションを実行しないように制御できます。」
document.ontouchmove = function ( event ) {
var isTouchMoveAllowed = true, target = event.target;
while ( target !== null ) {
if ( target.classList && target.classList.contains( 'disable-scrolling' ) ) {
isTouchMoveAllowed = false;
break;
}
target = target.parentNode;
}
if ( !isTouchMoveAllowed ) {
event.preventDefault();
}
};
そして、ページdivにスクロール不可のクラスを追加します。
<div class="page disable-scrolling">
以前の回答に追加したいのですが、これをやろうとしましたが、本文をpositionに切り替えるとすぐにレイアウトが壊れてしまいました:fixed。それを避けるために、私は体の高さも100%に設定しなければなりませんでした:
function onMouseOverOverlay(over){
document.getElementsByTagName("body")[0].style.overflowY = (over?"hidden":"scroll");
document.getElementsByTagName("html")[0].style.position = (over?"fixed":"static");
document.getElementsByTagName("html")[0].style.height = (over?"100%":"auto");
}
次のHTMLを使用してください。
<body>
<div class="page">Page content here</div>
<div class="overlay"></div>
</body>
それからJavaScriptをスクロールしてスクロールを遮断し停止します
$(".page").on("touchmove", function(event) {
event.preventDefault()
});
それから物事を正常に戻すために:
$(".page").off("touchmove");
Body/html scrollを停止したい場合は、以下のように追加してください。
_ css _
html, body {
height: 100%;
}
.overlay{
position: fixed;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
background-color: rgba(0, 0, 0, 0.8);
.overlay-content {
height: 100%;
overflow: scroll;
}
}
.background-content{
height: 100%;
overflow: auto;
}
_ html _
<div class="overlay">
<div class="overlay-content"></div>
</div>
<div class="background-content">
lengthy content here
</div>
基本的に、あなたはJSなしでそれをすることができます。
主なアイデアは、高さ:100%、オーバーフロー:自動でHTML /ボディを追加することです。オーバーレイの内側では、要件に応じてスクロールを有効または無効にすることができます。
お役に立てれば!
意図がモバイル/タッチデバイスで無効にすることであるならば、それをする最も簡単な方法はtouch-action: none;
を使うことです。
例:
const app = document.getElementById('app');
const overlay = document.getElementById('overlay');
let body = '';
for (let index = 0; index < 500; index++) {
body += index + '<br />';
}
app.innerHTML = body;
app.scrollTop = 200;
overlay.innerHTML = body;
* {
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
}
#app {
background: #f00;
position: absolute;
height: 100%;
width: 100%;
overflow-y: scroll;
line-height: 20px;
}
#overlay {
background: rgba(0,0,0,.5);
position: fixed;
top: 0;
left: 0;
right: 0;
height: 100%;
padding: 0 0 0 100px;
overflow: scroll;
}
<div id='app'></div>
<div id='overlay'></div>
(この例は、スタックオーバーフローの状況では機能しません。スタンドアロンのページで再作成する必要があります。)
#app
コンテナのスクロールを無効にしたい場合は、touch-action: none;
を追加するだけです。
防止したい動作はスクロールチェーンと呼ばれます。無効にするには
overscroll-behavior: contain;
cSSのオーバーレイに。
これを試して
var mywindow = $('body'), navbarCollap = $('.navbar-collapse');
navbarCollap.on('show.bs.collapse', function(x) {
mywindow.css({visibility: 'hidden'});
$('body').attr("scroll","no").attr("style", "overflow: hidden");
});
navbarCollap.on('hide.bs.collapse', function(x) {
mywindow.css({visibility: 'visible'});
$('body').attr("scroll","yes").attr("style", "");
});