sassでコーディング効率化!意外と知らなかった?関数いろいろ※cssコンパイル後ソースあり

2015.5.8 CSS

sassでコーディング効率化!意外と知らなかった?関数※cssコンパイル後ソースあり

Sassを使ってコーディングする中で、ネストやらミックスインだけでも効率化において効果を発揮しますが、拡張メタ言語としてもっとイキイキとしてもらうためには関数が必須ですね。

compassなんかも使って効率化しましょう!というわけで、僕も忘れがちな関数とコンパイル後にCSSでどうなっているか、さらにちょっとした注釈などを殴り書きしていきます。

sassでコーディング効率化!意外と知らなかった?関数

ソースコード簡略化系

処理の条件分岐をさせる「@if(~)」

Sass(コンパイル前)

@mixin ifKakko($fontweight : bold){
	
	@if($fontweight == bold){
		p{
			font-weight: bold;
		}
	}
	@else if($fontweight == lighter){
		p{
			font-weight: lighter;
		}
	}@else{
		p{
			font-style: italic;
		}
	}
}

@mixin ifNoKakko($fontweight : bold){
	
	@if $fontweight == bold {
		p{
			font-weight: bold;
		}
	}
	@else if $fontweight == lighter{
		p{
			font-weight: lighter;
		}
	}@else{
		p{
			font-style: italic;
		}
	}
}


.div1{
	@include ifNoKakko(bold);
}
.div2{
	@include ifKakko(lighter);
}
.div2{
	@include ifKakko(other);
}

CSS(コンパイル後)

.div1 p {
 font-weight: bold;
}

.div2 p {
 font-weight: lighter;
}

.div2 p {
 font-style: italic;
}

@ifに関してはよく紹介されていますが、Javascriptなどみたいに@if(~~)と、括弧を用いても動作するのはあまり紹介されていない気がします。

僕は括弧を使ったほうがやりやすいので、括弧派です!

 

CSSを引用する「@extend」

Sass(コンパイル前)

.ext
{
 p{
  margin: 1em;
 }
}

html
{
 section{
  @extend .ext;
 }
}

CSS(コンパイル後)

.ext p, html section p {
  margin: 1em;
}

ネストしてあるクラス指定まできっちりと継承して、まとめられます。

値ひとつを返す際に使う「@function」

Sass(コンパイル前)

@function sample($value){
 @return round($value / 2);
}

.test{
 width : sample(100px);
}

CSS(コンパイル後)

.test {
 width: 50px;
}

@functionに至っては@mixinとほぼ同様の動作ですが、こちらは処理結果の単体の値しか返せません。

@return 値 と書いて値をリターンします。

「わかりやすいコードを書く」という意味で使い分けるといいですね!

関数を作成する「@mixin」

Sass(コンパイル前)

//引数が単体の値の役割を果たす時
@mixin shadowColor($color){
 text-shadow : 0 0 10px $color;
}

//引数が複数の値の役割を果たす時
@mixin shadow($value...){
 text-shadow : $value;
}

.shadow{
 @include shadow(5px 5px 0 #ccc , 10px 10px 5px #aaa);
}

.shadowColor{
 @include shadowColor(#ccc);
}

CSS(コンパイル後)

.shadow {
 text-shadow: 5px 5px 0 #ccc, 10px 10px 5px #aaa;
}

.shadowColor {
 text-shadow: 0 0 10px #ccc;
}

関数名の後の()内の引数に続けて「」と書くことで、カンマ区切りの配列で値を指定できるようになります。

「@content」を応用してレスポンシブデザイン用のCSSメディアクエリを楽に書く

Sass(コンパイル前)

$bpSmp : 480px; //smartphone
$bpTab : 780px; //tablet
$bpPc : 1200px; //pc
$bpSmpMin : 'min-width : #{$bpSmp}';
$bpSmpMax : 'max-width : #{$bpSmp}';
$bpTabMin : 'min-width : #{$bpTab}';
$bpTabMax : 'max-width : #{$bpTab}';
$bpPcMin : 'min-width : #{$bpPc}';
$bpPcMax : 'max-width : #{$bpPc}';

@mixin breakPoint(
	$mediaWidth ,
	$minMax
	){
	@if ($mediaWidth == sp){

		@if($minMax == min){//min-width
			@media only screen and ($bpSmpMin){
				@content;
			}
		}			
		@if($minMax == max){//max-width
			@media only screen and ($bpSmpMax){
				@content;
			}
		}
	}

	@if ($mediaWidth == tab){

		@if($minMax == min){//min-width
			@media only screen and ($bpTabMin){
				@content;
			}
		}			
		@if($minMax == max){//max-width
			@media only screen and ($bpTabMax){
				@content;
			}
		}
	}

	@if ($mediaWidth == pc){

		@if($minMax == min){//min-width
			@media only screen and ($bpPcMin){
				@content;
			}
		}			
		@if($minMax == max){//max-width
			@media only screen and ($bpPcMax){
				@content;
			}
		}
	}
}

body{
	margin: 0 auto;

	@include breakPoint(sp , max){
		width : 98%;
		margin : 0 1%;
	}
	@include breakPoint(tab , max){
		width : 90%;
		margin : 0 2.5%;
	}	
	@include breakPoint(pc , min){
		width : 1000px;
	}
}

CSS(コンパイル後)

body {
 margin: 0 auto;
}
@media only screen and (max-width: 480px) {
 body {
 width: 98%;
 margin: 0 1%;
 }
}
@media only screen and (max-width: 780px) {
 body {
 width: 90%;
 margin: 0 2.5%;
 }
}
@media only screen and (min-width: 1200px) {
 body {
 width: 1000px;
 }
}

1~3行目でブレークポイントのpx数を変数に格納します。
それを使って4~9行目でmin-widthやmax-widthなどメディアクエリの記述をさらに変数に格納します。

breakPoint」というミックスインをつくり、第一引数で「sp(スマホ)」「tab(タブレット)」「pc(パソコン)」を指定したときにそれぞれのブレークポイントに条件分岐するように書きました。
第二引数は「min(min-width)」か「max(max-width)」の分岐です。

 

プロパティをネストする

Sass(コンパイル前)

.nestedSample{
	border : {
		solid : 1px;
		color : #c00;
	}

	.nestedSample-bordetTop{
		border : {
			top : 5px;
		}
	}
}

CSS(コンパイル後)

.nestedSample {
  border-solid: 1px;
  border-color: #c00;
}
.nestedSample .nestedSample-bordetTop {
  border-top: 5px;
}

とても解りづらいのですが、例えば、cssの「border」というプロパティには「border-top」「border-width」「border-image」など、様々な種類があります。

それらを「border{}」の中にネストすることで簡略化できるということですね。

変数名を自在に使用できる「インターポレーション」

Sass(コンパイル前)

//通常、演算してしまう
.sample{
	$font-size : 12px;
	$line-height : 24px;

	font : $font-size / $line-height; //shorthand
}

//インターポレーションを用いて演算しないようにする
.sampleB{
	$font-size : 12px;
	$line-height : 24px;

	font : #{$font-size} / #{$line-height}; //shorthand	
}

//クラス名中でも演算
@for $i from 0 through 5{
	.sample-#{$i * 5}{
		margin-top : $i * 5px ;
	}
}

CSS(コンパイル後)

.sample {
  font: 0.5;
}

.sampleB {
  font: 12px / 24px;
}

.sample-0 {
  margin-top: 0px;
}

.sample-5 {
  margin-top: 5px;
}

.sample-10 {
  margin-top: 10px;
}

.sample-15 {
  margin-top: 15px;
}

.sample-20 {
  margin-top: 20px;
}

.sample-25 {
  margin-top: 25px;
}

スラッシュで区切ってショートハンドでCSSのfont指定をするとき、変数や数値どうしだと「/」が演算子となって、割り算されてしまいます。
しかしそこで、#{$変数名}と記述することで、演算されないようになります。

またこの記述でクラス名やグラデーションのfilterプロパティにも変数を使うことが出来ます。

色系

色の明度を調節する「darken」「lighten」

Sass(コンパイル前)

$defaultColor : #67abff;

.darken{
    background-color: darken($defaultColor , 50%);
}

.lighten{
    background-color: lighten($defaultColor , 10%);
}

CSS(コンパイル後)

.darken {
  background-color: #002e67;
}

.lighten {
  background-color: #9ac7ff;
}

色の彩度を調節する「saturate」「desaturate」

Sass(コンパイル前)

$defaultColor : #67abff;

.saturate{
    background-color: saturate($defaultColor , 50%);
}

.desaturate{
    background-color: desaturate($defaultColor , 10%);
}

CSS(コンパイル後)

.saturate {
  background-color: #67abff;
}

.desaturate {
  background-color: #6facf7;
}

色によっては彩度の高めようがない場合があります。その場合は、そのままのカラーコードが返されます。ちなみに彩度の単位は「%」でも「0.x」でも良いです。

似ている記述でも返す値の違う「rgba」「rgb」

Sass(コンパイル前)

.rgba{
    -webkit-box-shadow: 0 0 0 10px rgba(#000,.4);
    box-shadow: 0 0 0 10px rgba(#000,.4);
}

.rgb{
    -webkit-box-shadow: 0 0 0 10px rgb(125,100,15);
    box-shadow: 0 0 0 10px rgb(125,100,15);
}

CSS(コンパイル後)

.rgba {
  -webkit-box-shadow: 0 0 0 10px rgba(0, 0, 0, 0.4);
  box-shadow: 0 0 0 10px rgba(0, 0, 0, 0.4);
}

.rgb {
  -webkit-box-shadow: 0 0 0 10px #7d640f;
  box-shadow: 0 0 0 10px #7d640f;
}

rgba()は、本来10進数でカラーを指定するところに16進数や「white」などの文字列で指定しても変換して返してくれます。

rgb()は、10進数で指定して16進数で返してくれます。

引数の特定のカラーを抽出して10進数で返す「red」「green」「blue」

Sass(コンパイル前)

.red{
    color:red(#ff0000);
}

.green{
    color : green(#00fd00);
}

.blue{
    color : blue(#0000df);
}

CSS(コンパイル後)

.red {
  color: 255;
}

.green {
  color: 253;
}

.blue {
  color: 223;
}

完全にNGな結果になっていますが、要するに、括弧内の引数のRGB値から

  • red()なら#FF0000
  • blue()なら#00FF00
  • green()なら#0000FF

といった具合に、該当のカラーコードを10進数で返してくれます。

 

HSL色空間を操作する「hsl」「hsla」「hue」「saturation」「lightness」

 

Sass(コンパイル前)

 

.hsl{
    background-color: hsl(127 , 92% , 39%); //→rgb
}

.hsla{
    background-color: hsla(127 , 92% , 39% , 0.5); //→rgba
}

.hueOnly{
    property : hue(hsl(127 , 92% , 39%)); //→hue(色相)
}

.saturationOnly{
    property : saturation(hsl(127 , 92% , 39%)); //→saturation(彩度)
}

.lightnessOnly{
    property : lightness(hsl(127 , 92% , 39%)); //→hightness(明度)
}

 

CSS(コンパイル後)

 

.hsl {
  background-color: #08bf1d;
}

.hsla {
  background-color: rgba(8, 191, 29, 0.5);
}

.hueOnly {
  property: 127deg;
}

.saturationOnly {
  property: 92%;
}

.lightnessOnly {
  property: 39%;
}

 

Hue(色相)、Saturate(彩度)、Lightness(明度、輝度)という意味がありますが、hue(),saturation(),lightness()は、引数を元にそれぞれ対応した値を返します。
サンプルでは引数にhsl()関数を使っていますが、普通に16進数の#00adbbとかでも大丈夫です!

そのhsl()ですが、引数に指定したhsl形式のカラーコードを16進数のRGB値に変換してくれます。

同じ要領で、hsla()はa=Alpha(透明渡)が加わっているのでRGBA値に変換して返してくれます!

透明度の調節をする「opacify」「transparentize」

Sass(コンパイル前)

$defaultColor : #67abff;

//透明度を返す
.opacity{
    background-color: opacity(
        hsla(
            hue($defaultColor),
            saturation($defaultColor) ,
            lightness($defaultColor),
            0.8
        )
    );
}

//透明度を下げる
.opacify{
    background-color: opacify(
        hsla(
            hue($defaultColor),
            saturation($defaultColor) ,
            lightness($defaultColor),
            0.8
        ) ,
        0.1
    ); //#16進数
}

//透明度を上げる =透明にする
.transparentize{
    background-color: transparentize($defaultColor , 0.4); //→rgba
}

CSS(コンパイル後)

.opacity {
  background-color: 0.8;
}

.opacify {
  background-color: rgba(103, 171, 255, 0.9);
}

.transparentize {
  background-color: rgba(103, 171, 255, 0.6);
}

opacifyは、指定した色の透明度を下げて、より不透明にした値を返します。不透明にした結果、透明度の値が1を超えた場合は、16進数のRGB値を返します。

対して、transparentizeは、透明度を上げて、より透明に知覚した値を返します。

色相環上での補色を返す「complement」

Sass(コンパイル前)

$defaultColor : #67abff;

.blue{
    background-color: complement(blue);
}

.smaple{
    background-color: complement($defaultColor);
}

CSS(コンパイル後)

.blue {
  background-color: yellow;
}

.smaple {
  background-color: #ffbb67;
}

補色とは、色相環上で対照的な位置にある色のことです。

引数に指定した色の補色を返します。

色を反転させる「invert」

Sass(コンパイル前)

$defaultColor : #67abff;

.blue{
    background-color: invert(blue);
}

.smaple{
    background-color: invert($defaultColor);
}

CSS(コンパイル後)

.blue {
  background-color: yellow;
}

.smaple {
  background-color: #985400;
}

complement()と同じ場合もありますが、反転した色を返します。

数値系

絶対値を取得する「abs」

Sass(コンパイル前)

$absNum : -50px;

.minus{
    padding: 0 $absNum;
}
.plus{
    padding: 0 abs($absNum);
}

css(コンパイル後)

.minus {
  padding: 0 -50px;
}

.plus {
  padding: 0 50px;
}

数値の切り捨て、切り上げ「ceil」「round」「floor」

Sass(コンパイル前)

$Number : 999.4321;

.ceil{
	width : ceil($Number);
}

.round{
	width : round($Number);
}

.floor{
	width : floor($Number);
}

css(コンパイル後)

.ceil {
  width: 1000;
}

.round {
  width: 999;
}

.floor {
  width: 999;
}

.Sass(応用編ミックスイン)

// Round (四捨五入)
@function round-decimal ($number, $digits: 0) {
    @return to-fixed($number, $digits, 'round');
}

// Ceil (切り上げ)
@function ceil-decimal ($number, $digits: 0) {
    @return to-fixed($number, $digits, 'ceil');
}

// Floor (切り捨て)
@function floor-decimal ($number, $digits: 0) {
    @return to-fixed($number, $digits, 'floor');
}

@function to-fixed ($number, $digits: 0, $round: 'round') {
    $n: 1;
    // $number must be a number
    @if type-of($number) != number {
        @warn '#{ $number } is not a number.';
        @return $number;
    }
    // $digits must be a unitless number
    @if type-of($digits) != number {
        @warn '#{ $digits } is not a number.';
        @return $number;
    } @else if not unitless($digits) {
        @warn '#{ $digits } has a unit.';
        @return $number;
    }
    @for $i from 1 through $digits {
        $n: $n * 10;
    }
    @if $round == 'round' {
        @return round($number * $n) / $n;
    } @else if $round == 'ceil' {
        @return ceil($number * $n) / $n;
    } @else if $round == 'floor' {
        @return floor($number * $n) / $n;
    } @else {
        @warn '#{ $round } is undefined keyword.';
        @return $number;
    }
}

// round-decimal(0.333)    => 0
// round-decimal(0.333, 1) => 0.3
// round-decimal(0.333, 2) => 0.33
// round-decimal(0.666)    => 1
// round-decimal(0.666, 1) => 0.7
// round-decimal(0.666, 2) => 0.67

// ceil-decimal(0.333)     => 1
// ceil-decimal(0.333, 1)  => 0.4
// ceil-decimal(0.333, 2)  => 0.34
// ceil-decimal(0.666)     => 1
// ceil-decimal(0.666, 1)  => 0.7
// ceil-decimal(0.666, 2)  => 0.67

// floor-decimal(0.333)    => 0
// floor-decimal(0.333, 1) => 0.3
// floor-decimal(0.333, 2) => 0.33
// floor-decimal(0.666)    => 0
// floor-decimal(0.666, 1) => 0.6
// floor-decimal(0.666, 2) => 0.66

小数の桁数と丸め方を制御する Sass 関数 · terkel.jpより。なるほどー!

パーセント変換をしてくれる「percentage」

Sass(コンパイル前)

$wrapperWidth : 1000px;

$leftWidth : 750px;
$rightWidth : 200px;

$leftWidthP : percentage($leftWidth / $wrapperWidth);
$rightWidthP : percentage($rightWidth / $wrapperWidth);

.l{
    width : $leftWidthP;
}

.r{
    width: $rightWidthP;
}

css(コンパイル後)

.l {
  width: 75%;
}

.r {
  width: 20%;
}

ループ系

配列を順に処理する「@each~in~」

Sass(コンパイル前)

$navList : about , staff , store , profile , contact;

@each $navClass in $navList
{

	li.#{$navClass}{
		margin-right: 5px;
		padding: 10px 20px;
	}

}

css(コンパイル後)

li.about {
  margin-right: 5px;
  padding: 10px 20px;
}

li.staff {
  margin-right: 5px;
  padding: 10px 20px;
}

li.store {
  margin-right: 5px;
  padding: 10px 20px;
}

li.profile {
  margin-right: 5px;
  padding: 10px 20px;
}

li.contact {
  margin-right: 5px;
  padding: 10px 20px;
}

li {
  list-style: none;
  display: inline-block;
}
li:last-child {
  margin-right: 0;
}

規定の回数だけループする「@for~form~」

Sass(コンパイル前)

@mixin forLoop-through($hensuu){
	
	@for $classNum from 1 through 4{
		#{$hensuu}_#{$classNum}{
			margin-bottom: 3px * $classNum;
		}
	}
}

@mixin forLoop-to($hensuu){
	$classNum : 1;
	
	@for $classNum from 1 to 4{
		#{$hensuu}_#{$classNum}{
			margin-bottom: 3px * $classNum;
		}
	}
}

body{
	@include forLoop-through(div);
}

html{
	@include forLoop-to(div);
}

css(コンパイル後)

body div_1 {
  margin-bottom: 3px;
}
body div_2 {
  margin-bottom: 6px;
}
body div_3 {
  margin-bottom: 9px;
}
body div_4 {
  margin-bottom: 12px;
}

html div_1 {
  margin-bottom: 3px;
}
html div_2 {
  margin-bottom: 6px;
}
html div_3 {
  margin-bottom: 9px;
}

@for ~ from 1 to 4だと1~3。@for ~ from 1 thorough 4だと、1~4の繰り返し。

変数$classNumが1からスタートし4に到達するか、それ以下までか、ということですね。

数の上限までループする「@while~」

Sass(コンパイル前)

@mixin whileLoop(
	$hensuu ,
	$startNum : 0 ,
	$endNum : 5){
	@while $endNum > $startNum{
		#{$hensuu}_#{$startNum}{
			margin-bottom: 3px * $startNum;
		}
	}
}

body{
	@include whileLoop(div);
}

css(コンパイル後)

body .div_1 {
  background-image: url(../img/bg/bg-1.jpg);
}
body .div_2 {
  background-image: url(../img/bg/bg-2.jpg);
}
body .div_3 {
  background-image: url(../img/bg/bg-3.jpg);
}

いかがでしたか?

汎用的なものの一部はきっとこのページにある関数ではないかな、と思います。ここに書いたものはどれも結構使っていて、且つとても役立っていますねー!

SyntaxHighlighterでSASSのブラシがないため見づらいうえに、「●●系」で無理やりカテゴライズした感が満載ですが、こんな感じで次回はcompass編を紹介していこうと思います!

 

でわ!

プロフィール

東京でWebデザイナー・コーダーとして、フロントエンド的なことからグラフィックデザイン的なことをして、ごにょごにょと小さく活動中。Webクリエイターでは珍しい(?) HIPHOP, R&B好き。休日はよくカフェや漫画喫茶に出向いたりパン屋に行ったり、主に散歩しています。だいたいラーメンを食べて帰ってくる、そんな過ごし方です(都内のオススメ散歩コース募集中!)。デザインのトレンドやデザイン思考、HTML、CSSからSASS、Javascript、Wordpress構築などコーディングのTIPSなどをブログにアップしていきます。その他のことはtwitter( @satohmsys )まで。