data- lets you attach small ‘notes’ to an element, so CSS and JavaScript can read them to change styles or behavior.
タグに“自分だけのメモ”をくっつけて、CSSの見た目切り替えやJavaScriptの動きにそのまま使えるようにする仕組みが、data-属性です。
data属性は HTMLのタグに設定できる属性の一つです。属性とは要素に設定を付与することができるものです。属性は dataの他にも idや style、classなどがあります。
data属性はカスタムデータ属性とも呼ばれていて、独自の属性を設定することができます。
data- の後ろ(名前の部分)は、基本は 小文字+ハイフン で付けるのがおすすめです(例:data-user-id)。大文字や :、xml で始まる名前は避けると安全です。
HTML
<div data-○○="data">テキスト</div>
CSS
セレクタ[data-○○="data"] {
プロパティ: 値;
}
data-○○ の○○の部分を自由に設定することができます。
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で設定したものと同じ名称を指定してください。
data-boxに値を設定しなくても、[data-box]の形式でスタイルの設定ができます。
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;
}
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%);
}
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-* は「この要素は今どんな状態?」を持たせるのが得意です。
たとえば data-state="open" / data-state="closed" みたいにすると、
CSSは見た目を切り替えやすく、JavaScriptは状態を更新しやすくなります。
ここが中身です。data-state が open のときだけ表示します。
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-* は「状態」だけじゃなく、「何をするボタン?」みたいな“命令メモ”にも使えます。
ここでは data-action と data-target を使って、クリック処理を1つにまとめます。
パネルAです。ボタンが増えても、JSは増やしません。
パネルBです。data-target を変えるだけで使い回せます。
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を増やさずに運用できます。
class、ページ内で一意に識別したいなら id が基本です。data-* は「表示とは別の情報」を持たせたいときに向いています。[data-state="open"])として使えます。ただし“見た目目的だけ”なら class の方が一般的な場合も多いです。dataset で読むときのルールは?data-sub は dataset.sub、data-user-id は dataset.userId のように、ハイフン区切りがキャメルケースに変換されます。dataset で取れる値は基本的に文字列です。数として使うなら Number(el.dataset.count) みたいに変換してから使います。”(全角のダブルクォート)"(半角)に直すと動くことが多いです。dataset が undefined っぽいgetElementById のIDが間違っている、または要素がまだ存在しないタイミングで読んでいる可能性があります。data-user-id を dataset["user-id"] で読めないdataset.userId のようにキャメルケースで読みます(ハイフンは変換されます)。[data-box] が効かないattr(data-...) が出ないcontent: に書いているか、疑似要素(::before / ::after)側に書いているかを確認します。