【Sass】CSSを効率的に書くために

プログラミング初心者の勉強ブログ #103

CSSを効率的に書くことができる記法であるSassについて学んでいきます。ファイルをパーシャルで分割したり、変数や関数を用いて繰り返し文を書いたりと、CSSをバカみたいに書きまくることがいかに時間を無駄にかけていたかを痛感します。

 

目次

[toc]

 

Sassとは

sass_logo

Sassとは簡単に言うと「CSSを効率的に書くための記法」です。よく使用する色や形などをあらかじめ変数に代入したり、モジュールのようにまとめておくことができます。Sassのようなプログラムのことは「CSSプリプロセッサー」と呼ばれており、変数やMixinだけでなく、関数を定義して繰り返し文を作ることや、オブジェクト指向で言う「継承」をさせることも可能です。

Sassと言いつつ主流は「scss」ファイルを使います。もともとSassはRubyで開発されており、「sass」ファイルの仕様がデザイナーの人々に不評だったらしく、改良を加えた結果作られたのが「scss」だったらしいです。scssファイルをSassプログラムがcssファイルに変換する、といった仕組みです。

Sassで使用できるデータ型は、

  • 数値
  • 文字列
  • 真偽値
  • リスト

とたくさんあり、もちろん「+, -, /, *, %, >, <」などの演算子を使うことができます。

以下scssファイルでの記法をまとめていきます。上にscssのコーディング、下に反映されるcssを書きます。

 

入れ子構造

【scss側】

body {
 font-size: 16px;
 p {
   color: #fff;
   a {
     text-decoration: none;
     &:hover {
       opacity: 0.8;
     }
   }
 }
}

【変換されたcss】

body {
 font-size: 16px;
}
body p {
 color: #fff;
}
body p a {
 text-decoration: none;
}
body p a:hover {
 opacity: 0.8;
}

 

まずsassの基本として、ブロックを入れ子構造にできます。途中の「&」は親要素を表します。

a {
 text-decoration: none;
 &:hover {
  opacity: 0.8;
}

この場合「&:hover」は「a:hover」に変換されます。

入れ子構造を取ることで、冗長的な表現を字下げですっきりとまとめることができるのがSassの基本的な特徴となります。

 

変数

【scss側】

$baseFontSize: 16px;
$imgDir: "assets/img/";
$baseColor: #fff;

body {
 font-size: $baseFontSize;
 div {
  background: url("#{$imgDir}image.png");
 }
 p {
   color: $baseColor;
 }
}

 

【変換されたcss】

body {
 font-size: 16px;
}
body div {
 background: url("assets/img/image.png");
}
p {
 color: #fff;
}

「$ 変数名: 値;」で変数を定義できます。ダブルクオーテーション内などの文字列上で変数を使いたい場合は、「#{ }」で変数を囲みます。ここら辺はRubyと似ています。注意点として、変数を定義できるのは「値」のみです。プロパティ名は変数を利用することができません。

 

繰り返し

for

【scss側】

/* for文で繰り返し処理 */
@for $i from 12 through 16 {
 .fSize_#{$i} {
  font-size: #{$i}px;
 }
}

 

【変換されたcss】

/* for文で繰り返し処理 */
.fSize_12 {
  font-size: 12px;
}

.fSize_13 {
  font-size: 13px;
}

.fSize_14 {
  font-size: 14px;
}

.fSize_15 {
  font-size: 15px;
}

.fSize_16 {
  font-size: 16px;
}

 

while

【scss側】

/* while文で繰り返し処理 */
$j: 20;
@while $j <= 28 {
  .fSize_#{$j} { font-size: #{$j}px; }
  $j: $j + 2;
}

 

【変換されたcss】

/* while文で繰り返し処理 */
.fSize_20 {
  font-size: 20px;
}

.fSize_22 {
  font-size: 22px;
}

.fSize_24 {
  font-size: 24px;
}

.fSize_26 {
  font-size: 26px;
}

.fSize_28 {
  font-size: 28px;
}

 

each(リストの処理)

【scss側】

/* リストでeach文 */
$fluits: apple, orange, grape;
@each $f in $fluits {
  .#{$f}-img { background: url("#{$f}.png") }
}

 

【変換されたcss】

/* リストでeach文 */
.apple-img {
  background: url("apple.png");
}

.orange-img {
  background: url("orange.png");
}

.grape-img {
  background: url("grape.png");
}

forやwhileを使って一気に変数を作成することが可能です。また、「@each」を使うことでリストデータを繰り返し処理することも可能です。

 

関数

【scss側】

/* グリッドのカラム幅を計算する関数 */

// ウィンドウの幅
$totalWidth: 960px;

//カラムの個数
$columnCount: 10;

@function getColumnWidth($width, $count) {
 // グリッド間のpadding幅を定義
 $padding: 10px;

 // paddingとcolumnCountより幅を計算
 $columnWidth: floor($width - ($padding * ($count - 1))) / $count;

 // @debugで実行結果をターミナルに表示できる
 @debug $columnWidth;

 // @returnで戻り値を指定
 @return $columnWidth;
}

.grid {
  float: left;
  width: getColumnWidth($totalWidth, $columnCount);
}

 

【変換されたcss】

.grid {
 float: left;
 width: 87px;
}

関数は「@function 関数名(引数){ }」で定義できます。戻り値は「@return」、「@debug」は実行結果をターミナルに表示させることができます。

 

Mixin

【scss側】

/* mixinの利用 */
@mixin btn ($width:200px){
 width: $width;
 padding: 7px;
 color: #fff;
 background: blue;
 cursor: pointer;
 border-radius: 5px;
}

.btn {
  font-size: 15px;

  // @includeでmixinを呼び出す
  @include btn(300px);
}

 

【変換されたcss】

/* mixinの利用 */
.btn {
 font-size: 15px;
 width: 300px;
 padding: 7px;
 color: #fff;
 background: blue;
 cursor: pointer;
 border-radius: 5px;
}

@mixinを定義し、ブロックの中で@includeを書くことで呼び出せます。引数を与えることができ、引数には初期値もあらかじめ定義できます。今回の場合、初期値は200pxであり、仮に引数が渡って来なかった場合は200pxのwidthでbtnが表示されます。

 

継承

【scss側】

/* 継承(extend)の利用 */
.msg {
 font-size: 12px;
 font-weight: bold;
 padding: 2px 4px;
 color: #fff;
}

.errorMsg {
 @extend .msg;
 background: red;
}

.infoMsg {
 @extend .msg;
 background: skyblue;
}

 

【変換されたcss】

/* 継承(extend)の利用 */
.msg, .errorMsg, .warningMsg {
 font-size: 12px;
 font-weight: bold;
 padding: 2px 4px;
 color: #fff;
}

.errorMsg {
 background: red;
}

.infoMsg {
 background: skyblue;
}

「@extend」で継承が行えます。Mixinと似ていますが、継承の場合複数の要素に対して@extendをしてもコードが重複しません。重複コードを避けることができ、処理が早くなります。

 

パーシャルの活用

Sassではパーシャルファイルを作成しインポートすることが可能です。先ほどのグリッドのカラム幅を計算する関数の場合、「_function.scss」と「_setting.scss」というパーシャルファイルを作成し、関数や変数をメインと分けます。

 

_function.scss

@function getColumnWidth($width, $count) {
 $padding: 10px;
 $columnWidth: floor($width - ($padding * ($count - 1))) / $count;
 @return $columnWidth;
}

 

_setting.scss

$totalWidth: 960px;
$columnCount: 10;

 

main.scss

@import "functions";
@import "settings";

.grid {
  float: left;
  width: getColumnWidth($totalWidth, $columnCount);
}

「@import」を使うことでファイルの分割が可能になります。実行結果は同じです。

 

まとめ

Rubyで作られただけあってRubyの書き方と似ている部分が多い気がします。Mixinとかパーシャルとか継承とか、もうそれはオブジェクト指向な訳であって、設計力が必要になってきます。最近JSやっててconstとletとvarの違いがだいぶ理解できるようになりました。JSの変数は「宣言」と「代入」でしっかり区別して考えるべきなんだなと。スコープもなんとなくで覚えていましたが、コードを綺麗に書く意識を持つと明確になってきます。ここ最近ずっとJSとCSSやってて今日久しぶりにRubyでif文書こうとしたら、カッコもセミコロンも何もつけないでスッキリしすぎてて不安になりました。やたらめったら思うがままに感想を書いてますが、今後の当面の個人目標は「設計力向上」なのかなと思ってます。フレームワーク依存しすぎの状況からの脱却です。Webアプリの「ブラウザ上のカッコよさ」だけでなく、コーディングに対しても洗練されたカッコよさが出せたらなということです。結局今まではコーティングに対する「カッコよさ」が不明瞭で、重要性は頭では理解していても、僕の中でうまいこと優先順位を上げきれてなかったんだと思います。何がカッコいいのかわからなければ憧れようもないっていう。オブジェクトがうまいことまとまった綺麗で整ったコードに対し「カッコ良い。シャレオツだ。洗練されている。」という価値を見出せたことが最近の進歩かなと。

以上ありがとうございました。

返信を残す

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

CAPTCHA