command属性でモーダル実装|JavaScriptなしで開く方法
2026/09/24
先日Xで流れてきた投稿でJavaScriptを書かずにモーダルが開けるコードがあると知りました。
調べてみると、2025年12月12日のSafari 26.2リリースで主要4ブラウザに対応したところでした。
気になったので実際に使えるのか検証しましたので、もし「初めて聞いた」という方は参考にしていただけると幸いです。
コードの書き方:属性2つで開く
commandfor に操作対象のIDを書き、command に動作を書きます。基本的にそれだけで動きます。
実際のコードは以下のような感じです。
<button command="show-modal" commandfor="dlg">開く</button>
<dialog id="dlg">
<p>JavaScriptを1行も使わずに開いています。Escキーでも閉じられます。</p>
<button command="close" commandfor="dlg">閉じる</button>
</dialog>
上のコードをそのまま iframe でプレビューに入れました。見た目を整えるCSS以外は同じものです。JavaScriptが1行も入っていませんがしっかり動きます。
※Escキーで閉じますし、フォーカスもモーダル内に閉じ込められます。どちらもブラウザ側の挙動で実装はしていません。ボタンを押しても何も起きない場合は、ご利用のブラウザが未対応です。
実装時の注意ポイント:dialog に display を指定すると閉じなくなる
モーダル内の要素で画像とテキストを入れるパターンは案件時によくあります。そこで、2カラムにするため dialog { display: grid; } と書きました。ページを開いた時点でモーダルの中身が表示されたままになり、閉じるボタンを押しても消えません。
原因はブラウザの既定スタイルに dialog:not([open]) { display: none; } があるからでした。
そこへ display: grid を上書きすると、この指定を打ち消してしまいます。
代替案として、以下の実装が使えます。
/* ①:既定スタイルを自分で書き戻す */
dialog {
display: grid;
}
dialog:not([open]) {
display: none;
}
/* ②:モーダルの内側のラッパーに持たせる */
dialog > .modal-body {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1.5rem;
}
おすすめは②の方法です。保守性の観点からCSSの上書きはなるべくしないほうがいいと思います。
対応ブラウザの現状
| ブラウザ | 対応バージョン | リリース時期 |
|---|---|---|
| Chrome | 135 | 2025年4月 |
| Edge | 135 | 2025年4月 |
| Firefox | 144 | 2025年10月 |
| Safari | 26.2 | 2025年12月 |
| Safari(iOS) | 26.2 | 2025年12月 |
細かいバージョンごとの対応状況は Can I Use(commandfor属性) で確認できます。
まとめ
実際の案件で使用するかどうかの判断は、要件を確認して行うのがいいと感じました。
ただ、こういう方法もあると知っておくことで、実装の幅も広がりますし、修正案件時のコードに使われていた場合の対応もスムーズになると思います。
参考
- Invoker Commands API – MDN
- Invoker commands – web-features explorer
- HTML element: button: commandfor – Can I Use
おわりに
ここまで読んでいただき、ありがとうございました。
私たちは、できることを誠実にやる会社です。
Web・システム・AIのことで気になることがあれば、
「何から相談すればいいか分からない」段階でも大丈夫です。
お気軽にご相談ください。
▶ お問い合わせ
本記事は、Claudeでのやり取りから作成し、加筆・修正しております。