• {{ item.count }}

コピペで始めるgulp入門(3):Sass(SCSS)導入編・後編

  • {{ item.count }}
コピペで始めるgulp入門(3):Sass(SCSS)導入編・後編

こんにちは、リードスペースです。
前回のコピペで始めるgulp入門(2):Sass(SCSS)導入編・前編から3か月経ってしまいました汗

今回はその続編です。前回は環境を作りSass(SCSS)が使えるようになりましたね!
続いてSass(SCSS)をもっと便利に使う方法について触れていきます。

この記事は、CSSがあらかじめ理解できていることを前提に進めています。ご了承ください。

スタイルはパーツで管理

みなさん、スタイルはどのように管理してますか?
以下のような管理をしている人が大半ではないでしょうか。

共通のスタイル
スマフォ用のメディアクエリ{
  スタイル
}
PC用のメディアクエリ{
  スタイル
}

CSSはカスケードスタイルシートと言って字のごとく上から滝(カスケード)のように書いていきます。
そのせいでよく考えて書かないと上書き、上書きで、しまいにはスタイルを!importantで矯正してしまいには破綻を招く羽目に
しかもメディアクエリごとにPCとスマフォのスタイルを分けて書いているとさらにカオスです汗
ファイルを複数分けて読めばいいと思うでしょうが、昨今のWebサイトの読み込みスピードを考慮するとできるだけ分けず1ファイルにまとめたいものですよね。

なので私は可読性・メンテナンス性を高めるためにパーツやレイアウトに分けて以下のように管理しています。

ヘッダー{
  共通スタイル
  スマフォ用のメディアクエリ{
    スタイル
  }
  PC用のメディアクエリ{
    スタイル
  }
}

フッター{
  共通スタイル
  スマフォ用のメディアクエリ{
    スタイル
  }
  PC用のメディアクエリ{
    スタイル
  }
}

メディアクエリだらけになるけどどうするの?と思いますよね。大丈夫!CSSにコンパイルする際に同じメディアクエリを一つにまとめれば解決します。
gulpのモジュールをインストール&タスクを追加するのですが、この記事の最後の方にまとめましたので参考にしてください。

import(ファイル読込)

ファイルを分けたい時はimportを使用します。読み込み用ファイルは_(アンダースコア)を頭に付与すれば、CSSにコンパイルされません。

ちなみに以下は私がよく使う Sass(SCSS) のファイル構成です。SMACSS(※) の考え方を一部拝借しています。ページごとの特有のスタイルがある場合は、_page.scss なども付け足します。JSなどによって状態が変わるようなスタイルが必要な場合は _state.scss なども作りますが、あまり厳格にやりすぎると辛いので現時点ではこんな感じが多いです。

※ SMACSSについてはCodeGridさんの説明がとてもわかりやすいです。
SMACSSによるCSSの設計

_global.scss はどのサイトでも頻繁に使うおきまりの設定をまとめて入れてあります。

scss/
  ┣ main.scss
  ┗ components/
      ┣ _mixin.scss mixinや変数
      ┣ _reset.scss リセット系
      ┣ _base.scss htmlなど要素に直接
      ┣ _global.scss 頻繁に使う設定
      ┣ _layout.scss header、mainエリアなどエリアごとのスタイル設定
      ┗ _module.scss 一覧やテーブルなどの部品類

main.scss に components/ 内のファイルを読み込んで一個にまとめます。_(アンダースコア)、.scss(拡張子)は不要です。

[code title=”SCSS”]@charset “UTF-8”;
@import “conponents/mixin”,
  “components/reset”,
  “components/base”,
  “components/global”,
  “components/layout”,
  “components/module”;[/code]

余談ですが、例えば_module.scss(記事の一覧など使い回すパーツ)に書くスタイルにはmd-の接頭辞(moduleの略)をつけて管理してます。このパーツはmodule(記事の一覧など使い回すパーツ)で、スタイルの設定は_module.scssにあることが一目瞭然です。

スタイルの記述が増えすぎてしまう時は別フォルダなどを作って、さらにファイルを小分けにして管理することもあります。

[code title=”HTML”]<ul class=”md-archive”>
  <li class=”md-archive_item”>最新の記事 1</li>
  <li class=”md-archive_item”>最新の記事 2</li>
</li>[/code]

コメント

コメントの記述方法です。
ライセンス関係のコメントが必要な時は!をつけておけば圧縮しても削除されません。

[code title=”HTML”]// 一行コメント

/*
* 複数行コメント
*/

/*!
* 削除されないコメント
*/[/code]

入れ子(ネスト)

結構何でもネストできます。

[code title=”SCSS/CSS”]//Sass(SCSS)
.md-table {
  color: #666;
  .heading{
    color: #fff;
    background: #666;
    font-weight: bold;
  }
}

//CSS
.md-table {
  color: #666;
}
.md-table .heading {
  color: #fff;
  background: #666;
}[/code]

&でつなぐと次のようなこともできます。
[code title=”SCSS/CSS”]//Sass(SCSS)
.md-heading{
  &_1{
    font-size: 3rem;
  }
  &_2{
    font-size: 2rem;
  }
}

//CSS
.md-heading_1 {
  font-size: 3rem;
}

.md-heading_2 {
  font-size: 2rem;
}[/code]

メディアクエリごとネストして入れてしまえば、パーツのスタイルごとに管理できメンテナンス性も上がります。

[code title=”SCSS/CSS”]//Sass(SCSS)
.md-archive {
  @media screen and (min-width:768px){
    &_item{
      width: 50%;
    }
  }//SP
  @mediascreen and (max-width:768px){
    display: flex;
    flex-wrap: wrap;
    &_item{
      width: 25%;
    }
  }//PC
}//.md-archive

//CSS
@media screen and (min-width: 768px) {
  .md-archive_item {
    width: 50%;
  }
}
@media screen and (max-width: 768px) {
  .md-archive {
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -ms-flex-wrap: wrap;
    flex-wrap: wrap;
  }
  .md-archive_item {
    width: 25%;
  }
}[/code]

ネストしていくと.md-archiveと.md-archive_itemと要素の親子関係もわかりやすいですし、 それぞれ独立して色のでスタイルも汚染されにくくなります。

注意点としてはあまりネストが深くなりすぎないようにしましょう。

変数

Sass(SCSS)は変数が使えて便利です。変数に入れておくとカラーの変更があった場合などに助かります。

[code title=”SCSS/CSS”]//Sass(SCSS)
$font-color: #333;
html{
  color: $font-color;
}

//CSS
html {
  color: #333;
}[/code]

クラス名などのように文字列として利用する時は#{}を使います。

[code title=”SCSS/CSS”]//Sass(SCSS)
$class: icon;
.md-#{$class} {
  color: #333;
}

//CSS
.md-icon {
  color: #333;
}[/code]

!defaultで変数のデフォルト値を決めることができます。
pタグはデフォルト値に戻ります。

[code title=”SCSS/CSS”]//Sass(SCSS)
$color: #333 !default;
html {
  $color: #666;
  color: $color;
}
p {
  color: $color;
}

//CSS
html {
  color: #666;
}
p {
  color: #333;
}[/code]

if(条件分岐)

ifはあまり使いどころはないですが、こんな感じに使えます。

[code title=”SCSS/CSS”]//Sass(SCSS)
@mixin p($type){
  p {
    @if $type == true{
      color: red;
    } @else {
      color: black;
    }
  }
}
@include p(true);
@include p(false);

//CSS
p {
  color: red;
}
p {
  color: black;
}[/code]

for/while(繰り返し処理)

for/whileを使うと繰り返し処理ができます。

[code title=”SCSS/CSS”]//Sass(SCSS)
//for
@for $i from 1 through 3 {
  .icon_#{$i} { width: 20px * $i; }
}

//while
$i: 1;
@while $i <= 3 {
  .icon_#{$i} { width: 20px * $i; }
  $i: $i + 1;
}

//CSS
.icon_1 {
  width: 20px;
}
.icon_2 {
  width: 40px;
}
.icon_3 {
  width: 60px;
}[/code]

each

each文も使えます。in以降のカンマ区切りが配列で下の例であれば$colorに代入されます。

[code title=”SCSS/CSS”]//Sass(SCSS)
@each $color in blue, red, pink, yellow {
  .bg-#{$color} {
    background: $color;
  }
}

//CSS
.bg-blue {
  background: blue;
}
.bg-red {
  background: red;
}
.bg-pink {
  background: pink;
}
.bg-yellow {
  background: yellow;
}[/code]

配列のkeyとvalueを利用したようなこんな書き方もできます。

[code title=”SCSS/CSS”]//Sass(SCSS)
$colors: ( blue: #4673C7, red: #DB0707, pink: #C77FA9, yellow: #E5B900);
@each $color, $code in $colors {
  .bg-#{$color} {
    background: $color-cord;
  }
}

//CSS
.bg-blue {
  background: #4673C7;
}
.bg-red {
  background: #DB0707;
}
.bg-pink {
  background: #C77FA9;
}
.bg-yellow {
  background: #E5B900;
}[/code]

mixin/include

いわゆる関数のようなもので使い回しが効きます。@includeで呼び出せます。引数も使えて便利です。

[code title=”SCSS/CSS”]//Sass(SCSS)
@mixin h1{
  h1{
    font-size: 3rem;
  }
}

//CSS
h1{
  font-size: 3rem;
}[/code]

引数を使う場合はこんな感じです。

[code title=”SCSS/CSS”]//Sass(SCSS)
@mixin fontAwesome($num){
  content: $num;
  font-family: fontAwesome;
}
li{
  ::before{
    @include fontAwesome(‘\f105’);
  }
}

//CSS
li::before{
  content: ‘\f105’; font-family: fontAwesome;
}[/code]

extend(継承)

クラスの継承ができます。

[code title=”SCSS/CSS”]//Sass(SCSS)
.md-button{
  border-radius: 15px;
  width: 280px;
  padding: 10px;
  background: #8B8B8B;
  color: #fff;
  &:hover{
    opacity: .7;
  }
}
.md-button_orange{
  @extend .md-button;
  background: #E56100;
}

//CSS
.md-button, .md-button_orange {
  border-radius: 15px;
  width: 280px;
  padding: 10px;
  background: #8B8B8B;
  color: #fff;
}
.md-button:hover, .md-button_orange:hover {
  opacity: .7;
}
.md-button_orange {
  background: #E56100;
}[/code]

おまけ:メディアクエリを圧縮するモジュール

npmモジュールを入れてメディアクエリをまとめます。gulpでSass(SCSS)をコンパイルする方法がわからない方はコピペで始めるgulp入門(2):Sass(SCSS)導入編・前編をご覧ください。

[code title=”コマンド”]$ npm install gulp-combine-media-queries –save-dev[/code]

このモジュール残念なことに、このままgulp走らせたらコンパイル途中でコケます。モジュールがインストールできたら node_modules/gulp-combine-media-queries/index.jsの152行目をコメントアウトします。

[code title=”JS”]// file.contents = new Buffer(cssJson);[/code]

gulpfile.jsにメディアクエリをまとめるためのタスクを追加します。sassのタスクに追加すると圧縮とかうまくいかないことがあるので、別途タスクを作ります。

[code title=”JS”]const cmq = require(‘gulp-combine-media-queries’)

//css
gulp.task(‘css’, () => {
  gulp.src(dev.css + ‘*.css’)
  .pipe(sourcemaps.init()) //map生成
  .pipe(plumber())
  .pipe(cmq({
    log: false
  }))
  .pipe(gulp.dest(dest.css))
})

gulp.task(‘default’, [‘sass’, ‘css’, ‘browser-sync’], () => {
  gulp.watch(dev.scss, [‘sass’])
  gulp.watch(dev.scss).on(‘change’, browserSync.reload)
  gulp.watch(dest.css + ‘/*.css’, [‘css’])
})[/code]

まとめ

いかがでしたでしょうか?使いこなせばSass(SCSS)は相当便利ですね!
次回はもっとパーツを使って実践的な実例をご紹介します。