Sassを使ってみる-その③難しそうなところ-
この記事の目次
@functionで関数を作る
SCSSでは関数を作って使うこともできますが他のプログラミング言語とは違い複雑なことはせずに返り値を使うことしかできません。
作り方は大体のプログラミング言語とそっくりで、先頭に@functionをいれ、半角スペースの後に関数名 引数を入れる()の中に引数必要な分だけカンマ区切りで変数の形で入れます {}の中には引数を使った処理を入れていきます 呼び出しもとに返すための@return文を最後に置けば完成
処理の中で変数を使うこともできるのでオススメ
1 2 3 4 |
@function 関数名(必要な文変数を入れる){ 引数を使った処理 @return 呼び出しもとに戻すデータ } |
親要素と子要素の大きさを引数に入れて何%か計算して出力する関数を試してみます
Really Quick Responsive Web Design Calculatorこのサイトの計算機と同じ機能を作ってみます
1 2 3 4 5 6 7 8 |
/*親要素と子要素の値だけを使って%に直す関数*/ @function responsive($parent,$child){ $result:($child/$parent*100)#{'%'}; /*最後の#{'%'}は単位を付けるためのもの*/ @return $result; } header{ width: responsive(1000,400); /*第一引数に親の幅、第二引数に個の幅を入れる*/ } |
この状態でコンパイルすると計算した状態で出力されるようになります
毎回計算しないといけなかったものが関数さえ作っておけばSCSSのファイル内でできるので楽なのではなかろうか
1 2 3 |
header { width: 40%; } |
#{}
変数に入った文字列は通常は値として認識されてエラーが出てしまって、そのままだとプロパティの値にしか使用できません。単位なども同じで変数を使った処理の後につけようとするとエラーになります
ハッシュ記号を前に置いた波括弧 #{}と組み合わせることでセレクタやプロパティ名にも使うことができるようになります。上の関数のところでは文字列扱いで使いました
例として変数に入れた文字列を使ってクラスセレクタやプロパティ名を出力してみます
1 2 3 4 5 |
$name: name; $bgc: background; p.#{$name} { #{$bgc}-color: blue; } |
コンパイルした出力内容は以下のようになります
1 2 3 |
p.name { background-color: blue; } |
何かと何かを組み合わせるのであればこの#{}を使ってください
@mixinと@includeで用意したコードを使いまわす
@mixinは使いまわしたいコードを準備するための構文で, 引数を使って初期値を指定したり、コンテントブロックを指定したりできる
@includeは準備したコードを呼び出すための構文になります
まずは簡単なひな形から
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/*引数を使わず呼び出す用途なら()付けずに作る*/ @mixin 呼び出すための名前 { 呼び出したときに出力するコード } /*引数を使うときはカンマで区切る*/ @mixin 呼び出すための名前(引数1,引数2){ 呼び出したときに出力するコード } /*呼び出し*/ body{ @include 名前; } |
例えば文字に対しての指定をまとめておいて出力すると
1 2 3 4 5 6 7 8 |
@mixin text{ font-size: 18px; color: #111; letter-spacing: 3px; } p{ @include text; } |
コンパイルするとこのように@mixinで作った設定がそのまま吐き出されます
1 2 3 4 5 |
p { font-size: 18px; color: #111; letter-spacing: 3px; } |
引数を使って初期値を指定する例も見ておきましょう
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
//mixinを定義 @mixin text($size:18px,$color:#111){ font-size: $size; color: $color; } /*そのまま初期値で呼び出し*/ h1{ @include text; } /*それぞれ値を指定して呼び出し*/ p{ @include text(30px,#fff); } /*特定の値だけ指定 他は初期値*/ div{ @include text($color:#000); } |
このコードでコンパイルすると
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/*そのまま初期値で呼び出し*/ h1 { font-size: 18px; color: #111; } /*それぞれ値を指定して呼び出し*/ p { font-size: 30px; color: #fff; } /*特定の値だけ指定 他は初期値*/ div { font-size: 18px; color: #000; } |
※プロパティ値でカンマを使って複数を区切らないといけないものは少し書き方が複雑になります
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
@mixin font($family) { font-family: $family; } /*定義するときの()内にそのまま変数を入れた場合は、さらに()で囲む必要がある*/ h1{ @include font((Arial, sans-serif)); } /*カンマ区切りで複数の値を指定するならば()内の変数名直後に...を付ける*/ @mixin font($family...) { font-family: $family; } h1 { @include font(Arial, sans-serif); } |
コンパイル結果
1 2 3 4 5 6 7 8 |
/*定義するときの()内にそのまま変数を入れた場合は、さらに()で囲む必要がある*/ h1 { font-family: Arial, sans-serif; } /*カンマ区切りで複数の値を指定するならば()内の変数名直後に...を付ける*/ h1 { font-family: Arial, sans-serif; } |
@contentの使い方
@mixinの中の{}内で@content;と記述するとコンテントブロックを渡すことができ、1つのmixinで呼び出し側に合わせて処理を追加したりすることが可能になります
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/*特定のクラスが付いた要素に対して使いたい*/ @mixin active() { &.active { display: none; @content; } } /*普通に呼び出し*/ div { @include active(); } /*呼び出した後に{}を付けると中の内容を@content部分に追加したようにできる*/ section{ @include active(){ background-color: #fff; } } |
コンパイルすると
1 2 3 4 5 6 7 8 9 10 11 |
@charset "UTF-8"; /*特定のクラスが付いた要素に対して使いたい*/ /*普通に呼び出し*/ div.active { display: none; } /*呼び出した後に{}を付けると中の内容を@content部分に追加したようにできる*/ section.active { display: none; background-color: #fff; } |
特定要素のスタイルを引き継ぐ@extend
一度記述した要素のスタイルを、他の要素のスタイル記述時に再利用したい場合に便利です
1 2 3 |
セレクタ{ @extend 継承したいセレクタ; } |
例えばこんなコードを書いてみると
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
div { width: 500px; height: 300px; font-size: 20px; } /*divのスタイルを継承しつつ文字サイズは18px*/ section { @extend div; font-size: 18px; } /*divのスタイルを継承しつつ文字サイズは14px*/ article { @extend div; font-size: 14px; } |
コンパイルしてみるとこのような形になります
どうしても仕様で継承した場合は複数セレクタの形で出力されてしまいますのでその点には注意
1 2 3 4 5 6 7 8 9 10 11 12 13 |
div, section, article { width: 500px; height: 300px; font-size: 20px; } /*divのスタイルを継承しつつ文字サイズは18px*/ section { font-size: 18px; } /*divのスタイルを継承しつつ文字サイズは14px*/ article { font-size: 14px; } |
@if / @else / @else if で条件分岐
余り使い道がないように思えますがsassでも条件分岐ができます
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@if 条件式{ 条件式がtrueの処理 } @if 条件式{ 条件式がtrueの処理 }@else{ 条件式がfalseの処理 } @if 条件A{ 条件Aがtrueの処理 }@else if 条件B{ 条件Bがtrueの処理 } |
1 2 3 4 5 6 7 8 |
$font: 30px; body { @if $font>24px{ /*変数$fontの中身が24pxより大きかったら*/ font-weight: bold; } @else { /*それ以外の処理*/ font-weight: normal; } } |
コンパイルすると
1 2 3 |
body { font-weight: bold; } |
繰り返し構文は@for
@for 変数名 from ◯ to(through) △」の記法によって、指定した数値の範囲で繰り返し処理ができます。 変数名はやっぱり$iを使うことが多いようですが、好きなものを使ってください
1 2 3 |
@for 変数名 from 最初の数値 to 終わる数値{ 繰り返す処理 } |
toを使った場合は2つ目の値を範囲に含まず、throughを使った場合は2つ目の値を範囲に含む形になります
1 2 3 4 5 6 7 8 9 10 11 12 |
/*toを使うと.box1と.box2への指定が出てくる*/ @for $i from 1 to 3 { .box#{$i} { width: 100px; } } /*throughを使うと.box1と.box2と.box3への指定が出てくる*/ @for $i from 1 through 3 { .box#{$i} { width: 100px; } } |
コンパイルすると
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/*toを使うと.box1と.box2への指定が出てくる*/ .box1 { width: 100px; } .box2 { width: 100px; } /*throughを使うと.box1と.box2と.box3への指定が出てくる*/ .box1 { width: 100px; } .box2 { width: 100px; } .box3 { width: 100px; } |
配列を繰り返し処理する@each
変数に配列を格納して、配列のデータがなくなるまで繰り返すことも可能です
扱うデータが配列の場合は「@each データを入れる変数名 in 配列名」の記法を使います。
1 |
$配列名:データ1,データ2,データ3; |
配列の各値を一つずつ取り出して繰り返し処理することが可能になります
PHPなどのforeach考え方は同じだけど書き方が別物になっているので注意
1 2 3 4 5 |
$配列名:データ1,データ2,データ3; @each データを入れる変数 in 配列{ データを入れた変数を使った処理 } |
例えば大まかにコンテンツを配列で作りクラスセレクタにして使うなら
1 2 3 4 5 6 7 |
$contents:news,about,menu,staff; @each $content in $contents{ .#{$content}{ width: 80%; margin: 0 auto; } } |
元々共通するクラスを使えばいいように思えますがこのように配列のデータを使い各クラスへ指定ができます
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
.news { width: 80%; margin: 0 auto; } .about { width: 80%; margin: 0 auto; } .menu { width: 80%; margin: 0 auto; } .staff { width: 80%; margin: 0 auto; } |