ドロワーメニュー(右から)— ページ読み込みで自動表示
本記事では、ページを開いた瞬間に右からスライド表示されるドロワーメニューを
HTML / CSS / JS だけで実装します。
画面の暗幕クリック・ESC キー・「閉じる」ボタンで閉じられるほか、
アクセシビリティに配慮してフォーカス移動も行います。
すぐ使えるデモと、コピペ可能なタブ切替のコードブロックを用意しました。
コードについて
本記事のコードは AI(ChatGPT)による生成をベースに作成・調整しています。ご利用の環境でテストの上ご使用ください。
免責
本コードの利用に伴う不具合・損害について、当サイトは責任を負いません。自己責任にてご利用ください。
デモ
ページを開いた瞬間に右から自動でスライド表示されるドロワーメニューです。暗幕クリック・ESCキー・「閉じる」ボタンで閉じられます。
コードをコピーして使おう!
/* ================================
ドロワーメニューのスタイル定義
================================ */
/* ドロワー全体のラッパー */
.cp-drawer{
position:relative; /* 子要素の基準 */
}
/* 暗幕(ドロワー表示中のみ有効) */
.cp-drawer .layer{
position:fixed; /* 画面全体を覆う */
inset:0; /* 上下左右を0にして全体をカバー */
background:rgba(2,8,23,.5); /* 半透明の黒 */
opacity:0; /* 初期状態は非表示 */
pointer-events:none; /* 初期はクリック不可 */
transition:.2s; /* フェード用アニメーション */
}
/* data-open="1" が付与されたとき(開いた状態) */
.cp-drawer[data-open="1"] .layer{
opacity:1;
pointer-events:auto; /* クリック可能に */
}
/* ドロワーパネル本体 */
.cp-drawer .panel{
position:fixed;
top:0;
right:0; /* 右側からスライドイン */
width:320px; /* 横幅 */
height:100vh; /* 全高 */
background:#fff;
border-left:1px solid #e5e7eb;
box-shadow:-6px 0 20px rgba(2,8,23,.15); /* 影で浮かせる */
transform:translateX(100%); /* 初期は画面外 */
transition:.25s ease-out; /* スライドアニメーション */
display:flex;
flex-direction:column;
}
/* 開いたときのパネル */
.cp-drawer[data-open="1"] .panel{
transform:translateX(0);
}
/* ヘッダー(タイトル+閉じるボタン) */
.cp-drawer header{
display:flex;
justify-content:space-between;
align-items:center;
padding:12px 16px;
border-bottom:1px solid #e5e7eb;
}
.cp-drawer header h3{
margin:0;
font-size:16px;
}
.cp-drawer .close{
background:#fff;
border:1px solid #e5e7eb;
border-radius:8px;
padding:6px 10px;
cursor:pointer;
}
/* メニューリンク */
.cp-drawer nav{
padding:10px;
}
.cp-drawer nav a{
display:block;
padding:8px 10px;
border-radius:8px;
color:#0f172a;
text-decoration:none;
}
.cp-drawer nav a:hover{
background:#f8fafc;
}
/* 開くボタン */
.btn{
appearance:none;
background:#0b6bff;
color:#fff;
border:none;
border-radius:12px;
padding:10px 16px;
cursor:pointer;
}
.btn:hover{
opacity:0.9;
}
<!-- ================================
ドロワーメニューのHTML構造
================================ -->
<!-- ドロワー全体ラッパー -->
<div class="cp-drawer" id="drawer-auto" data-side="right" data-open="1">
<!-- 手動で開くためのボタン(任意配置OK) -->
<p>
<button class="btn" id="open-drawer-btn"
aria-haspopup="dialog"
aria-controls="drawer-auto-panel">
ドロワーを開く
</button>
</p>
<!-- 暗幕(背景クリックで閉じる) -->
<div class="layer" aria-hidden="true"></div>
<!-- パネル本体 -->
<aside class="panel"
id="drawer-auto-panel"
role="dialog"
aria-modal="true"
aria-labelledby="drawer-auto-title"
tabindex="-1">
<!-- ヘッダー部分 -->
<header>
<h3 id="drawer-auto-title">メニュー</h3>
<button class="close"
data-close-drawer
aria-label="閉じる">閉じる</button>
</header>
<!-- ナビゲーションリンク -->
<nav aria-label="サイト内メニュー">
<a href="#">ホーム</a>
<a href="#">サービス</a>
<a href="#">料金</a>
<a href="#">お問い合わせ</a>
</nav>
</aside>
</div>
// ================================
// ドロワーメニューの挙動を制御するJS
// ================================
(function(){
// 対象ドロワーを取得
const drawer = document.getElementById('drawer-auto');
if(!drawer) return;
// 要素参照
const layer = drawer.querySelector('.layer'); // 暗幕
const panel = drawer.querySelector('.panel'); // パネル本体
const closeBtn = drawer.querySelector('[data-close-drawer]');// 閉じるボタン
const openBtn = document.getElementById('open-drawer-btn'); // 開くボタン
// ESCキーで閉じる処理
function onKey(e){
if(e.key === 'Escape') close();
}
// 開く処理
function open(){
drawer.setAttribute('data-open','1'); // data-open=1を付与
panel && panel.focus(); // パネルにフォーカス
document.addEventListener('keydown', onKey);
}
// 閉じる処理
function close(){
drawer.removeAttribute('data-open'); // data-openを削除
document.removeEventListener('keydown', onKey);
openBtn && openBtn.focus(); // ボタンにフォーカス戻す
}
// イベント割り当て
closeBtn && closeBtn.addEventListener('click', close); // 閉じるボタン
layer && layer.addEventListener('click', (e)=>{ // 暗幕クリック
if(e.target === layer) close();
});
openBtn && openBtn.addEventListener('click', open); // 開くボタン
// ページ読み込み時に自動オープン
panel && panel.focus(); // パネルに初期フォーカス
document.addEventListener('keydown', onKey);
})();
コメント