サーバサイドエンジニアのためのフロントエンド入門 〜Sass編〜

f:id:Naotsugu:20160627231549p:plain

フロントエンドの移り変わりが激しすぎてついていけない。 というサーバサイドエンジニア向けのフロントエンドの概要第2回目です。 より深い話題については他を当たってください。。

前回までで、node と gulp を導入しました。

blog1.mammb.com

今回は gulp を使って Saas のコンパイルをしていきましょう。


Sass とは

CSS は少し大きくなるとメンテナンスが困難になってきます。

そこでCSSに似た、より高度な文法で記載したファイルをコンパイルしてCSSを生成することが行われるようになってきました。

一般によく使われているのが Sass と less になります。 最近では bootstrap4 が Sass に移行したりと、Sass の利用が多くなっています(bootstrap5 では PostCSS 使うという話もありますが)。

Sass(Syntactically Awesome StyleSheet) は .sass.scss の2種類の文法で書けますが、.scss が主流です(.sass はインデントで階層を表し、セミコロン無しの構文となります)。

.scss は CSS3 の上位互換の文法で、プレーンな CSS も .scss として扱えます。

Sass を使うとどんなことができるのかというと、主に以下の点が上げられます。

  • 変数を扱えるためプロパティ値の再利用ができる
  • 長いセレクタはネストとして簡素に定義できる
  • ミックスインでスタイルコードが再利用できる
  • セレクタの継承が行えプロパティの重複を排除できる
  • 四則演算や制御構文も使える

scss の文法

基本的な scss (Sassy CSS) の文法を見てみましょう。

ネスト

以下のような CSS は、

ul.nav { float: right; }
ul.nav li { float: left; }
ul.nav li a { color: #111; }
ul.nav li.current { font-weight: bold; }

Sass ではセレクタをネストさせて、以下のように書くことができます。

ul.nav {
    float: right;
    li {
        float: left;
        a {
            color: #111;
        }
        &.current {
            font-weight: bold;
        }
    }
}

&.current& は親セレクタで、li.current のように展開されます。


変数

$ で変数を定義できます。

// 変数定義
$width: 100px;

#main {
  width: $width/2;
}

また、/* */ によるコメントに加え // で行コメントが書けます。

さらに四則演算もでき、この例では2で割った値を設定しています。color: #010203 + #040506; のようにカラーの演算もできます。

#{} にて変数による置換もできます。

$name: foo;
$attr: border;
p.#{$name} {
    #{$attr}-color: blue;
}

p.foo { border-color: blue; } として展開されます。

例えば、bootstrap4 の _variables.scss でカラー定義は以下の様に変数定義されています。

$brand-primary:             #0275d8 !default;
$brand-success:             #5cb85c !default;
$brand-info:                #5bc0de !default;
$brand-warning:             #f0ad4e !default;
$brand-danger:              #d9534f !default;

これを変更することで、ボタンの配色など、一括して変更できるようになっています。


ミックスイン

共通のルールを再利用するには @mixin が使えます。 @mixin で共通ルールを定義し、@include ディレクティブで共通ルールを適用します。

@mixin horizontal-list {
  li {
    float: left;
    margin-right: 10px;
  }
}

#header ul.nav {
  @include horizontal-list;
  float: right;
}

#footer ul.nav {
  @include horizontal-list;
  margin-top: 1em;  
}

ミックスインはパラメータを取ることができます。

/* デフォルト 10px */
@mixin horizontal-list($spacing: 10px) {
  li {
    float: left;
    margin-right: $spacing;
  }
}

#header ul.nav {
  @include horizontal-list; /* デフォルトを利用 */
  float: right;
}

#footer ul.nav {
  @include horizontal-list(20px);
  margin-top: 1em;  
}

ルールの再利用には @extend を利用したルールの継承も可能です。 @extend は CSS プロパティを重複させることなく、あるセレクタに他のセレクタの全てのスタイルを継承させることができます。 ルールが本当に継承関係となっている場合にのみ使うべきで、使い方が難しい部分があります。ここでは説明を省略します。

Sass プラグインをインストールする

gulp で Sass コンパイルを行うには gulp-sass プラグインを使います。 他にも gulp-ruby-sass プラグインなど色々ありますが、gulp-sass プラグインの方が処理が早いのでおすすめです。

前回と同じようにインストールしていきます。

$ npm install gulp-sass --save-dev

package.jsongulp-sass の依存が追記されます。

{
  // ・・・
  "devDependencies": {
    "gulp": "^3.9.1",
    "gulp-sass": "^2.2.0"
  }
}

scss をコンパイルする

gulp-sass プラグインを使ったコンパイルタスクを gulpfile.js に定義します。

var gulp = require('gulp');
var sass = require('gulp-sass');

var paths = {
  'scss': './src/app/scss/',
  'css' : './src/app/css/'
}

gulp.task('sass', function () {
  return gulp.src(paths.scss + '**/*.scss')
    .pipe(sass().on('error', sass.logError))
    .pipe(gulp.dest(paths.css));
});

gulp では gulp.src() でストリームを取得し、pipe() で処理をつなげていくことでタスクを定義します。

コンパイル対象の style.scss を作成ましょう。

#main p {
  color: #00ff00;
  width: 97%;

  .redbox {
    background-color: #ff0000;
    color: #000000;
  }
}

ここでのフォルダ構成は以下のようになります。

.
├─ gulpfile.js
├─ package.json
└─ src
    └─ app
        ├─ css
        └─ scss
            └─ style.scss

gulp タスクを実行してみましょう。

$ ./node_modules/.bin/gulp sass
[00:00:00] Using gulpfile ~/XXXXX/example-gulp/gulpfile.js
[00:00:00] Starting 'sass'...
[00:00:00] Finished 'sass' after 33 ms

src/app/css/style.css にコンパイルされた CSS が出力されます。

#main p {
  color: #00ff00;
  width: 97%; }
  #main p .redbox {
    background-color: #ff0000;
    color: #000000; }

Autoprefixer でベンダープレフィックスを自動化する

ベンダープレフィックスを調べながら CSS 書いていく作業はかなり煩雑な作業です。

Autoprefixer を使えば CSS のベンダープレフィックス(-webkit-XXX)を自動調整してくれます。

早速インストールしてみましょう。

$ npm install gulp-autoprefixer --save-dev

gulpfile.js に autoprefixer の処理を追加します。

var gulp = require('gulp');
var sass = require('gulp-sass');
var autoprefixer = require('gulp-autoprefixer');

var paths = {
  'scss': './src/app/scss/',
  'css' : './src/app/css/'
}

gulp.task('sass', function () {
  return gulp.src(paths.scss + '**/*.scss')
    .pipe(sass().on('error', sass.logError))
    .pipe(autoprefixer({browsers: ['last 3 versions']}))
    .pipe(gulp.dest(paths.css));
});

gulp ではストリームとして処理を重ねていけば良いので、sass() の処理の後に autoprefixer() の処理を追加すれば良いです。

この例では、最新から3バージョン前のブラウザをサポートする設定としています。

> 5% のようにブラウザシェアで指定したり、'ie 8', 'ios 4', 'android 2.3' のように個別で指定したりできます。

以下のような CSS があった場合、

.example {
    display: flex;
    user-select: none;
}

sass タスクの実行で、

$ ./node_modules/.bin/gulp sass
[00:00:00] Using gulpfile ~/XXXX/example-gulp/gulpfile.js
[00:00:00] Starting 'sass'...
[00:00:00] Finished 'sass' after 109 ms

以下のような CSS が出力されます。

.example {
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  -webkit-user-select: none;
     -moz-user-select: none;
      -ms-user-select: none;
          user-select: none; }

まとめ

今回は、gulp タスクを定義して Sass によるCSSのビルド処理を見てきました。

次回は js ファイルのビルドについて見ていきます。

blog1.mammb.com