300
288

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-03-04

カスタムデータ属性とは

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

最後に

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

300
288
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
300
288

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?