<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');
};
});
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.