1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

inert属性を使ってフォーカスやクリックを無効化する

Posted at

Webアプリケーションを作っていると 操作を無効にしたい場面がいろいろと出てきます。

例えば

  • API通信中は全画面にLoadingを表示し、さらに背景にフォーカス遷移を防止する。
  • モーダルダイアログ表示中はタブキーによって背景(親画面)へのフォーカス移動を防止する。

などのケースが存在します。

最近ほとんどのブラウザで使えるようになった inert という属性を使うことで 特定の領域内でのフォーカスやクリックの発生を無効化することができるようになります。

inert 属性を利用することでできることについては 参考のリンク先をご確認ください。

使い方

以下のように 適応したい領域のルートに inert 属性を付与します。

<div inert>
  <div>
    ここにあなたのお名前と血液型を選択して登録してください。
  </div>
  <div>
    <label for="yourName">お名前:</label>
    <input type="text" id="yourName">
  </div>
  <div>
    <label for="bloodType">血液型:</label>
    <select id="bloodType">
      <option value=""></option>
      <option value="A">A</option>
      <option value="B">B</option>
      <option value="O">O</option>
      <option value="AB">AB</option>
    </select>
  </div>
  <div>
    <button>登録</button>
  </div>
</div>

sample1.gif

このようにすることで領域選択やフォーカス、クリックが発生しなくなります。

スタイルを適用する

inert 属性を付与しても見た目上は変化がありません。

スタイルを適用することで見た目を変化させることができます。
(最近はCSSもネストができたり:isでまとめてかけたり便利ですね)

[inert] {
  & :is(input, select, button) {
    background-color: gray;
  }
}

sample2.png

JavaScriptを使って動的に付与する

実際のアプリケーションでは動的にinert を付与することがほとんどだと思います。

JavaScript では以下のようにすることで適用することができます。

<!-- 切り替え可能にするためにidを追加 -->
<div id="target">
  <div>
    ここにあなたのお名前と血液型を選択して登録してください。
  </div>
  <div>
    <label for="yourName">お名前:</label>
    <input type="text" id="yourName">
  </div>
  <div>
    <label for="bloodType">血液型:</label>
    <select id="bloodType">
      <option value=""></option>
      <option value="A">A</option>
      <option value="B">B</option>
      <option value="O">O</option>
      <option value="AB">AB</option>
    </select>
  </div>
  <div>
    <button>登録</button>
  </div>
</div>
<!-- 切り替え用ボタン -->
<button id="toggleInert">inert 切り替え</button>
const targetElem = document.getElementById("target")
const toggleInertElem = document.getElementById("toggleInert")

// クリック時に切り替える
toggleInertElem.addEventListener("click", () => {
  // 要素のinert属性にtrue/falseを設定する。
  // このコードでは反転した値を設定している。
  targetElem.inert = !targetElem.inert
})

sample3.gif

Vueを使った例

実際の開発では何らかのフロントエンドライブラリと組み合わせることがほとんどでしょう

ここでは Vueを使ってモーダルを表示する例を紹介します。モーダルにはBulmaのモーダルを利用します。

<script setup>
import { ref } from "vue";

const inert = ref(false);
const visibleModal = ref(false);

function show() {
  inert.value = true;
  visibleModal.value = true;
}

function closeModal() {
  inert.value = false;
  visibleModal.value = false;
}
</script>

<template>
  <div>
    <!-- inertにバインド -->
    <div :inert="inert">
      <div class="field">
        <label class="label">Name</label>
        <div class="control">
          <input class="input" type="text" placeholder="Text input" />
        </div>
      </div>

      <button class="button is-primary" @click="show">モーダル開く</button>

      <!-- Teleportの機能を利用しモーダル自体は このコンポーネントのDOMの外側に配置する。そうすることでinertの領域の外側となりモーダルはinertの影響を受けない-->
      <Teleport to="body">
        <template v-if="visibleModal">
          <div class="modal is-active">
            <div class="modal-background"></div>
            <div class="modal-card">
              <header class="modal-card-head">
                <p class="modal-card-title">モーダルヘッダー</p>
              </header>
              <section class="modal-card-body">
                モーダルの本体
              </section>
              <footer class="modal-card-foot">
                <button class="button is-success" @click="closeModal">OK</button>
              </footer>
            </div>
          </div>
        </template>
      </Teleport>
    </div>
  </div>
</template>

sample-vue.gif

ここでは単純な例にしていますが実際は無効化の対象領域がページ全体などになることが多いと思うので VuexやPiniaを用いてグローバルに状態管理をするか、親のコンポーネントからprovide/injectしてもよいかもしれません。

※dialog要素を使ってモーダルを表示する時はフォーカスが背景に移動しないようになっているそうですが、まだまだdiv要素を利用したモーダルが多いと思うので一例として紹介しました。

参考

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?