Edited at

CSS設計の類はもっとカスタムデータ属性を活用するべきでは

More than 3 years have passed since last update.


カスタムデータ属性とは

HTML5で定義されたカスタムデータ属性、当然皆さんご存知のことかと思います。

HTMLにプライベートな値を設定できるという仕様です。

data-から始まる属性です。 このように書きます。


html

<div class="hoge" data-type='fuga'>🐳</div>


この値は、次のようにしてjavascriptやcssから触ることができます。


js

// 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' />に



scss

// data-typeの文字サイズを大きく

.hoge {
&[data-type] {
font-size: 2em; // data-typeを持つ要素の文字サイズを大きく
}
// data-typeがpiyoなら末尾にヒヨコを追加
&[data-type='piyo']::after {
content:"🐤";
}
}

細かい仕様や利用可能なブラウザーは他の記事を参考にしていただくとして、

この指定方法とても便利だと思いませんか?


カスタムデータ属性を使った書き換え

例えば次のようなコードがあったとします。


html

<div class="block is-hide"> ... </div>



scss

.block {

display:block;
&.is-hide {
display:none;
}
}

これをデータ属性付きの方法で書き換えると次のようになります。


html

<div class="block" data-is-hide="true"> ... </div>



scss

.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で操作できるということは・・・?

こんなこともできると思います。


html


<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> // ☂☁︎


scss

.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属性を使えばより簡単に指定することができます。


html

<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>



scss

.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%);
}
}
}
}
}
}


最後に

というわけで状態の指定にカスタムデータ属性を使うともう少し幸せになるのではないかという提言です。