COMPANY SERVICE STAFF BLOG NEWS CONTACT
2025.05.09

JavaScriptのセレクタフックはclass じゃなくてdata 属性で管理が良い!― 管理性・拡張性・安全性を高める設計 ―

テクログjavascript

はじめに

DOM 操作のフックに、

<button type="button" class="js-toggle-menu">開く</button>

みたいなクラス指定、よく使いますよね。
でもこれ、CSS のスタイル用クラスと、JS の機能用クラスがごっちゃになって、「どっちのためのクラス?」って後から迷子になりがちです。
そんな悩みを解決してくれるのが、data 属性による JavaScript フック設計です!

クラス指定のよくある悩み

  • ・CSSとJSの責務が混ざってて壊れやすい
  • ・命名ルールが人によってバラバラ
  • ・別担当者あるいは非エンジニアがクラスを変更→JS が壊れる

…という感じで、規模が大きくなると特にツラい。

data-js-**属性で全部スッキリ解決!

そこでオススメしたいのが、data 属性です!!
HTML5 から使えるようになったdata-**属性、実はめっちゃ便利です。
特に、JavaScriptのフック用途に使うと爆発的に管理しやすくなります。

例をどうぞ

<button
  data-js-trigger="menu"
  data-js-toggle-class="is-open"
>
  メニュー開く
</button>

<div data-js-target="menu" class="menu">中身</div>
const dataPref = "data-js";
const trigger = document.querySelector(`[${dataPref}-trigger]`);
const key = trigger.getAttribute(`${dataPref}-trigger`);
const target = document.querySelector(`[${dataPref}-target="${key}"]`);
const className = trigger.getAttribute(`${dataPref}-toggle-class`);
target?.classList.toggle(className);

ほら、クラス名をJSに直書きしてない!
クラス名すら HTML 側で宣言できるってめっちゃ柔軟じゃないですか?

これが data属性フック設計のいいところ

【1】見た目とJSの責任が完全に分かれる!

  • ・クラスは見た目用(btn, menu, is-open など)
  • ・data 属性は JS 用(data-js-trigger, data-js-target など)
    → もう「このクラスってJS 用?」って迷わない!

【2】data 属性って、値を持てるんです(これ最強)

クラスって「ラベル」だけなんですよね。
でも data属性なら、値を埋め込める!

<button
  data-js-modal-trigger="type01"
  data-js-modal-toggle-class="is-active"
>
  モーダル開く
</button>
<div data-js-modal-target="type01" class="modal">中身</div>
const dataPref = "data-js-modal";
const trigger = document.querySelector(`[${dataPref}-trigger]`);
const key = trigger.getAttribute(`${dataPref}-trigger`);
const target = document.querySelector(`[${dataPref}-target="${key}"]`);
const className = trigger.getAttribute(`${dataPref}-toggle-class`);
target?.classList.toggle(className);

→ いろんなUIに使い回せる、無限汎用トグル関数の爆誕!

【3】タブUIも値でつなぐだけで OK

<!-- タブ -->
<button data-js-tab-trigger="a">A</button>
<button data-js-tab-trigger="b">B</button>

<!-- 中身 -->
<div data-js-tab-target="a">Aの内容</div>
<div data-js-tab-target="b">Bの内容</div>
const dataPref = "data-js-tab";
const triggersAttr = `${dataPref}-trigger`;
const targetsAttr = `${dataPref}-target`;

document.querySelectorAll(`[${triggersAttr}]`).forEach((trigger) => {
  trigger.addEventListener("click", () => {
    const key = trigger.getAttribute(triggersAttr);
    document.querySelectorAll(`[${targetsAttr}]`).forEach((content) => {
      content.hidden = content.getAttribute(targetsAttr) !== key;
    });
  });
});

if 文なしでタブ切り替え、楽すぎる。

【4】非エンジニアや別担当者が触っても壊れにくい!

  • ・クラス名を変えても、JSに影響しない(JSはdata-**で管理してるから)
  • ・data属性さえ守れば、機能は絶対に壊れない
  • ・非エンジニアでも「これとこれが対応してるのね」って分かる

【5】命名ルール:data-js-役割-機能で統一感出る

属性名 意味
data-js-modal-trigger モーダルを開くボタン
data-js-tab-trigger タブ切り替えボタン
data-js-tab-target タブの中身
data-js-toggle-class トグルするクラス名

フックの一例

→ 名前見ただけで「何のための属性か」一発で分かる!

よくある疑問

Q. data属性ってクラスよりセレクタ遅くない?
→ ほぼ誤差です。現代ブラウザなら体感ゼロ。

Q. SEOやアクセシビリティに問題ある?
→ ないです。data属性はHTML5で正式に OK な書き方!

まとめ:data属性フックで快適 JS ライフを

比較項目 クラス指定 data 属性フック(おすすめ)
スタイルとの責務分離 難しい しっかり分離できる
柔軟性 if 文だらけ 値ベースで楽ちん
再利用性 構造に縛られる 汎用ロジックでどこでも使える
チーム開発 壊れやすい 安定&安全
命名統一 バラバラになりがち data-js-役割-機能で超わかりやすい

最後に

data属性でフックするだけで、JSがこんなに整理されて、HTML側で「動き方」まで決められるようになるなんて、素晴らしいですよね。

今では、もうクラスでフックする気になれません。もしあなたのプロジェクトでも「JS がごちゃついてきたな…」と思ったら、data属性ぜひ試してみてください!

この記事を書いた人

中田

入社年
2024年
出身地
東京都
業務内容
コーディング
特技・趣味
ゲーム、ギター

テクログに関する記事一覧