See the Pen 繰り返し利用可能なドロワーをJavaScriptだけで書く by 熊瀬川直也 (@momonoki1990) on CodePen.
使い方
- ドロワーの開閉ボタンに
data-drawer-btn="true"
data-drawer-target="{ドロワーのid}"
をセットする - ドロワー本体に
id
class="drawer"
data-drawer="true"
をセットする。 - ドロワーを閉じるボタンに
class="drawer"
data-drawer-close-btn="true" data-drawer-target="{ドロワーのid}"
をセットする - フェードレイヤーとナビゲーション(
nav
)が同じスタッキングコンテキストに属するように注意(ボタンの並びにおいて、共通の親要素であるdiv.my-drawer1
がヘッダー、かつ、position:fixed
でスタッキングコンテキストを生成してしまっていた時、フェードレイヤーがヘッダーの上か下になってしまい、結果としてヘッダーに内包されているナビゲーションも同じようにフェードレイヤの下か上になってしまって、ナビゲーションとヘッダーの間にフェードレイヤーを挟むことができず、嵌ってしまったので)
ベタがき
drawer.html
<div id="main">
<div class="my-drawer1">
<button class="drawer-btn" data-drawer-btn="true" data-drawer-target="drawer1">
開閉ボタン1
</button>
</div>
<nav class="drawer" id="drawer1" data-drawer="true">
<div>
<button class="drawer-close-btn" data-drawer-close-btn="true" data-drawer-target="drawer1">x</button>
</div>
<div class="drawer-menu">
<div class="drawer-title">
ドロワー1です
</div>
</div>
</nav>
<div class="my-drawer2">
<button class="drawer-btn" data-drawer-btn="true" data-drawer-target="drawer2">
開閉ボタン2
</button>
</div>
<nav class="drawer" id="drawer2" data-drawer="true">
<div>
<button class="drawer-close-btn" data-drawer-close-btn="true" data-drawer-target="drawer2">x</button>
</div>
<div class="drawer-menu">
<div class="drawer-title">
ドロワー2です
</div>
</div>
</nav>
<div class="my-drawer3">
<button class="drawer-btn" data-drawer-btn="true" data-drawer-target="drawer3">
開閉ボタン3
</button>
</div>
<nav class="drawer" id="drawer3" data-drawer="true">
<div>
<button class="drawer-close-btn" data-drawer-close-btn="true" data-drawer-target="drawer3">x</button>
</div>
<div class="drawer-menu">
<div class="drawer-title">
ドロワー3です
</div>
</div>
</nav>
</div>
<style>
.drawer {
position: fixed;
overflow: auto;
top: 0;
right: 0;
padding: 1rem;
background-color: red;
width: 300px;
height: 100%;
z-index: 100;
transition: all 0.2s;
transform: translate(340px);
}
.drawer-open {
transform: translate(0px);
}
.drawer-close-btn {
position: absolute;
top: 0;
left: 0;
}
.fade-layer {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
background-color: #000000;
opacity: 0.5;
z-index: 99;
}
.d-none {
display: none;
}
</style>
<script type="text/javascript">
// フェードレイヤーを生成しておく
window.addEventListener('DOMContentLoaded', () => {
const main = document.getElementById('main');
const fadeLayer = document.createElement('div');
fadeLayer.setAttribute('id', 'fade-layer');
fadeLayer.classList.add('fade-layer', 'd-none');
main.prepend(fadeLayer);
})
// フェードレイヤーの表示・非表示切り替え
toggleFadeLayer = () => {
const fadeLayer = document.getElementById('fade-layer');
fadeLayer.classList.toggle('d-none');
}
// ドロワーの表示・非表示切り替え
const toggleDrawer = (event) => {
const currentTarget = event.currentTarget;
const drawerTarget = currentTarget.getAttribute('data-drawer-target');
const drawer = document.getElementById(drawerTarget);
drawer.classList.toggle('drawer-open');
}
// ドロワーの開閉ボタンにクリックイベントを仕込む
const drawers = document.querySelectorAll('[data-drawer-btn="true"]');
drawers.forEach((drawer) => {
drawer.addEventListener("click", (event) => {
toggleDrawer(event);
toggleFadeLayer()
})
})
// ドロワーを閉じるボタンにクリックイベントを仕込む
const drawerCloseBtns = document.querySelectorAll('[data-drawer-close-btn="true"]');
drawerCloseBtns.forEach(closeBtn => {
closeBtn.addEventListener('click', (event) => {
toggleDrawer(event);
toggleFadeLayer();
})
})
// フェードレイヤーにクリックイベントを仕込む
// フェードレイヤーがクリックされたらドロワーを閉じて、フェードレイヤーを非表示にする
window.addEventListener('DOMContentLoaded', () => {
const fadeLayer = document.getElementById('fade-layer');
fadeLayer.addEventListener('click', () => {
const openingDrawer = document.getElementsByClassName('drawer-open')[0];
openingDrawer.classList.remove('drawer-open');
fadeLayer.classList.add('d-none');
})
})
</script>