<body>  
  <main class="l-container">
    <section class="p-sec-wrap">
      <h2 class="c-ttl">bodyにoverflow: hidden;</h2>
      <button type="button" id="openBtn1" class="c-btn">open</button>
      <dialog class="modal-dialog" id="modalDialog1">
        <h3 class="modal-dialog-ttl">bodyにoverflow: hidden;</h3>
        <button type="button" id="closeBtn1" class="c-btn">close</button>
      </dialog>
    </section>

    <section class="p-sec-wrap">
      <h2 class="c-ttl">bodyとhtmlにoverflow: hidden;</h2>
      <button type="button" id="openBtn2" class="c-btn">open</button>
      <dialog class="modal-dialog" id="modalDialog2">
        <h3 class="modal-dialog-ttl">bodyとhtmlにoverflow: hidden;</h3>
        <button type="button" id="closeBtn2" class="c-btn">close</button>
      </dialog>
    </section>

    <section class="p-sec-wrap">
      <h2 class="c-ttl">bodyにposition: fixed;</h2>
      <button type="button" id="openBtn3" class="c-btn">open</button>
      <dialog class="modal-dialog" id="modalDialog3">
        <h3 class="modal-dialog-ttl">bodyにposition: fixed;</h3>
        <button type="button" id="closeBtn3" class="c-btn">close</button>
      </dialog>
    </section>
  </main>
</body>
body {
  position: relative;
}
button {
  cursor: pointer;
  border: none;
}
.l-container {
  height: 300vh;
  padding: 20px;
  background-color: #fcfcfc;
}
.p-sec-wrap {
  margin-block: 40px;
}
.c-ttl {
  margin-bottom: 12px;
}
.c-btn {
  width: 250px;
  padding-block: 7px 8px;
  border-radius: calc(1px / 0);
  background-color: #3e64ea;
  color: #fff;
}

/* modal */
.modal-dialog {
  width: 90%;
  height: 35em;
  padding: 20px;
  margin: auto;
  border: 0;
  border-radius: 0.6rem;
  position: fixed;
  inset: 0;
  transition: opacity 5s ease-out;
  &[open] {
    animation: fadeIn .2s forwards ease-out;
  }
  &-ttl {
    margin-bottom: 20px;
  }
}
.modal-dialog::backdrop {
  background-color: rgba($color: #888, $alpha: .8);
}
@keyframes fadeIn {
  from {
      opacity: 0;
  }
  to {
      opacity: 1;
  }
}
document.addEventListener('DOMContentLoaded', function() {
  function setModal(openBtnId, modalId, closeBtnId, openCallback, closeCallback) {
    const openBtn = document.getElementById(openBtnId);
    const modalDialog = document.getElementById(modalId);
    const closeBtn = document.getElementById(closeBtnId);
  
    // モーダルを開く
    openBtn?.addEventListener('click', async () => {
      modalDialog.showModal();
      if (typeof openCallback === 'function') {
        openCallback();
      }
    });
  
    // モーダルを閉じる
    closeBtn?.addEventListener('click', async () => {
      modalDialog.close(); 
      if (typeof closeCallback === 'function') {
        closeCallback();
      }
    });
  }
  
  // bodyにoverflow: hidden;のパターン
  setModal(
    'openBtn1',
    'modalDialog1',
    'closeBtn1',
    () => {
      document.body.style.overflow = "hidden";
    },
    () => {
      document.body.style.overflow = "visible";
    }
  );
  
  // bodyとhtmlにoverflow: hidden;のパターン
  setModal(
    'openBtn2',
    'modalDialog2',
    'closeBtn2',
    () => {
      document.documentElement.style.overflow = "hidden";
      document.body.style.overflow = "hidden";
    },
    () => {
      document.documentElement.style.overflow = "visible";
      document.body.style.overflow = "visible";
    }
  );
  
  
  const openFixedBtn = document.getElementById('openBtn3');
  const modalFixedDialog = document.getElementById('modalDialog3');
  const closeFixedBtn = document.getElementById('closeBtn3');
  const body = document.body;
  let scrollPosition = 0;

  // スクロールバーの幅を計算する
  const getScrollBarSize = () => {
    const scrollBarXSize = window.innerHeight - document.body.clientHeight;
    const scrollBarYSize = window.innerWidth - document.body.clientWidth;
    return isVerticalWritingMode() ? scrollBarXSize : scrollBarYSize;
  };

  // スクロール位置を固定する関数
  const backfaceFixed = (fixed) => {
    const scrollBarWidth = getScrollBarSize();
    document.body.style.paddingInlineEnd = fixed ? `${scrollBarWidth}px` : '';
    document.body.style.position = fixed ? 'fixed' : '';
  };

  openFixedBtn.addEventListener('click', function() {
    // 現在のスクロール位置を保存
    scrollPosition = window.scrollY;
    // スクロールを固定しスクロールバー幅を調整
    body.style.top = `-${scrollPosition}px`;
    backfaceFixed(true);
    modalFixedDialog.showModal();
  });

  closeFixedBtn.addEventListener('click', function() {
    modalFixedDialog.close();
    // スクロール位置の固定を解除
    backfaceFixed(false);
    body.style.top = '';
    document.body.style.paddingInlineEnd = '';
    // スクロール位置を元に戻す
    window.scrollTo(0, scrollPosition);
  });

  // 縦書きかどうかの判定関数
  const isVerticalWritingMode = () => {
    return window.getComputedStyle(document.body).writingMode.includes('vertical');
  };
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.