私はこれを可能にする「ライトボックス」タイプのソリューションを探していましたが、まだ見つかっていません (ご存知でしたらご提案ください)。
私が再現しようとしている動作は、ピンタレスト画像をクリックすると、オーバーレイはスクロール可能です (オーバーレイ全体がページの上にページが重なるように上に移動します) が、オーバーレイの背後にある本体は固定されています。
私はこれを CSS だけで作成しようとしました (つまり、div
ページ全体と本文の上にオーバーレイを配置しますoverflow: hidden
div
) が、スクロールできなくなります。
本文/ページのスクロールは行わずに、フルスクリーン コンテナー内でスクロールし続けるにはどうすればよいですか?
ベストアンサー1
理論
Pinterest サイトの現在の実装を見ると (将来変更される可能性があります)、オーバーレイを開くと、要素noscroll
にクラスが適用されbody
(設定overflow: hidden
)、body
スクロールできなくなります。
オンザフライで作成されたオーバーレイ、または既にページに挿入されて を介して表示されたオーバーレイ (どちらでもかまいません)にはdisplay: block
、およびがあり、、、プロパティが に設定されています。このスタイルにより、オーバーレイがビューポート全体を埋め尽くします (ただし、現在は 2022 年なので、代わりに を使用できます)。position : fixed
overflow-y: scroll
top
left
right
bottom
0
inset: 0
div
オーバーレイの内側には垂直position: static
スクロールバーがその要素に関連付けられています。これにより、スクロール可能でありながら固定されたオーバーレイが作成されます。
オーバーレイを閉じるときは、それを非表示にする必要があります ( を使用display: none
)。また、JavaScript を使用してノードを削除することもできます (または、内部のコンテンツのみを削除することもでき、これはユーザー次第ですが、コンテンツの性質にも依存します)。
最後のステップは、noscroll
適用されたクラスも削除することですbody
(これにより、overflow
プロパティは以前の値に戻ります)。
コード
aria-hidden
(オーバーレイの属性を変更して表示/非表示を切り替え、アクセシビリティを向上させることで機能します)。
マークアップ
(開くボタン)
<button type="button" class="open-overlay">OPEN LAYER</button>
(オーバーレイと閉じるボタン)
<section class="overlay" aria-hidden="true" tabindex="-1">
<div>
<h2>Hello, I'm the overlayer</h2>
...
<button type="button" class="close-overlay">CLOSE LAYER</button>
</div>
</section>
CS
.noscroll {
overflow: hidden;
}
.overlay {
position: fixed;
overflow-y: scroll;
inset: 0; }
[aria-hidden="true"] { display: none; }
[aria-hidden="false"] { display: block; }
Javascript (バニラJS)
var body = document.body,
overlay = document.querySelector('.overlay'),
overlayBtts = document.querySelectorAll('button[class$="overlay"]'),
openingBtt;
[].forEach.call(overlayBtts, function(btt) {
btt.addEventListener('click', function() {
/* Detect the button class name */
var overlayOpen = this.className === 'open-overlay';
/* storing a reference to the opening button */
if (overlayOpen) {
openingBtt = this;
}
/* 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;
/* forcing focus for Assistive technologies but note:
- if your modal has just a phrase and a button move the
focus on the button
- if your modal has a long text inside (e.g. a privacy
policy) move the focus on the first heading inside
the modal
- otherwise just focus the modal.
When you close the overlay restore the focus on the
button that opened the modal.
*/
if (overlayOpen) {
overlay.focus();
}
else {
openingBtt.focus();
openingBtt = null;
}
}, false);
});
/* detect Escape key when the overlay is open */
document.body.addEventListener('keyup', (ev) => {
if (ev.key === "Escape" && overlay.getAttribute('aria-hidden') === 'false') {
overlay.setAttribute('aria-hidden', 'true');
body.classList.toggle('noscroll', false);
openingBtt.focus();
openingBtt = null;
}
})
transition
最後に、プロパティに適用されたCSS によってフェードイン効果でオーバーレイが開く別の例を示しますopacity
。また、padding-right
スクロールバーが消えたときに基になるテキストの再フローを回避するために が適用されます。
CS
.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;
inset: 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;
}