HTML

data- lets you attach small ‘notes’ to an element, so CSS and JavaScript can read them to change styles or behavior.

data-*属性

タグに“自分だけのメモ”をくっつけて、CSSの見た目切り替えやJavaScriptの動きにそのまま使えるようにする仕組みが、data-属性です。

data-*属性とは?

data属性は HTMLのタグに設定できる属性の一つです。属性とは要素に設定を付与することができるものです。属性は dataの他にも idstyleclassなどがあります。

data属性はカスタムデータ属性とも呼ばれていて、独自の属性を設定することができます。

data- の後ろ(名前の部分)は、基本は 小文字+ハイフン で付けるのがおすすめです(例:data-user-id)。大文字:xml で始まる名前は避けると安全です。

基本書式

HTML

<div data-○○="data">テキスト</div>

CSS

セレクタ[data-○○="data"] {
	プロパティ: 値;
}

data-○○ の○○の部分を自由に設定することができます。

Sample 1

HTML

<div data-box="box-orange" class="box"></div>
<div data-color="box-red" class="box"></div>

CSS

.box {
	width: 200px;
	height: 150px;
}

.box[data-box="box-orange"] {
	background-color: orange;
}

.box[data-color="box-red"] {
	background-color: red;
}

data-*属性を「条件」にして、その要素にスタイルを当てたい場合は、要素[data-○○××="○○××"] の形式で指定します。data-の後ろの部分は、HTMLで設定したものと同じ名称を指定してください。

Sample 2

data-boxに値を設定しなくても、[data-box]の形式でスタイルの設定ができます。

box1
box2

HTML

<div data-box="box-orange" class="box">box1</div>
<div data-box class="box">box2</div>

CSS

.box {
	width: 200px;
	height: 150px;
}

.box[data-box] {
	background-color: orange;
}

Sample 3

data属性を使うと、例えば次のように data属性で設定したものを疑似要素でブラウザに表示することができます。

メインタイトル

HTML

<h2 data-sub="サブタイトル">メインタイトル</h2>

CSS

h2 {
	position: relative;
	display: inline-block;
}

h2:before {
	position: absolute;
	content: attr(data-sub);
	top: -8px;
	left: 50%;
	font-size: 10px;
	transform: translateX(-50%);
}

Sample 4

data属性は JavaScriptと組み合わせて使うことが多いです。

次のコードは、JavaScriptで data属性にセットした値を変更する処理をする場合です。

メインタイトル

HTML

<h2 id="test" data-sub="サブタイトル">メインタイトル</h2>
<script>
	const el = document.getElementById('test');
	el.dataset.sub='サブタイトル変更';
</script>

CSS

h2 {
	position: relative;
	display: inline-block;
}

h2:before {
	position: absolute;
	content: attr(data-sub);
	top: -8px;
	left: 50%;
	font-size: 10px;
	transform: translateX(-50%);
}

要素に設定した idを、変数el で取得しています。datasetで data属性を更新することができます。datasetのあとの subは、data属性で設定した data-subの部分(data-の後ろの部分)を指定します。

このようにすると、JavaScriptで data属性を取得して中身を変更することができます。

data-stateで「開く/閉じる」を作る

data-* は「この要素は今どんな状態?」を持たせるのが得意です。 たとえば data-state="open" / data-state="closed" みたいにすると、 CSSは見た目を切り替えやすく、JavaScriptは状態を更新しやすくなります。

HTML

<button type="button" id="toggleBtn" aria-controls="panel" aria-expanded="false" data-state="closed">
	詳細を開く
</button>

<div id="panel" data-state="closed" hidden>
	<p>ここが中身です。<code>data-state</code> が <code>open</code> のときだけ表示します。</p>
</div>

JavaScript

const btn = document.getElementById('toggleBtn');
const panel = document.getElementById('panel');

btn.addEventListener('click', () => {
	const isOpen = panel.dataset.state === 'open';

	panel.dataset.state = isOpen ? 'closed' : 'open';
	btn.dataset.state = panel.dataset.state;

	panel.hidden = isOpen;
	btn.setAttribute('aria-expanded', String(!isOpen));
	btn.textContent = isOpen ? '詳細を開く' : '詳細を閉じる';
});

CSS

/* ボタンの見た目を状態で切り替え */
button[data-state="open"] {
    font-weight: bold;
}

/* パネルはhiddenで出し分けるけど、状態も見えるように例として書いておく */
#panel[data-state="open"] {
    display: block;
}

大事: data-* はHTMLに書かれているので、ブラウザで見れば誰でも読めます。 パスワードやトークンみたいな「見られたら困る情報」は入れないのがおすすめです。

data-actionで“ボタンが増えてもJSは1つ”にする

data-* は「状態」だけじゃなく、「何をするボタン?」みたいな“命令メモ”にも使えます。 ここでは data-actiondata-target を使って、クリック処理を1つにまとめます。

HTML

<div id="actionDemo">
	<button type="button" data-action="toggle" data-target="#panelA" aria-controls="panelA" aria-expanded="false">
		Aを開く
	</button>

	<button type="button" data-action="toggle" data-target="#panelB" aria-controls="panelB" aria-expanded="false">
		Bを開く
	</button>

	<div id="panelA" hidden data-state="closed">
		<p>パネルAです。ボタンが増えても、JSは増やしません。</p>
	</div>

	<div id="panelB" hidden data-state="closed">
		<p>パネルBです。<code>data-target</code> を変えるだけで使い回せます。</p>
	</div>

	<script>
		<!-- JavaScript code here -->
	</script>
</div>

JavaScript

const root = document.getElementById('actionDemo');

root.addEventListener('click', (e) => {
	const btn = e.target.closest('button[data-action]');
	if (!btn) return;

	const action = btn.dataset.action;
	const targetSelector = btn.dataset.target;

	if (action !== 'toggle' || !targetSelector) return;

	const panel = root.querySelector(targetSelector);
	if (!panel) return;

	const isOpen = !panel.hidden;

	panel.hidden = isOpen;
	panel.dataset.state = isOpen ? 'closed' : 'open';

	btn.setAttribute('aria-expanded', String(!isOpen));
	btn.textContent = isOpen ? btn.textContent.replace('閉じる', '開く') : btn.textContent.replace('開く', '閉じる');
});

ポイント: ボタンごとにイベントを付けるのではなく、親(ここでは #actionDemo)に1つだけ付けています。 だからボタンが増えても、JSを増やさずに運用できます。

よくある質問(FAQ)

data-*属性って、何のために使うの?
「この要素は何者か」「IDは何か」みたいな“自分用メモ”をHTMLに持たせたいときに使います。見た目(CSS)と動き(JavaScript)の“橋渡し”にも便利です。
classやidで代用できない?
見た目の指定なら class、ページ内で一意に識別したいなら id が基本です。data-* は「表示とは別の情報」を持たせたいときに向いています。
CSSだけで使ってもいい?
OKです。属性セレクタ(例:[data-state="open"])として使えます。ただし“見た目目的だけ”なら class の方が一般的な場合も多いです。
JavaScriptの dataset で読むときのルールは?
data-subdataset.subdata-user-iddataset.userId のように、ハイフン区切りがキャメルケースに変換されます。
値は数値として扱える?
dataset で取れる値は基本的に文字列です。数として使うなら Number(el.dataset.count) みたいに変換してから使います。

よくあるエラー早見表

コピペしたのに動かない:(全角のダブルクォート)
"(半角)に直すと動くことが多いです。
datasetundefined っぽい
getElementById のIDが間違っている、または要素がまだ存在しないタイミングで読んでいる可能性があります。
data-user-iddataset["user-id"] で読めない
dataset.userId のようにキャメルケースで読みます(ハイフンは変換されます)。
CSSの [data-box] が効かない
HTML側にその属性が本当に付いているか、スペルが一致しているかを確認します。
attr(data-...) が出ない
content: に書いているか、疑似要素(::before / ::after)側に書いているかを確認します。