モーダルを開いたのに、背後にあるボタンやリンクを Tab キーで操作できてしまう。読み込み中のフォームを触られて二重送信になってしまう。こうした「一時的に、ある範囲だけ操作できないようにしたい」という場面で役立つのが HTML の inert 属性です。inert を付けた要素とその中身は、クリックもフォーカスもできなくなり、スクリーンリーダーからも無視されます。この記事では、inert の基本的な書き方から、モーダルの背後をまとめて無効化する実践的な使い方、disabled や aria-hidden との違い、そして「見た目が変わらないので気づきにくい」といったつまずきポイントまでを、具体的なコードとあわせて解説します。
目次
inert を付けると要素が「不活性」になる
inert は真偽値属性(boolean attribute)です。要素に付けるだけで、その要素と、中に含まれるすべての子孫が「不活性(inert)」な状態になります。不活性になった範囲では、次のことができなくなります。
- クリックなどのポインター操作に反応しない
- Tab キーやマウスでフォーカスできない
- マウスでのテキスト選択ができない
- スクリーンリーダーなどの支援技術から無視される
つまり、その部分がまるごと「存在しないもの」のように扱われる、と考えると分かりやすいです。ページ全体ではなく、指定した要素の内側だけをピンポイントで無効化できるのが特徴です。
基本の書き方
使い方はとてもシンプルで、無効化したい要素に inert と書くだけです。真偽値属性なので値は必要ありません。
<!-- この div の中はすべて操作できなくなる --> <div inert> <p>この説明文は選択できません。</p> <a href="/help">このリンクはクリックできません</a> <button>このボタンも押せません</button> </div>
状態を動的に切り替えたいときは、JavaScript から inert プロパティを使います。element.inert = true で不活性にし、element.inert = false で元に戻せます。属性の付け外し(setAttribute / removeAttribute)でも同じことができますが、プロパティを使うほうが簡潔です。
const box = document.getElementById("box");
// 不活性にする(操作できなくする)
box.inert = true;
// 元に戻す(操作できるようにする)
box.inert = false;
モーダルの背後をまとめて無効化する
inert の代表的な使いどころが、モーダルやダイアログを開いたときの「背後のコンテンツを操作できないようにする」処理です。モーダルを表示しても、背後のページにフォーカスが移動できてしまうと、Tab キーでの操作が裏側に抜けてしまい、キーボード利用者やスクリーンリーダー利用者にとって使いづらくなります。そこで、モーダルを開いている間だけ、背後のコンテンツ全体に inert を付けてしまうわけです。
次の例では、ボタンを押すとダイアログが開き、そのあいだ本文(main 要素)を inert で不活性にします。閉じると inert を外して元に戻します。[inert] { opacity: .4; } という CSS を添えて、不活性な部分が視覚的にも分かるようにしています。プレビューのタブを切り替えながら、ボタンを押して挙動を確かめてみてください。
<main id="main">
<h2>ページの本文</h2>
<p>下のボタンでダイアログを開きます。開いている間、この本文はクリックもフォーカスもできません。</p>
<p><a href="https://example.com">本文中のリンク</a> や <button>本文中のボタン</button> も操作できなくなります。</p>
<button id="open">ダイアログを開く</button>
</main>
<div id="dialog" class="dialog" hidden>
<div class="dialog__panel">
<p>これはダイアログです。背後の本文は inert で不活性になっています。</p>
<button id="close">閉じる</button>
</div>
</div>
body {
font-family: sans-serif;
padding: 16px;
}
/* inert が付いた要素は薄く表示して「操作できない」ことを伝える */
[inert] {
opacity: 0.4;
}
.dialog {
position: fixed;
inset: 0;
display: grid;
place-items: center;
background: rgba(0, 0, 0, 0.4);
}
.dialog__panel {
background: #fff;
padding: 24px;
border-radius: 8px;
max-width: 320px;
}
button {
padding: 6px 14px;
cursor: pointer;
}
const main = document.getElementById("main");
const dialog = document.getElementById("dialog");
document.getElementById("open").addEventListener("click", () => {
dialog.hidden = false; // ダイアログを表示
main.inert = true; // 背後の本文を不活性にする
});
document.getElementById("close").addEventListener("click", () => {
dialog.hidden = true; // ダイアログを隠す
main.inert = false; // 本文の操作を元に戻す
});
ポイントは、無効化したいのが「モーダル以外のすべて」だということです。モーダル自体は操作できる必要があるので、モーダルの外側にあたる main や、ヘッダー・フッターなどにだけ inert を付けます。同じ考え方は、画面の横から出てくるオフキャンバスメニューを開いたときや、通信中にフォーム全体を一時的に触れないようにしたいときにも使えます。
disabled や aria-hidden との違い
「操作できないようにする」ための手段は inert のほかにもいくつかあり、それぞれ効果の範囲が異なります。混同しやすいので、代表的なものを比べてみましょう。
| 方法 | クリック無効 | フォーカス無効 | 支援技術から除外 | 対象 |
|---|---|---|---|---|
inert | する | する | する | 任意の要素とその子孫 |
disabled | する | する | 「無効」として読まれる | フォーム部品のみ |
aria-hidden="true" | しない | しない | する | 任意の要素とその子孫 |
pointer-events: none | する | しない | しない | 任意の要素(CSS) |
disabled は button や input といったフォーム部品専用の属性で、div や section のような一般の要素には使えません。aria-hidden は支援技術から隠すだけで、マウスやキーボードでは普通に操作できてしまいます。pointer-events: none はマウス操作こそ防げますが、Tab キーによるフォーカスは残るうえ、スクリーンリーダーからも読み上げられます。
これに対して inert は、クリックもフォーカスもテキスト選択も止め、さらに支援技術からも除外するという、いわば「まとめて無効化」を1つの属性で実現します。しかも一般の要素にそのまま使えるので、モーダルの背後全体のように「範囲まるごと」を無効にしたいときに最も適しています。
付けたのに効いていないと感じるとき
inert を使い始めたときに戸惑いやすいのが、属性を付けても見た目がまったく変わらない点です。原因を切り分けやすいよう、よくある2つのケースに分けて説明します。
見た目が変わらず、付いているか分からない
inert は、あくまで「操作できるかどうか」を制御する属性で、要素の見た目には手を加えません。そのため、属性が付いていても画面上は普段どおりに見え、うっかり付け忘れ・外し忘れに気づきにくいという問題があります。実際にクリックやフォーカスを試すまで効いているか分からないため、開発中は混乱のもとになりがちです。
おすすめは、属性セレクターを使って不活性な要素に見た目の変化を付けておくことです。次のように書いておくと、inert が付いている間だけ半透明になり、状態が一目で分かります。
/* inert が付いている要素を薄く表示する */
[inert] {
opacity: 0.5;
/* 必要ならフィルターなどを足してもよい */
}
古い環境で動かないとき
inert は比較的新しく標準化された属性で、現在のモダンブラウザ(Chrome・Edge・Firefox・Safari の新しいバージョン)ではすでに利用できます。一方で、かなり古いブラウザや一部の古い環境では未対応で、その場合は属性が単に無視され、要素は普通に操作できてしまいます。
古い環境まで確実にサポートしたい場合は、公式に用意されている polyfill(WICG の inert polyfill)を読み込むことで、未対応ブラウザでも近い挙動を再現できます。まずは対象ユーザーのブラウザ状況を確認し、必要なときだけ polyfill を追加する、という判断でよいでしょう。
まとめ
inert は、付けた要素とその子孫をまるごと「不活性」にする真偽値属性です。クリック・フォーカス・テキスト選択を止め、さらに支援技術からも除外するため、モーダルを開いたときに背後のコンテンツ全体を無効化する用途にぴったりです。書き方は要素に inert と付けるだけ、JavaScript からは element.inert = true / false で切り替えられます。disabled はフォーム部品専用、aria-hidden は読み上げを隠すだけ、pointer-events: none はフォーカスが残る、といった違いを踏まえると、範囲まるごとを包括的に無効化したいときに inert が最適だと分かります。見た目が変わらず気づきにくいので [inert] セレクターで視覚的な変化を添える、古い環境では polyfill を検討する、という2点を押さえておけば安心して使えます。