例えばクラス名の一部と背景画像名だけ変更したものをいくつも記述するとか連番付きクラスをいくつも記述しながら一部プロパティだけ変更するなど、普段からCSSを書くことが多い人であれば、ほとんどの人が先述したような同じようなものを繰り返し記述していくということをしたことがあると思います。
そういったときにSassを使っていれば、@each
や@for
といった制御構文を利用して繰り返し記述する手間を省くことができます。
ここで紹介しているものはいずれも簡易的なものですし、実際に使ってみたりコードを少し見ればわかるようなものばかりだと思うので、普段から同じようなものを繰り返し記述する機会が多いのにまだ試したことがないという人は是非試してみてください。
Sass:@eachや@forを使って繰り返し記述する手間を省く 目次
1. クラス名と背景
@each
と配列を使って、クラス名とイメージまたはカラーの背景指定を楽に出力するものです。
ここで紹介するサンプルぐらいでは数が少ないので苦じゃないですが、これがもっと大量にある場合はコピーしてクラス名や背景指定部分変えるという作業を何度もしないで済みますし、あとで追加・削除などする場合も配列部分を変更するのみです。
1-1. クラス名と背景画像
各ページ名が付けられたクラス名とそれに対応するイメージディレクトリを出力するというものです。
配列にページ名とイメージディレクトリ名で使用するものを記述していき、あとは下記のように@each
でクラス名とイメージディレクトリの部分に配列で指定したものが出力されるように記述していきます。
SCSS
$pages: pageA, pageB, pageC, pageD, pageE;
@each $page in $pages {
.#{$page}-bg {
background: url(../images/#{$page}/bg.jpg) 0 0 no-repeat;
}
}
これをコンパイルすると下記のように出力されます。
CSS
.pageA-bg {
background: url(../images/pageA/bg.jpg) 0 0 no-repeat;
}
.pageB-bg {
background: url(../images/pageB/bg.jpg) 0 0 no-repeat;
}
.pageC-bg {
background: url(../images/pageC/bg.jpg) 0 0 no-repeat;
}
.pageD-bg {
background: url(../images/pageD/bg.jpg) 0 0 no-repeat;
}
.pageE-bg {
background: url(../images/pageE/bg.jpg) 0 0 no-repeat;
}
1-2. クラス名と背景色
こちらは各ページ名が付けられたクラス名とそれに対応する背景色が指定されたものが出力されるというものです。
クラス名と背景色指定はマップを利用して指定しておき、あとは下記のように@each
を使ってそれぞれ出力されるように記述していきます。
SCSS
$page-color: (
'pageA': #0ff,
'pageB': #f0f,
'pageC': #ff0,
'pageD': #000,
'pageE': #fff
);
@each $page, $color in $page-color {
.#{$page}-bg {
background-color: $color;
}
}
これをコンパイルすると下記のように出力されます。
CSS
.pageA-bg {
background-color: #0ff;
}
.pageB-bg {
background-color: #f0f;
}
.pageC-bg {
background-color: #ff0;
}
.pageD-bg {
background-color: #000;
}
.pageE-bg {
background-color: #fff;
}
1-3. クラス名と背景色(RGBA)
ほぼ先ほどの「クラス名と背景色」と一緒ですが、ちょっと記述を変えればRGBAでカラーや透明度を指定した状態で出力ができます。
SCSS
$page-color: (
'pageA': #0ff,
'pageB': #f0f,
'pageC': #ff0,
'pageD': #000,
'pageE': #fff
);
@each $page, $color in $page-color {
.#{$page}-bg {
background-color: rgba($color, .5);
}
}
これをコンパイルすると下記のように出力されます。
CSS
.pageA-bg {
background-color: rgba(0, 255, 255, 0.5);
}
.pageB-bg {
background-color: rgba(255, 0, 255, 0.5);
}
.pageC-bg {
background-color: rgba(255, 255, 0, 0.5);
}
.pageD-bg {
background-color: rgba(0, 0, 0, 0.5);
}
.pageE-bg {
background-color: rgba(255, 255, 255, 0.5);
}
1-4. クラス名と背景画像+背景色
背景イメージだけでなく背景カラーも併せて指定する必要がある場合は、上で紹介した「クラス名と背景画像」と「クラス名と背景色」を組み合わせる感じで下記のように記述していきます。
SCSS
$page-color: (
'pageA': #0ff,
'pageB': #f0f,
'pageC': #ff0,
'pageD': #000,
'pageE': #fff
);
@each $page, $color in $page-color {
.#{$page}-bg {
background: $color url(../images/#{$page}/bg.jpg) 0 0 no-repeat;
}
}
これをコンパイルすると下記のように出力されます。
CSS
.pageA-bg {
background: #0ff url(../images/pageA/bg.jpg) 0 0 no-repeat;
}
.pageB-bg {
background: #f0f url(../images/pageB/bg.jpg) 0 0 no-repeat;
}
.pageC-bg {
background: #ff0 url(../images/pageC/bg.jpg) 0 0 no-repeat;
}
.pageD-bg {
background: #000 url(../images/pageD/bg.jpg) 0 0 no-repeat;
}
.pageE-bg {
background: #fff url(../images/pageE/bg.jpg) 0 0 no-repeat;
}
2. SNSクラス名と背景
基本的には「1-2. クラス名と背景色」で紹介したマップと@each
を組み合わせたもので、それをSNSに関するスタイル指定で使ってみるサンプルコードです。
2-1. SNSクラス名と背景色
.sns-サービス名
のように各SNSのサービス名が入ったクラスを出力し、さらにそれぞれのブランドカラーを背景カラーとして指定したものもスタイルとして出力します。
SCSS
$sns-color: (
'twitter' : #55acee,
'facebook': #3b5998,
'gplus' : #dc4e41
);
@each $key, $color in $sns-color {
.sns-#{$key} {
background-color: $color;
}
}
これをコンパイルすると下記のように出力されます。
CSS
.sns-twitter {
background-color: #55acee;
}
.sns-facebook {
background-color: #3b5998;
}
.sns-gplus {
background-color: #dc4e41;
}
2-2. SNSクラス名と背景色+box-shadow
こちらは先ほどのものに加えてbox-shadow
の指定も出力するというものです。
別途box-shadow
で使用するカラー用の配列を作るとかでもいいですが、今回はブランドカラーで使用したカラーを明度を下げるdarken()
と組み合わせる形で出力していきます。
SCSS
$sns-color: (
'twitter' : #55acee,
'facebook': #3b5998,
'gplus' : #dc4e41
);
@each $key, $color in $sns-color {
.sns-#{$key} {
background-color: $color;
box-shadow: 0 3px 0 darken($color, 10%);
}
}
これをコンパイルすると下記のように出力されます。
CSS
.sns-twitter {
background-color: #55acee;
box-shadow: 0 3px 0 #2795e9;
}
.sns-facebook {
background-color: #3b5998;
box-shadow: 0 3px 0 #2d4373;
}
.sns-gplus {
background-color: #dc4e41;
box-shadow: 0 3px 0 #c63224;
}
2-3. SNSクラス名と背景色+hover
先ほどは背景カラーだけでなくdarken()
と組み合わせることでbox-shadow
のカラー指定も一緒に出力しましたが、下記のようにホバー時のカラー指定として使ったりすることもできます。
SCSS
$sns-color: (
'twitter' : #55acee,
'facebook': #3b5998,
'gplus' : #dc4e41
);
@each $key, $color in $sns-color {
.sns-#{$key} {
background-color: $color;
&:hover {
background-color: darken($color, 10%);
}
}
}
これをコンパイルすると下記のように出力されます。
CSS
.sns-twitter {
background-color: #55acee;
}
.sns-twitter:hover {
background-color: #2795e9;
}
.sns-facebook {
background-color: #3b5998;
}
.sns-facebook:hover {
background-color: #2d4373;
}
.sns-gplus {
background-color: #dc4e41;
}
.sns-gplus:hover {
background-color: #c63224;
}
今回はdarken()
を使っていきましたが、lighten()
とかsaturate()
でももちろんできるので、場面によって使い分けられます。
3. nth-childとアイコン画像
例えば、各li
要素にそれぞれ別のスタイル指定をしたいと思ったときに、それぞれに異なるクラスが付いていればそのクラスを利用すればいいですが、そうでない場合は:nth-child()
や:nth-of-type()
などの疑似クラスを使って指定することがあると思います。
下記はそのような場合の一例で、各li
要素に配列で指定したものが背景で指定する画像名の一部となって出力するような記述ですが、li
要素の部分はindex()
で取得した数値が:nth-child()
の数値指定部分に入るようになっています。
SCSS
$pages: pageA, pageB, pageC, pageD, pageE;
@each $page in $pages {
$i: index($pages, $page);
li:nth-child(#{$i}) {
background: url(../images/icon_#{$page}.png) 0 0 no-repeat;
}
}
これをコンパイルすると下記のように出力されます。
CSS
li:nth-child(1) {
background: url(../images/icon_pageA.png) 0 0 no-repeat;
}
li:nth-child(2) {
background: url(../images/icon_pageB.png) 0 0 no-repeat;
}
li:nth-child(3) {
background: url(../images/icon_pageC.png) 0 0 no-repeat;
}
li:nth-child(4) {
background: url(../images/icon_pageD.png) 0 0 no-repeat;
}
li:nth-child(5) {
background: url(../images/icon_pageE.png) 0 0 no-repeat;
}
4. ゼロパディングな連番クラスとアイコン画像
こちらは先ほどとは違いli
要素に連番付きのクラスが指定されているときに使える方法です。
単純に.item1
, .item2
, .item3
... のような連番クラスの場合は先ほど紹介したコードをほんの少し変更すればいいですが、これが.item01
, .item02
, .item03
... のようなゼロパディングな連番が付いているというときは、下記のように@if
を使った条件分岐を組み合わせ、10以下の場合とそうでない場合とで連番部分の出力内容を変更するように記述することで、出力する際にゼロパディングな連番クラスを指定することができます。
SCSS
$pages: pageA, pageB, pageC, pageD, pageE;
$num: "";
@each $page in $pages {
$i: index($pages, $page);
@if $i < 10 {
$num: "0#{$i}";
} @else {
$num: $i;
}
.item#{$num} {
background: url(../images/common/icon_#{$page}.png) 0 0 no-repeat;
}
}
これをコンパイルすると下記のように出力されます。
CSS
.item01 {
background: url(../images/common/icon_pageA.png) 0 0 no-repeat;
}
.item02 {
background: url(../images/common/icon_pageB.png) 0 0 no-repeat;
}
.item03 {
background: url(../images/common/icon_pageC.png) 0 0 no-repeat;
}
.item04 {
background: url(../images/common/icon_pageD.png) 0 0 no-repeat;
}
.item05 {
background: url(../images/common/icon_pageE.png) 0 0 no-repeat;
}
5. CSS Sprite(正方形アイコン)
こちらはCSS Spriteを使用する際に面倒なbackground-position
の指定を@each
を使って楽にするというもので、今回はわかりやすいので正方形のアイコンを使う場合で、サンプルコードでは32pxの正方形のアイコンが縦一列に並んでいるスプライト画像を使用した想定です。
まず、$icons
にそれぞれクラス名で使用する名前を、$size
ではアイコンのサイズを指定しておきます。
その下にある[class^="cs-icon"]
ではアイコンの基本スタイルとなるものを記述しており、サンプルではいずれも.cs-icon
というのがクラスの頭にくるので、ここではセレクタ指定に前方一致を利用しています。
最後に@each
内では上でも紹介してきたようにはじめに指定しておいた名前を使ってクラスを出力しつつ、index()
で取得した数とあらかじめ指定しておいたサイズとで計算してbackground-position
の値を出力するようにしています。
SCSS
$icons: foo, bar, baz;
$size: 32px;
[class^="cs-icon"] {
width: $size;
height: $size;
background-image: url(../images/common/icon_sprite.png);
background-repeat: no-repeat;
}
@each $name in $icons {
$i: index($icons, $name);
$position: ($i * $size - $size) * -1;
.cs-icon-#{$name} {
background-position: 0px $position;
}
}
これをコンパイルすると下記のように出力されます。
CSS
[class^="cs-icon"] {
width: 32px;
height: 32px;
background-image: url(../images/common/icon_sprite.png);
background-repeat: no-repeat;
}
.cs-icon-foo {
background-position: 0px 0px;
}
.cs-icon-bar {
background-position: 0px -32px;
}
.cs-icon-baz {
background-position: 0px -64px;
}
この方法を利用すればすべて記述する手間やbackground-position
の値指定が楽になるだけに限らず、他にも後々アイコンを追加・削除したとかサイズ変更したというときも、変数をいじるだけで対応できたりするので便利です。
6. 汎用クラス
これ自体スマートな感じがしませんが、よくあるmargin
やpadding
指定のみを行うとかカラム幅の指定をするといった汎用クラスを、Sassを使って楽に出力するというものです。
6-1. margin & padding指定の汎用クラス
.mt20 { margin-top: 20px !important; }
や.pt20 { padding-top: 20px !important; }
のように、margin
やpadding
指定のみを行うための汎用クラスを出力する方法です。
下記は5の倍数で0〜50までの数値を上下左右の全方向出力させるというもので、倍数は$num
の部分で指定しています。
SCSS
$num: 5;
@for $i from 0 through 10 {
.mt#{$i * $num} {
margin-top: #{$i * $num}px !important;
}
.mr#{$i * $num} {
margin-right: #{$i * $num}px !important;
}
.mb#{$i * $num} {
margin-bottom: #{$i * $num}px !important;
}
.ml#{$i * $num} {
margin-left: #{$i * $num}px !important;
}
.pt#{$i * $num} {
padding-top: #{$i * $num}px !important;
}
.pr#{$i * $num} {
padding-right: #{$i * $num}px !important;
}
.pb#{$i * $num} {
padding-bottom: #{$i * $num}px !important;
}
.pl#{$i * $num} {
padding-left: #{$i * $num}px !important;
}
}
これをコンパイルすると下記のように出力されます。
(すべて表示すると長くなるので、スペースなどを調整した出力例の一部になります。)
CSS
.mt0 { margin-top: 0px !important; }
.mr0 { margin-right: 0px !important; }
.mb0 { margin-bottom: 0px !important; }
.ml0 { margin-left: 0px !important; }
.pt0 { padding-top: 0px !important; }
.pr0 { padding-right: 0px !important; }
.pb0 { padding-bottom: 0px !important; }
.pl0 { padding-left: 0px !important; }
.
.
.
.mt50 {margin-top: 50px !important; }
.mr50 { margin-right: 50px !important; }
.mb50 { margin-bottom: 50px !important; }
.ml50 { margin-left: 50px !important; }
.pt50 { padding-top: 50px !important; }
.pr50 { padding-right: 50px !important; }
.pb50 { padding-bottom: 50px !important; }
.pl50 { padding-left: 50px !important; }
6-2. font-size
こちらはfont-size
指定用のクラスを出力するもので、最小サイズを$fs-min
に、最大サイズを$fs-max
にそれぞれ指定しており、最小サイズから最大サイズまでのフォントサイズ指定用のクラスを出力してくれます。
SCSS
$fs-min: 10;
$fs-max: 20;
@for $i from $fs-min through $fs-max {
.fs#{$i} {
font-size: #{$i}px;
}
}
これをコンパイルすると下記のように出力されます。
CSS
.fs10 { font-size: 10px; }
.fs11 { font-size: 11px; }
.fs12 { font-size: 12px; }
.fs13 { font-size: 13px; }
.fs14 { font-size: 14px; }
.fs15 { font-size: 15px; }
.fs16 { font-size: 16px; }
.fs17 { font-size: 17px; }
.fs18 { font-size: 18px; }
.fs19 { font-size: 19px; }
.fs20 { font-size: 20px; }
6-3. width(カラム幅指定)
margin
指定などない単純なカラム幅指定なので実際に使う場合は+α必要になってくると思いますが、下記でパーセントで幅指定されたカラム用のクラスを出力できます。
カラム数の指定は@for $i from 1 through 8
の部分で決めているので、増減をしたい場合は8
となっているところを任意の数値に変更してください。
SCSS
@for $i from 1 through 8 {
$width: percentage(1 / $i);
.col#{$i} {
width: $width;
}
}
これをコンパイルすると下記のように出力されます。
CSS
.col1 { width: 100%; }
.col2 { width: 50%; }
.col3 { width: 33.33333%; }
.col4 { width: 25%; }
.col5 { width: 20%; }
.col6 { width: 16.66667%; }
.col7 { width: 14.28571%; }
.col8 { width: 12.5%; }