

下記のようにHTMLとCSSを作ってみました。  
サイドメニュー上でマウスをスクロールさせ、サイドメニューが全部表示されている場合（もしくはサイドメニューを下までスクロールしきった場合）は、コンテンツ側をスクロールさせたいのですが、やりかたがわかりません。

なにか方法はないかと思って下記ページをみてみましたが、やはりサイドメニューとメインコンテンツ側は独立しており、サイドメニュー上でマウスをスクロールしたとしても、コンテンツ側がスクロールすることはありませんでした。

  * <https://stackoverflow.com/questions/48107353/allow-one-grid-item-to-scroll-with-fixed-header-and-sidebar>
  * <https://stackoverflow.com/questions/58562531/css-grid-with-fixed-sidebar>

一方、CSSグリッドを使用しない以下の方法はサイドメニュー上でマウスをスクロールするとコンテンツ側がスクロールして内容を下部まで表示することができました。

  * <https://www.w3schools.com/howto/tryit.asp?filename=tryhow_css_sidenav_fixed2>
  * <https://www.w3schools.com/howto/tryit.asp?filename=tryhow_css_sidenav_fixed>

違いはなんなのでしょうか？CSSグリッドでは不可能なのでしょうか？それとも何かアプローチの仕方が違うのでしょうか？

[code]

    .mainSpace {
        min-height: 100vh;
        display: grid;
        grid-template: 
            "a-side a-body" 100vh
        /   320px 1fr;
    }
    .mainSpaceSide {
        grid-area: a-side;
        background-color: yellow;
        overflow: scroll;
    }
    .mainSpaceBody {
        grid-area: a-body;
        background-color: green;
        overflow: scroll;
    }
[/code]

[code]

    <div class="mainSpace">
        <div class="mainSpaceSide">
            start side<br>
            side<br>side<br>side<br>side<br>side<br>side<br>side<br>side<br>side<br>
            side<br>side<br>side<br>side<br>side<br>side<br>side<br>side<br>side<br>
            end side
        </div>
        <div class="mainSpaceBody">
            start main<br>
            main<br>main<br>main<br>main<br>main<br>main<br>main<br>main<br>main<br>
            main<br>main<br>main<br>main<br>main<br>main<br>main<br>main<br>main<br>
            main<br>main<br>main<br>main<br>main<br>main<br>main<br>main<br>main<br>
            main<br>main<br>main<br>main<br>main<br>main<br>main<br>main<br>main<br>
            main<br>main<br>main<br>main<br>main<br>main<br>main<br>main<br>main<br>
            end main
        </div>
    </div>
[/code]


CC BY-SA 4.0
2021-05-25T09:57:49.063
76056
2022-02-07T13:10:50.573
2021-05-25T16:54:35.827
3068
9008
question
html css
CSSグリッドでサイドメニュー固定を作ったが、サイドメニュー上でマウスをスクロールさせてもメインコンテンツ側がスクロールしない


ひとつの方法は、 **スクロール連鎖**
を利用するものです。スクロール連鎖とは、あるスクロールコンテナをスクロールし境界に達したとき、当該スクロールコンテナの祖先となるスクロールコンテナへスクロールが伝播することです。

今回の場合は、 `.mainSpace` を祖先スクロールコンテナ、 `.mainSpaceSide` を子孫スクロールコンテナとします。そして
`.mainSpaceBody` をスクロールコンテナとせず、 `.mainSpaceSide` のスクロールイベントを `.mainSpace`
へ伝播させます。するとスクロール連鎖によって、 `.mainSpaceSide` のスクロール境界に達したとき、あたかも `.mainSpaceBody`
がスクロールするかのような動作を実現出来ます。

[code]

    body {
      margin: 0;
      padding: 0;
    }
    
    .mainSpace {
      min-height: 100vh;
      display: grid;
      grid-template: "a-side a-body" 100vh / 320px 1fr;
      overflow: auto;
      background-color: green;
    }
    
    .mainSpaceSide {
      grid-area: a-side;
      background-color: yellow;
      overflow-y: scroll;
      position: sticky;
      top: 0;
    }
    
    .mainSpaceBody {
      grid-area: a-body;
    }
[/code]

[code]

    <div class="mainSpace">
      <div class="mainSpaceSide">
        start side<br> side
        <br>side<br>side<br>side<br>side<br>side<br>side<br>side<br>side<br> side
        <br>side<br>side<br>side<br>side<br>side<br>side<br>side<br>side<br> end side
      </div>
      <div class="mainSpaceBody">
        start main<br> main
        <br>main<br>main<br>main<br>main<br>main<br>main<br>main<br>main<br> main
        <br>main<br>main<br>main<br>main<br>main<br>main<br>main<br>main<br> main
        <br>main<br>main<br>main<br>main<br>main<br>main<br>main<br>main<br> main
        <br>main<br>main<br>main<br>main<br>main<br>main<br>main<br>main<br> main
        <br>main<br>main<br>main<br>main<br>main<br>main<br>main<br>main<br> end main
      </div>
    </div>
[/code]

* * *

もうひとつの方法は、 JavaScript を用いてスクロールする対象を制御するものです。ただし、 `scroll`
イベントは「ページの一番上や下から、さらに上や下へスクロールしようとしたとき」のように、そもそもスクロールが発生しないような場合には **発火しません**
。このため、ここでは **`wheel` イベントを使う**必要がある点に注意が必要です。さらに、 `WheelEvent.deltaY`
属性が必ずしもスクロールの方向を示すわけではない点にも注意を払う必要があります。

[code]

    const mainSpaceSide = document.querySelector(".mainSpace > .mainSpaceSide");
    const mainSpaceBody = document.querySelector(".mainSpace > .mainSpaceBody");
    const scrollLength = 100;
    
    mainSpaceSide.addEventListener(
      "wheel",
      function(e) {
        const direction = e.deltaY;
        if (direction < 0 && mainSpaceSide.scrollTop <= 0) {
          mainSpaceBody.scrollTo({
            top: mainSpaceBody.scrollTop - scrollLength,
            behavior: "smooth"
          });
        } else if (direction > 0 && (mainSpaceSide.scrollHeight - mainSpaceSide.scrollTop === mainSpaceSide.clientHeight)) {
          mainSpaceBody.scrollTo({
            top: mainSpaceBody.scrollTop + scrollLength,
            behavior: "smooth"
          });
        }
      }
    );
[/code]

[code]

    body {
      margin: 0;
      padding: 0;
    }
    
    .mainSpace {
      min-height: 100vh;
      display: grid;
      grid-template: "a-side a-body" 100vh / 320px 1fr;
    }
    
    .mainSpaceSide {
      grid-area: a-side;
      background-color: yellow;
      overflow: scroll;
    }
    
    .mainSpaceBody {
      grid-area: a-body;
      background-color: green;
      overflow: scroll;
    }
[/code]

[code]

    <div class="mainSpace">
      <div class="mainSpaceSide">
        start side<br> side
        <br>side<br>side<br>side<br>side<br>side<br>side<br>side<br>side<br> side
        <br>side<br>side<br>side<br>side<br>side<br>side<br>side<br>side<br> end side
      </div>
      <div class="mainSpaceBody">
        start main<br> main
        <br>main<br>main<br>main<br>main<br>main<br>main<br>main<br>main<br> main
        <br>main<br>main<br>main<br>main<br>main<br>main<br>main<br>main<br> main
        <br>main<br>main<br>main<br>main<br>main<br>main<br>main<br>main<br> main
        <br>main<br>main<br>main<br>main<br>main<br>main<br>main<br>main<br> main
        <br>main<br>main<br>main<br>main<br>main<br>main<br>main<br>main<br> end main
      </div>
    </div>
[/code]


CC BY-SA 4.0
2021-12-24T04:29:27.117
85316
2022-02-07T13:10:50.573
2022-02-07T13:10:50.573
32986
32986
76056
answer