↑答えはここにあります
<dialog>の背景に×印を配置するには、2枚のdialogを重ねて対応。
/** * modal dialog open close * * author ao-system, Inc. * date 2024-04-13 * * <style> dialog#dialogBack01 { border: none; background-color: transparent; &::backdrop { background-color: rgba(0,0,0,0.5); } > div { position: fixed; right: 10px; top: 10px; font-size: 2.0rem; font-weight: 900; line-height: 1; color: #fff; } } dialog#dialog01 { padding: 0; border: none; &::backdrop { background-color: transparent; } > div { } } </style> <dialog id="dialogBack01"><div>×</div></dialog> <dialog id="dialog01"> <div> コンテンツ </div> </dialog> * */ (() => { new class { 'use strict'; #dialogOpen = document.getElementById('dialogOpen01'); #dialogBack = document.getElementById('dialogBack01'); #dialogBody = document.getElementById('dialog01'); constructor() { //開くボタンのクリック this.#dialogOpen.addEventListener('click', () => { this.#dialogBack.showModal(); this.#dialogBody.showModal(); //フェードインで開く this.#dialogBody.animate( [ {opacity:0}, {opacity:1}, ], {duration:300,fill:'forwards'} ); }); //ブラウザ内のクリック //クリックされた場所の親を辿り、ダイアログの前景(内側のdiv)だったら何もしない。 //ダイアログ自身(この場合はダイアログの背景)だったら閉じる。 this.#dialogBody.addEventListener('click',(event) => { let tgt = event.target; for (let i = 0; i < 99; i++) { //whileで回さずforなのは99回のリミッターを付けたため。記述ミスやブラウザの仕様変更やバグで無限ループを防ぐ。 if (tgt == this.#dialogBody.querySelector('div')) { return; } else if (tgt == this.#dialogBody) { this.#dialogBody.close(); this.#dialogBack.close(); return; } if (tgt.parentNode) { tgt = tgt.parentNode; } else { return; } } }); } } })();