html5のdata属性をcss/scss/jsで利用する

data属性のcss/jsでの読み込みとscssとの連携

以前から知ってはいたけどいまいち有効な利用方法が分からなかったdata属性。
使わなくてもwebサイトは作ることができるので、必要性を感じずこれまで使わずにいましたが、調べてみると結構色々とできるようなのでサンプルをまとめてみました。

SAMPLE(削除されました)

1.attr()を使ったcssでの値の読み込み

タグに付与したdata属性値はcssのattr({data名})で読み込めます。

現状疑似要素のcontent内でしか使えないようですが、拡張されてcolorやurlなどでも使えるようになると用途が増えそうですね。

ホバー時の色変化

HTML

<div class="slide" data-slide="WEB SITE">
	WEB SITE
</div>

CSS

.slide {
  position: relative;
  left: 50%;
  display: inline-block;
  width: auto;
  height: auto;
  font-size: 20px;
  -webkit-transform: translate(-50%);
  -moz-transform: translate(-50%);
  -ms-transform: translate(-50%);
  -o-transform: translate(-50%);
  transform: translate(-50%); }
  .slide::before {
    position: absolute;
    top: 0;
    left: 0;
    content: attr(data-slide);
    width: 0;
    height: 100%;
    color: #f00;
    transition: 0.5s;
    overflow: hidden; }
  .slide:hover::before {
    width: 100%; }

疑似要素に色違いの文字を配置して、時間経過で色付き文字をスライド表示させるサンプルです。

日本語と英語のメニュー

HTML

<ul class="menu">
	<li class="menu_item" data-name="会社概要">ABOUT</li>
	<li class="menu_item" data-name="サービス">SERVICE</li>
	<li class="menu_item" data-name="新着情報">NEWS</li>
	<li class="menu_item" data-name="ブログ">BLOG</li>
	<li class="menu_item" data-name="アクセス">ACCESS</li>
</ul>

CSS

.menu {
  display: flex;
  margin: 0 auto 50px;
  width: 800px; }
  .menu_item {
    flex: 1;
    padding: 12px 0 0 0;
    height: 50px;
    font-size: 16px;
    line-height: 1;
    text-align: center;
    border-width: 0 0 0 1px;
    border-style: solid;
    border-color: #ccc; }
    .menu_item:last-child {
      border-width: 0 1px; }
    .menu_item::after {
      display: block;
      margin-top: 2px;
      content: attr(data-name);
      font-size: 12px;
      line-height: 1;
      color: #ccc; }

通常2段組にタグを書かなければならないところを、data属性を擬似要素から出力することで一行のタグで2段組のメニューが作れます。

これらのサンプルは下記サイトを参考にさせていただきました。


data属性を利用したナビゲーションの実装サンプル

2.SCSSと連携した記述

SCSSを使いだしてすっかりBEMベースの命名規則に慣れてしまって、マルチクラスなどで肥大化する一方のclass。
一つのフォーマットでいくつかのカテゴリや状態などのバリエーションへの対応をdata属性に振り分けたほうがソースの可読性が良くなります。
BEMで言うところのmodifierをdata属性に置き換える感じです。

カテゴリの色分け

HTML

<ul class="newsWrap">
	<li data-cat="new">
		<div class="cat">新着情報</div>
		<p class="title">吾輩はここで始めて人間というものを見た。</p>
	</li>
	<li data-cat="photo">
		<div class="cat">写真</div>
		<p class="title">何でも薄暗いじめじめした所でニャーニャー泣いていた</p>
	</li>
	<li data-cat="blog">
		<div class="cat">ブログ</div>
		<p class="title">どこで生れたかとんと見当がつかぬ。</p>
	</li>
	<li data-cat="info">
		<div class="cat">お知らせ</div>
		<p class="title">吾輩は猫である。名前はまだない。</p>
	</li>
	<li data-cat="other">
		<div class="cat">未分類</div>
		<p class="title">Hello world!</p>
	</li>
</ul>

SCSS(complass)

$newsColor:(
	new:#db2929,
	photo:#235daf,
	blog:#f79d16,
	info:#269963
);

@mixin color{
	@each $cat,$color in $newsColor{
		li[data-cat="#{$cat}"] &{
			background: $color;
		}
	}
}

ul.newsWrap{
	margin: 0 auto 50px;
	padding: 0;
	width: 1000px;
	height: auto;
	border-width: 1px 0;
	border-style: solid;
	border-color: #aaa;
}

ul.newsWrap>li{
	padding: 0 0 0 5px;
	border-width: 0 0 1px 0;
	border-style: dashed;
	border-color: #eee;
	list-style-type: none;
	@include clearfix;

	&:last-child{
		border-width: 0;
	}
}

.cat{
	float: left;
	margin: 10px 10px 10px 0;
	padding: 0 10px;
	width: 100px;
	height: 20px;
	font-size: 12px;
	line-height: 20px;
	text-align: center;
	color: #fff;
	border-radius: 3px;
	background: #666;
	@include color;
}
.title{
	padding: 0 0 0 10px;
	height: 40px;
	font-size: 16px;
	line-height: 40px;
	color: #888;
}

よくある更新情報に付くタグをカテゴリ別色に分け。
SCSSの連想配列を組んでkeyにカテゴリ名(スラッグ)、valueに色を記述して@eachで回しています。
「カテゴリ名:色」の配列で管理するので変更もカンタンですね。

タグ内の文字列も配列にしようと思ったのですが、よく考えたらwordpressのカテゴリ情報から引っ張るほうが楽だし利便性も良いですよね。
ちなみにデフォの色を該当セレクタに指定しておかないと、指定していないカテゴリが真っ白になってしまうので注意。

カテゴリ別にアイコンをつける

次は色付きタグではなく、タイトルの前にアイコンを付けます。

HTML

<ul class="newsWrap">
	<li data-cat="new">
		<p class="title2">吾輩はここで始めて人間というものを見た。</p>
	</li>
	<li data-cat="photo">
		<p class="title2">何でも薄暗いじめじめした所でニャーニャー泣いていた</p>
	</li>
	<li data-cat="blog">
		<p class="title2">どこで生れたかとんと見当がつかぬ。</p>
	</li>
	<li data-cat="info">
		<p class="title2">吾輩は猫である。名前はまだない。</p>
	</li>
	<li data-cat="other">
		<p class="title2">Hello world!</p>
	</li>
</ul>

SCSS(compass)

$newsicon:(
	new:'\f02b',
	photo:'\f03e',
	blog:'\f27b',
	info:'\f15c',
);

@mixin icon{
	@each $cat,$icon in $newsicon{
		li[data-cat="#{$cat}"] &::before{
			content: $icon;
		}
	}
}

ul.newsWrap{
	margin: 0 auto 50px;
	padding: 0;
	width: 1000px;
	height: auto;
	border-width: 1px 0;
	border-style: solid;
	border-color: #aaa;
}

ul.newsWrap>li{
	padding: 0 0 0 5px;
	border-width: 0 0 1px 0;
	border-style: dashed;
	border-color: #eee;
	list-style-type: none;
	@include clearfix;

	&:last-child{
		border-width: 0;
	}
}

.title2{
	padding: 0 0 0 10px;
	height: 40px;
	font-size: 16px;
	line-height: 40px;
	color: #888;
	@include icon;
	&::before{
		content: '\f040';
		font-family: FontAwesome;
		letter-spacing: 10px;
	}
}

こちらも色付きタグと同様に連想配列にFont Awesomeのユニコードを記述します。
それを上と同じ要領で@eachで回して疑似要素::beforeのcontentにあてるだけ。

注意すべきはユニコードの前に「\(バックスラッシュ)」をつけることと、疑似要素内に「font-family: FontAwesome;」を入れないと表示されない点です。

ポストイット風(?)記事一覧の色分け

少し発展させて、今度はブロックごと色を変えてみます。

HTML

<div class="wrap">
	<div class="item" data-cat="new">
		<div class="tag">
			新着情報
		</div>
		<div class="text">
			<h2>吾輩は猫である。名前はまだ無い。</h2>
			<p>
				テキスト
			</p>
			<div class="button">詳しく見る</div>
		</div>
	</div>
	<div class="item" data-cat="photo">
		<div class="tag">
			写真
		</div>
		<div class="text">
			<h2>吾輩は猫である。名前はまだ無い。</h2>
			<p>
				テキスト
			</p>
			<div class="button">詳しく見る</div>
		</div>
	</div>
	<div class="item" data-cat="blog">
		<div class="tag">
			ブログ
		</div>
		<div class="text">
			<h2>吾輩は猫である。名前はまだ無い。</h2>
			<p>
				テキスト
			</p>
			<div class="button">詳しく見る</div>
		</div>
	</div>
	<div class="item" data-cat="info">
		<div class="tag">
			お知らせ
		</div>
		<div class="text">
			<h2>吾輩は猫である。名前はまだ無い。</h2>
			<p>
				テキスト
			</p>
			<div class="button">詳しく見る</div>
		</div>
	</div>
</div>

SCSS(compass)

@mixin box{
	@each $cat,$color in $newsColor{
		&[data-cat="#{$cat}"]{
			background: lighten($color,42%);
			&::before{
				border-color: darken($color,20%) transparent transparent transparent;
			}
			& .tag,& .button{
				background: $color;
			}
			& h2,& p{
				color: $color;
			}
		}
	}
}

.wrap{
	display:flex;
	justify-content:space-between;
	flex-wrap: wrap;
	margin: 0 auto;
	width: 1000px;
	//background: #eee;
}
.item{
	position: relative;
	margin: 0 0 20px;
	width: calc(50% - 10px);
	height: 400px;
	background: #ccc;
	@include box;
	&::before{
		position: absolute;
		top: 48px;
		left: -10px;
		content: '';
		width: 0;
		height: 0;
		border-width: 10px 0 0 10px;
		border-style: solid;
		border-color: #000 transparent transparent transparent;
	}
}
.tag{
	position: absolute;
	top: 12px;
	left: -10px;
	z-index: 2;
	padding: 0 15px;
	min-width: 200px;
	height: 36px;
	background: #666;
	font-size: 16px;
	color: #fff;
	line-height: 36px;
	letter-spacing: 0.1em;
}
.text{
	display: flex;
	flex-direction:column;
	padding: 70px 24px 24px;
	width: 100%;
	height: 100%;
}
.text h2{
	margin: 0 0 12px;
	font-size: 22px;
	font-weight: bold;
	letter-spacing: 0.05em;
}
.text p{
	font-size: 16px;
	line-height: 140%;
}
.button{
	align-self:flex-end;
	margin-top: auto;
	width: 150px;
	height: 36px;
	font-size: 16px;
	line-height: 36px;
	text-align: center;
	color: #fff;
	border-radius: 5px;
	background: #333;
}

とは言ってもやってることはほぼ同じ。
ターゲットになるブロックの親セレクタにdata属性を付与して、該当のdata属性を持つ子要素に対して色をつけています。
&(アンパサンド)を使えば親要素から子要素の指定はもちろん、子要素を軸に親要素の属性判定もできます。

難点を言えば子要素を軸にした場合、親要素のセレクタは固定になってしまうことでしょうか。
javascriptみたいに親要素のセレクタを呼び出せるともっと楽なんですけどね。

3.jqueryで値を取得する

最後はjqueryでdata属性の値を取得する方法です。
jqueryでは値を取得するメソッドがdataとattrと2つ存在します。

それぞれ仕様が違い、またjquery側で属性の消去する方法などやや煩雑なります。
そのあたりは下記サイトで詳しく説明されていますので参照してください。


HTML5 カスタムデータ属性「data-*」にJavaScript、jQueryからアクセスする方法

簡易ライトボックス

jqueryを使ったライトボックスです。

HTML

<div class="modalBack"></div>
<div class="modalImg"></div>
<ul class="imgWrap">
	<li class="imgItem"><img src="img/photo1-thumb.jpg" alt="" data-img="photo1.jpg"></li>
	<li class="imgItem"><img src="img/photo2-thumb.jpg" alt="" data-img="photo2.jpg"></li>
	<li class="imgItem"><img src="img/photo3-thumb.jpg" alt="" data-img="photo3.jpg"></li>
	<li class="imgItem"><img src="img/photo4-thumb.jpg" alt="" data-img="photo4.jpg"></li>
</ul>

CSS

.modalBack {
  display: none;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 100;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.8); }

.modalImg {
  display: none;
  position: fixed;
  top: 0;
  left: 0;
  padding: 7px;
  z-index: 1000;
  height: auto;
  background: #fff;
  border-radius: 5px;
  box-shadow: 0 0 20px rgba(0, 0, 0, 0.5); }
  .modalImg img {
    display: block;
    width: 100%; }

.imgWrap {
  display: flex;
  margin: 20px auto;
  padding: 5px;
  width: 1000px;
  height: auto;
  background: #eee; }

.imgItem {
  padding: 5px; }
  .imgItem img {
    display: block;
    width: 100%; }

jquery

<script>
	$(function(){
		$(window).on('load resize',function(){
			wSize = $(window).width();
			if(wSize>1000){
				mSize = 1000;
			}else{
				mSize = wSize*0.9;
			}
			mLeft = (wSize - mSize)/2;
			$('.modalImg').css({
				'width' : mSize,
				'top' : '30px',
				'left' : mLeft,
			});
		});
		$('.imgItem img').on('click',function(){
			fullImg = $(this).data('img');

			$('.modalImg').html('<img src="img/'+fullImg+'">');
			$('.modalBack').fadeIn();
			$('.modalImg').fadeIn();
		});
		$('.modalImg , .modalBack').on('click',function(){
			$('.modalBack').fadeOut();
			$('.modalImg').fadeOut();
		});
	});
</script>

サムネイル画像には縮小サイズの画像、data属性にはフルサイズの画像ファイル名を入れておきます。
サムネイルをクリックするとimg src内のdata属性からファイル名を読み込み、拡大表示する方法です。

原理としてはライトボックス系プラグインではよくある手法じゃないでしょうか。
尚、スクリプトは簡易的なものなので実際の運用には表示位置やサイズなど、少々手を加える必要があります。

まとめ

以上、data属性を使用したサンプルでした。
phpからjqueryへの値の受け渡しでは時々使ったりしていましたが、アイディア次第で色々使えそうですね!

特にこれまでclassに頼り切っていたバージョン違いや状態変化のフラグなんかでのSCSSとの連携は大いに有用かなと。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA