【JavaScript】dataset と getAttribute の違いは?data属性の取得方法と活用例

JavaScriptでUIを実装していると、「HTML要素そのものに特定のデータ(IDやカテゴリ名など)を持たせておいて、クリックされた時にJSでそのデータを読み取りたい」という場面がよくあります。 そんな時に活躍するのが、data-* 属性(カスタムデータ属性) です!

値を取得する方法として dataset と getAttribute の2種類がありますが、今回はそれぞれの違いや使い分けのポイントを解説します。「タブ切り替え」などのデモを交えて、実践的な使い方をご紹介します!

デモ動作

See the Pen data属性の取得方法と活用例 by mikanbako (@mikanbako) on CodePen.

全画面でのデモ動作は以下のリンクからご確認下さい!(別タブで開かれます)

実装コード紹介

【HTML】

<div class="l-wrap">
  <h2>data属性 活用デモ</h2>

  <!-- 活用例1:タブ切り替え -->
  <section class="p-section">
    <h3>1. タブ切り替え(表示要素の紐付け)</h3>
    <ul class="c-tab-list">
      <!-- 💡 data-target に表示したいコンテンツのIDを持たせる -->
      <li class="c-tab-item is-active js-tab" data-target="tab-a">タブA</li>
      <li class="c-tab-item js-tab" data-target="tab-b">タブB</li>
    </ul>
    <div class="c-tab-content is-active js-content" id="tab-a">タブAのコンテンツです。</div>
    <div class="c-tab-content js-content" id="tab-b">タブBのコンテンツです。</div>
  </section>

  <!-- 活用例2:データ渡し -->
  <section class="p-section">
    <h3>2. 動的なデータ渡し(商品情報の取得)</h3>
    <p>ボタンをクリックすると、持っているデータを表示します。</p>
    <div class="p-btn-group">
      <!-- 💡 data-item-name と data-price で情報を持たせる -->
      <button class="c-btn js-item-btn" data-item-name="りんご" data-price="150">りんご</button>
      <button class="c-btn js-item-btn" data-item-name="みかん" data-price="300">みかん</button>
    </div>
    <div class="c-msg-box js-msg-box">商品を選択してください。</div>
  </section>
</div>

【CSS】

/* ベース装飾 */
.l-wrap {
  max-width: 800px;
  margin: 0 auto;
  padding: 40px 20px;
  color: #3e3e3e;
}
h2 {
  font-size: 16px;
  color: #1bb4d4;
  text-align: center;
  margin-bottom: 40px;
}
.p-section {
  background: #fff;
  padding: 30px;
  border-radius: 8px;
  margin-bottom: 40px;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.05);
}
h3 {
  font-size: 16px;
  border-bottom: 2px solid #eee;
  padding-bottom: 10px;
  margin-bottom: 20px;
}
p{
  font-size: 16px;
  margin-bottom: 20px;
}

/* 1. タブ切り替え用 */
.c-tab-list {
  display: flex;
  gap: 10px;
}
.c-tab-item {
  padding: 10px 30px;
  background: #eee;
  cursor: pointer;
  border-radius: 6px 6px 0 0;
  font-size: 16px;
  font-weight: bold;
}
.c-tab-item.is-active {
  background: #1bb4d4;
  color: #fff;
}
.c-tab-content {
  display: none;
  padding: 30px;
  background: #f9f9f9;
  border: 1px solid #ddd;
  font-size: 16px;
}
.c-tab-content.is-active {
  display: block;
}

/* 2. データ渡し用 */
.p-btn-group {
  display: flex;
  gap: 16px;
  margin-bottom: 20px;
}
.c-btn {
  padding: 10px 20px;
  background: #e83e8c;
  color: #fff;
  font-size: 16px;
  font-weight: bold;
  border-radius: 4px;
  cursor: pointer;
}
.c-msg-box {
  padding: 13px;
  background: #222;
  color: #0f0;
  font-family: monospace;
  font-size: 13px;
  border-radius: 4px;
}

【JavaScript】

/* =========================================
   1. タブ切り替え(data-target の活用)
========================================= */
const tabs = document.querySelectorAll('.js-tab');
const contents = document.querySelectorAll('.js-content');

tabs.forEach((tab) => {
  tab.addEventListener('click', (e) => {
    // 💡 datasetを使って、クリックされたタブの data-target の値を取得
    // HTML: data-target="tab-a" -> JS: dataset.target
    const targetId = e.currentTarget.dataset.target;

    // タブのアクティブ状態をリセット&付与
    tabs.forEach(t => t.classList.remove('is-active'));
    e.currentTarget.classList.add('is-active');

    // コンテンツの表示を切り替え
    contents.forEach(content => {
      content.classList.remove('is-active');
      // 取得した targetId と同じ ID を持つコンテンツだけ表示!
      if (content.id === targetId) {
        content.classList.add('is-active');
      }
    });
  });
});

/* =========================================
   2. 動的なデータ渡し(data-item-name, data-price の活用)
========================================= */
const itemBtns = document.querySelectorAll('.js-item-btn');
const msgBox = document.querySelector('.js-msg-box');

itemBtns.forEach((btn) => {
  btn.addEventListener('click', (e) => {
    // 💡 HTML側の data-item-name は、JS側では itemName になります!
    const name = e.currentTarget.dataset.itemName;
    const price = e.currentTarget.dataset.price;

    // 取得したデータを使ってメッセージを表示
    msgBox.textContent = `選択された商品: ${name} / 価格: ${price}円`;
  });
});

コード解説

今回のデモでは、取得した data 属性の値をそれぞれ次のように活用しています。

タブ切り替え(IDとの照合)

// 💡 datasetを使って、クリックされたタブの data-target の値を取得
// HTML: data-target="tab-a" -> JS: dataset.target
const targetId = e.currentTarget.dataset.target;

...

// コンテンツの表示を切り替え
contents.forEach(content => {
  content.classList.remove('is-active');
  // 取得した targetId と同じ ID を持つコンテンツだけ表示!
  if (content.id === targetId) {
    content.classList.add('is-active');
  }
});

e.currentTarget.dataset.target で、クリックされたタブに設定されている data-target の値(例:tab-a)を取得しています。 その後、すべてのコンテンツを順番にチェックし、「取得した値」と「コンテンツ自身の id」が一致するもの(content.id === targetId)だけに is-active クラスを付けて表示させています。タブ実装における王道のロジックです!

動的なデータ渡し(テンプレートリテラルでの展開)

// 💡 HTML側の data-item-name は、JS側では itemName になります!
const name = e.currentTarget.dataset.itemName;
const price = e.currentTarget.dataset.price;

// 取得したデータを使ってメッセージを表示
msgBox.textContent = `選択された商品: ${name} / 価格: ${price}円`;

dataset.itemName と dataset.price でボタンから取得したデータを、バッククォート(`)で囲んだ文字列の中に ${name} のように埋め込んで出力しています。 この仕組みを使えば、ECサイトの商品一覧からモーダルウィンドウを開く時など、「クリックした要素のデータを読み取って、別の場所に表示する」という処理がたった一つの関数で使い回せるようになります!

dataset と getAttribute の違いと使い分け

基本は dataset を使おう!

HTMLに <div data-sample-value="test"></div> と書かれている場合、どちらの方法でも値"test"を取得できます。

dataset プロパティを使う場合(推奨)

// HTML: data-sample-value
// JS  : キャメルケース(sampleValue)に変換される!
const value = element.dataset.sampleValue;

getAttribute() メソッドを使う場合

// HTMLの属性名をそのまま文字列で指定する
const value = element.getAttribute('data-sample-value');

短くて直感的に書ける dataset を使うのが主流です。

最大の注意点は、dataset を使う場合、HTML側でハイフン繋ぎ(ケバブケース)だった名前が、JS側ではキャメルケースに自動変換されるという点です!

getAttribute はいつ使うの?

基本は dataset でOKですが、以下のような少し特殊なケースでは getAttribute 系が役立ちます。

  • element.removeAttribute('data-sample-value') のように、属性そのものをHTMLから完全に削除したい時。
  • CSSのセレクタとしてそのまま文字列で扱いたい時など。

補足:公式ドキュメント

より詳しい仕様や最新の対応状況については、以下の公式ドキュメントをご参照ください。

・MDN: dataset プロパティ
・MDN: getAttribute() メソッド

まとめ

今回は data 属性の取得方法の違いと、活用例をご紹介しました。

JavaScriptでHTMLの要素を操作する際、要素自身に必要なデータを持たせておくことで、コードがとてもシンプルで管理しやすくなります。基本的にはキャメルケースで短く書ける dataset を使いこなしつつ、状況に合わせて上手く使い分けていきましょう!

Prev
Next