1. ホーム
  2. css

[解決済み] ボディのスクロールを防止し、オーバーレイのスクロールを可能にする

2022-03-19 16:53:49

質問

これを可能にするquot;lightbox"タイプのソリューションを検索していますが、まだ見つかっていません(ご存知の方はご提案ください)。

私が再現しようとしている動作は、ちょうど以下のようなものです。 ピンタレスト 画像をクリックすると オーバーレイはスクロール可能である ( オーバーレイ全体がページの上にあるページのように上に移動するように ) が、本体 背後 のオーバーレイは固定されています。

これをCSSだけで作ろうとしたのですが( すなわち div でページ全体とボディの上にオーバーレイしています。 overflow: hidden ) を防ぐことはできませんが div がスクロール可能になります。

ボディ/ページがスクロールしないようにしながら、フルスクリーンコンテナの中でスクロールし続けるには?

解決方法は?

理論編

現在のピンタレストサイトの実装を見ると(将来的には変わるかもしれませんが)、オーバーレイを開いたときに noscroll クラスが適用され body 要素と overflow: hidden が設定されているため body はスクロールできなくなる。

オーバーレイ(オンザフライで作成されたもの、またはすでにページ内にあり display: block というように position : fixedoverflow-y: scroll である。 top , left , rightbottom プロパティに設定された 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; }

ジャバスクリプト (バニラ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);

});


最後に、オーバーレイがCSSによるフェードイン効果で開く別の例を示します。 transition に適用されます。 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; 
}