パーツ番号 08-10-06 ・ JavaScript使用
Escで閉じるフォーカストラップモーダル
開くとモーダル内にフォーカスが移動して閉じ込められ、Escキーまたはボタンで閉じると呼び出し元へフォーカスが戻ります。WordPressの確認ダイアログに最適です。
プレビュー
ソースコード
HTML
<div class="d08-10-06-demo">
<button class="d08-10-06-open" type="button">モーダルを開く</button>
<div class="d08-10-06-overlay" hidden>
<div class="d08-10-06-modal" role="dialog" aria-modal="true" aria-labelledby="d08-10-06-title">
<h4 id="d08-10-06-title" class="d08-10-06-title">確認</h4>
<p class="d08-10-06-text">Escキーまたは下のボタンで閉じます。フォーカスはモーダル内に留まります。</p>
<div class="d08-10-06-actions">
<button class="d08-10-06-cancel" type="button">キャンセル</button>
<button class="d08-10-06-ok" type="button">OK</button>
</div>
</div>
</div>
</div>CSS
.d08-10-06-demo{position:relative;width:100%;display:flex;justify-content:center}
.d08-10-06-open{background:#2a2d3a;color:#fff;border:none;border-radius:10px;padding:11px 20px;font-size:13px;font-weight:600;cursor:pointer}
.d08-10-06-overlay{position:absolute;inset:0;background:rgba(20,20,30,.5);display:flex;align-items:center;justify-content:center;border-radius:12px;animation:d08-10-06-fade .18s ease}
@keyframes d08-10-06-fade{from{opacity:0}to{opacity:1}}
.d08-10-06-modal{background:#fff;border-radius:14px;padding:20px;width:88%;max-width:260px;box-shadow:0 20px 40px rgba(0,0,0,.25);animation:d08-10-06-pop .22s cubic-bezier(.3,1,.4,1)}
@keyframes d08-10-06-pop{from{transform:scale(.9);opacity:0}to{transform:scale(1);opacity:1}}
.d08-10-06-title{margin:0 0 8px;font-size:15px;font-weight:700}
.d08-10-06-text{margin:0 0 16px;font-size:12px;color:#666}
.d08-10-06-actions{display:flex;gap:8px;justify-content:flex-end}
.d08-10-06-cancel,.d08-10-06-ok{border:none;border-radius:8px;padding:8px 14px;font-size:12.5px;font-weight:600;cursor:pointer}
.d08-10-06-cancel{background:#eef0f3;color:#444}
.d08-10-06-ok{background:#6a5cff;color:#fff}
.d08-10-06-cancel:focus-visible,.d08-10-06-ok:focus-visible,.d08-10-06-open:focus-visible{outline:2px solid #6a5cff;outline-offset:2px}JavaScript
(function(){
var root=document.querySelector('#item-08-10-06 .d08-10-06-demo');if(!root)return;
var openBtn=root.querySelector('.d08-10-06-open');
var overlay=root.querySelector('.d08-10-06-overlay');
var modal=root.querySelector('.d08-10-06-modal');
var cancelBtn=root.querySelector('.d08-10-06-cancel');
var okBtn=root.querySelector('.d08-10-06-ok');
var focusables=[cancelBtn,okBtn];
function openModal(){
overlay.hidden=false;
cancelBtn.focus();
document.addEventListener('keydown',onKeydown,true);
}
function closeModal(){
overlay.hidden=true;
document.removeEventListener('keydown',onKeydown,true);
openBtn.focus();
}
function onKeydown(e){
if(e.key==='Escape'){e.preventDefault();closeModal();return;}
if(e.key==='Tab'){
var idx=focusables.indexOf(document.activeElement);
if(e.shiftKey){
if(idx<=0){e.preventDefault();focusables[focusables.length-1].focus();}
}else{
if(idx===focusables.length-1||idx===-1){e.preventDefault();focusables[0].focus();}
}
}
}
openBtn.addEventListener('click',openModal);
cancelBtn.addEventListener('click',closeModal);
okBtn.addEventListener('click',closeModal);
})();クラス名 .d08-10-06 は本ライブラリ内での識別用です。複数のパーツを同じページで使う場合は、重複しないよう名前を変更してください。