カスタムデータ属性とは
HTML5で定義されたカスタムデータ属性、当然皆さんご存知のことかと思います。
HTMLにプライベートな値を設定できるという仕様です。
data-
から始まる属性です。 このように書きます。
<div class="hoge" data-type='fuga'>🐳</div>
この値は、次のようにしてjavascriptやcssから触ることができます。
// data-typeを持つ要素を取得
var elem = document.querySelector("[data-type]");
// data-typeの中身を取得する
console.log(elem.dataset.type); // fuga
// data-typeを変更する
elem.dataset.type = 'piyo'; // <div data-type='piyo' />に
// data-typeの文字サイズを大きく
.hoge {
&[data-type] {
font-size: 2em; // data-typeを持つ要素の文字サイズを大きく
}
// data-typeがpiyoなら末尾にヒヨコを追加
&[data-type='piyo']::after {
content:"🐤";
}
}
細かい仕様や利用可能なブラウザーは他の記事を参考にしていただくとして、
この指定方法とても便利だと思いませんか?
カスタムデータ属性を使った書き換え
例えば次のようなコードがあったとします。
<div class="block is-hide"> ... </div>
.block {
display:block;
&.is-hide {
display:none;
}
}
これをデータ属性付きの方法で書き換えると次のようになります。
<div class="block" data-is-hide="true"> ... </div>
.block {
display:block;
&[data-is-hide="true"] {
display:none;
}
}
data属性に書き換えるだけなので変更も容易です。
さらに特に意識しなくてもCSSの名前が衝突することがなくなりますし、classが短くて済みます。
class名の操作をしなくていいので、javascriptで操作する場合も手軽になります。
const BlockElement = document.querySelector(".block");
let isHide = false;
button.addEventListener("click", () => {
BlockElement.dataset.isHide = isHide = !isHide;
},false);
Reactと組み合わせても便利
Reactのjsxは、基本的にはsrcなどの予約された属性以外のものを利用することができませんが、data属性なら自由に指定することができます。
次のように書けるので、jsxでstyleを直接当てることなく見た目を変更することも可能です。
<div className="block" data-is-hide={this.state.isHide}>
...
</div>
わざわざ条件分岐とかつけなくてもいいわけです
// こんなことしなくてもいい
<div className=`block ${this.state.isHide ? 'is-hide': ''}`>
...
</div>
data属性がcssで操作できるということは・・・?
こんなこともできると思います。
<div class="block" data-weather="cloudy"></div> // ☁︎
<div class="block" data-weather="sunny"></div> // ☀️
<div class="block" data-weather="rainy"></div> // ☂
<div class="block" data-weather="cloudy-sunny"></div> // ☁︎☀️
<div class="block" data-weather="sunny-cloudy"></div> // ☀️☁︎
<div class="block" data-weather="sunny-rainy"></div> // ☀️☂
<div class="block" data-weather="rainy-cloudy"></div> // ☂☁︎
.block {
$wathers : (
'cloudy':'☁️',
'sunny' : '☀️',
'rainy' : '☂'
);
@each $before, $before_icon in $wathers {
&[data-weather="#{$before}"]::before {
content: $before_icon;
}
}
@each $before, $before_icon in $wathers {
@each $after, $after_icon in $wathers {
&[data-weather="#{$before}-#{$after}"]::after {
content: $before_icon + $after_icon;
}
}
}
}
これだけ複雑なことをしても、一切classは汚れません。
グリッドシステムも簡単に(?)
12分割のグリッドシステムもdata属性を使えばより簡単に指定することができます。
<div class="row">
<div class="row__col" data-column="1/3">1/3</div>
<div class="row__col" data-column="1/3">1/3</div>
<div class="row__col" data-column="1/3">1/3</div>
</div>
<div class="row">
<div class="row__col" data-column="2/8">2/8</div>
<div class="row__col" data-column="9/12">9/12</div>
</div>
.row {
$min-columns : 1;
$max-columns : 12;
width: 100%;
display:flex;
&__col {
margin: auto;
@for $max_columns from $min-columns through $max-columns {
@for $i from 1 through $max_columns {
&[data-column="#{$i}/#{$max_columns}"] {
@if $i != $max_columns {
width: ($i / $max_columns * 100%);
}
}
}
}
}
}
最後に
というわけで状態の指定にカスタムデータ属性を使うともう少し幸せになるのではないかという提言です。