1. ホーム
  2. JavaScript

【JavaScript】dataset で data属性を読み書きする方法|HTMLとJSの値の受け渡し

Share

HTML 側に書いた値を JavaScript で受け取りたい、あるいは要素ごとに状態や ID を持たせて処理を分けたい。そんなときに活躍するのが data-* 属性と、それを読み書きするための dataset プロパティです。data-* 属性は HTML の正式な仕様で、好きな名前のカスタムデータを要素に持たせられます。この記事では、data-* 属性の書き方と dataset を使った読み書きの方法、属性名の変換ルール、値が必ず文字列になる点まで、コーディング初心者〜中級者の方に向けて MDN の仕様に沿って解説します。

data-* 属性と dataset とは何か

data-* 属性は、HTML 要素に独自のデータを埋め込むためのグローバル属性です。data- で始まる名前を付ければ、data-user-iddata-state のように自由な名前で値を持たせられます。クラスや id のように見た目や識別のためではなく、「この要素に紐づく追加情報」を保持しておく目的で使います。

この data-* 属性に JavaScript からアクセスする入口が dataset です。datasetHTMLElement が持つ読み取り専用プロパティで、その要素に付いたすべての data-* 属性を DOMStringMap というオブジェクトとしてまとめて返します。element.dataset.userId のようにプロパティ経由で値を読み書きでき、専用のメソッドを呼ばずに属性を扱えるのが特徴です。

HTML に data-* 属性を書く

まずは HTML 側の書き方です。属性名は data- に続けて任意の名前を付けます。名前には英小文字・数字・ハイフンなどが使え、値はダブルクォートで囲んだ文字列で指定します。複数の data-* 属性を1つの要素に付けても構いません。

index.html
<button
  id="btn"
  data-user-id="42"
  data-user-name="Taro"
  data-role="admin">
  会員情報を表示
</button>

この例では、ボタン1つに会員の ID・名前・権限という3つの情報を data-* 属性として持たせています。これらの値を JavaScript から取り出すのが、次に紹介する dataset です。

dataset で値を読み取る

読み取りは element.dataset.プロパティ名 の形で行います。先ほどのボタンであれば、btn.dataset.userIddata-user-id の値を取得できます。下のデモでは、ボタンをクリックすると dataset から3つの値を読み取り、その内容を画面に表示します。コードを書き換えながら動きを確かめてみてください。

<div class="demo">
  <p class="result" id="result">ボタンを押すと、data-* 属性の値を読み取って表示します。</p>
  <button
    id="btn"
    data-user-id="42"
    data-user-name="Taro"
    data-role="admin">
    この会員の情報を表示
  </button>
</div>
.demo {
  font-family: sans-serif;
  padding: 8px;
}

.result {
  margin: 0 0 16px;
  padding: 12px;
  background: #f1f3f5;
  border-radius: 8px;
  min-height: 1.5em;
}

button {
  padding: 10px 18px;
  border: none;
  border-radius: 8px;
  background: #007bff;
  color: #fff;
  font-size: 15px;
  cursor: pointer;
}

button:hover {
  background: #0069d9;
}
const btn = document.getElementById("btn");
const result = document.getElementById("result");

btn.addEventListener("click", () => {
  // data-user-id   -> dataset.userId
  // data-user-name -> dataset.userName
  // data-role      -> dataset.role
  const id = btn.dataset.userId;
  const name = btn.dataset.userName;
  const role = btn.dataset.role;

  result.textContent =
    "ID: " + id + " / 名前: " + name + " / 権限: " + role;
});
Preview

このように、要素自身がデータを持っているので、クリックされた要素から直接情報を取り出せます。クリックイベントの中で event.currentTarget.dataset を参照すれば、同じ処理を多数の要素で共有しつつ、それぞれに固有の値を扱う、といった設計もしやすくなります。

属性名のケバブケースは dataset でキャメルケースになる

dataset を使ううえで最初につまずきやすいのが、属性名の表記の違いです。HTML の data-* 属性はハイフン区切り(ケバブケース)で書きますが、dataset でアクセスするときはキャメルケースに変換した名前を使います。具体的には、data- の接頭辞を取り除き、ハイフンに続く文字を大文字にした名前になります。data-user-id なら dataset.userIddata-role ならハイフンがないのでそのまま dataset.role です。

主な対応関係を表にまとめると、次のようになります。HTML 側はすべて小文字+ハイフン、JavaScript 側はキャメルケース、という対応を押さえておけば迷いません。

HTML の属性名dataset でのアクセス名
data-iddataset.id
data-user-iddataset.userId
data-user-namedataset.userName
data-roledataset.role
data-is-activedataset.isActive

逆方向も同じルールです。dataset.userName = "Hanako" のようにキャメルケースのプロパティへ書き込むと、HTML 側では data-user-name という属性として反映されます。JavaScript ではハイフンを含むプロパティ名がそのままでは書けないため、この変換が用意されている、と理解しておくと自然です。

dataset で値を書き込んで状態を切り替える

dataset は読み取りだけでなく書き込みもできます。element.dataset.state = "open" のように代入すると、対応する data-state 属性が要素に追加・更新されます。この性質を使うと、要素に「現在の状態」を data-* 属性として持たせ、JavaScript で書き換えながら CSS の属性セレクタ([data-state="open"] など)で見た目を切り替える、という連携ができます。

下のデモは、パネルの開閉状態を data-state 属性で管理する例です。ボタンを押すたびに dataset.state の値を openclosed で反転させ、その値に応じて CSS が中身の表示・非表示を切り替えています。状態を JavaScript の変数ではなく DOM 自体に持たせている点に注目してください。

<div class="panel" id="panel" data-state="closed">
  <button id="toggle">開閉する</button>
  <p class="status" id="status">現在の状態: closed</p>
  <div class="body">
    <p>data-state 属性に状態を持たせ、JS で書き換えています。</p>
    <p>属性の値は CSS のセレクタからも参照できます。</p>
  </div>
</div>
.panel {
  font-family: sans-serif;
  max-width: 360px;
  padding: 16px;
  border: 1px solid #ddd;
  border-radius: 8px;
}

button {
  padding: 8px 16px;
  border: none;
  border-radius: 6px;
  background: #007bff;
  color: #fff;
  cursor: pointer;
}

.status {
  margin: 12px 0;
  color: #555;
}

/* data-state の値に応じて表示を切り替える */
.panel[data-state="closed"] .body {
  display: none;
}

.panel[data-state="open"] .body {
  display: block;
  padding: 12px;
  background: #e3f2fd;
  border-radius: 6px;
}
const panel = document.getElementById("panel");
const toggle = document.getElementById("toggle");
const status = document.getElementById("status");

toggle.addEventListener("click", () => {
  // 現在の状態を dataset から読む(data-state -> dataset.state)
  const current = panel.dataset.state;

  // 状態を反転して書き込む。これで data-state 属性自体が書き換わる
  const next = current === "open" ? "closed" : "open";
  panel.dataset.state = next;

  status.textContent = "現在の状態: " + next;
});
Preview

属性を削除したいときは、delete element.dataset.state のように delete 演算子を使います。これで対応する data-state 属性が要素から取り除かれます。状態を「無し」に戻したい場面で使うと便利です。

dataset の値は必ず文字列になる

dataset を使ううえで必ず覚えておきたいのが、取得できる値は常に文字列だという点です。HTML の属性値はもともと文字列なので、data-user-id="42"dataset.userId で読んでも、得られるのは数値の 42 ではなく文字列の "42" です。同じく data-is-active="true" を読んでも、真偽値の true ではなく文字列の "true" が返ります。

そのため、数値として計算したいときは Number(btn.dataset.userId)parseInt(btn.dataset.userId, 10) のように明示的に変換します。真偽値として扱いたいときも、btn.dataset.isActive === "true" のように文字列との比較で判定するのが安全です。書き込むときも同様で、dataset.count = 3 のように数値を代入しても、内部では文字列 "3" に変換されて属性に保存されます。

script.js
// data-user-id="42" を読むと文字列 "42"
const raw = btn.dataset.userId;
console.log(typeof raw); // "string"

// 数値として使うときは変換する
const id = Number(btn.dataset.userId);
console.log(id + 1); // 43

// 真偽値は文字列との比較で判定する
const active = btn.dataset.isActive === "true";

getAttribute・setAttribute との関係

data-* 属性は通常の属性でもあるため、dataset を使わずに getAttribute()setAttribute() で読み書きすることもできます。たとえば btn.getAttribute("data-user-id")btn.dataset.userId は同じ値を返し、btn.setAttribute("data-user-id", "99")btn.dataset.userId = "99" は同じ結果になります。どちらも同じ属性を操作しているだけなので、片方で書き換えればもう片方からも変更後の値が読めます。

大きな違いは名前の指定方法です。getAttribute() 系では "data-user-id" のように data- を含むケバブケースの完全な属性名を文字列で渡します。一方 dataset では data- を除いたキャメルケースのプロパティ名でアクセスします。data-* 属性を専門に扱うなら、変換ルールさえ押さえれば dataset の方が短く書けて読みやすいです。属性名を動的に組み立てたい、あるいは data-* 以外の属性も同じコードで扱いたい、といった場合は getAttribute() 系が向いています。

まとめ

data-* 属性は HTML 要素に独自データを持たせるための仕組みで、JavaScript からは HTMLElement.dataset を通じて読み書きできます。HTML 側のケバブケース(data-user-id)は、dataset ではキャメルケース(dataset.userId)になる、という変換ルールがポイントです。読み取りも代入も dataset.プロパティ名 の形で書け、delete で属性を削除できます。取得できる値は常に文字列なので、数値や真偽値として使うときは Number() や文字列比較で変換しましょう。getAttribute()setAttribute() と同じ属性を扱っているため、状況に応じて使い分けると、HTML と JavaScript の値の受け渡しをすっきり書けます。

参考ページ