Skip to content

Instantly share code, notes, and snippets.

@manabuyasuda
Last active July 19, 2016 15:14
Show Gist options
  • Save manabuyasuda/eaaf0fa8f86139cc0284552ea343ad3a to your computer and use it in GitHub Desktop.
Save manabuyasuda/eaaf0fa8f86139cc0284552ea343ad3a to your computer and use it in GitHub Desktop.

Sassのベターな使い方


目次

  • .sassより.scss
  • 変数で変更をしやすく
  • パーシャルと@importでモジュールごとにファイルを管理する
  • よく使うスタイルはデフォルトで置いておく
  • CSSの構成案を導入する
  • ネストは最小限に、検索しやすく
  • ブレイクポイントはMapと@mixinで管理する
  • レスポンシブに対応したクラスをつくる@mixin

.sassより.scss


Sassはインデントで階層構造を示すSASS記法とCSSに近いSCSS記法の2つがあります。SASS記法はブレース(波括弧)とセミコロンを省略できるのでコードが簡潔になりますが、SCSS記法を使いましょう。


// SASS記法
a
  color: blue
  text-decoration: none
  &:hover
    color: red
// SCSS記法
a {
  color: blue
  text-decoration: none
  &:hover {
    color: red
  }
}

インデントで構造を示す言語は使い慣れないと拒否反応が起きやすいです。SCSS記法はCSSの記法とほとんど同じなので、普通に読むことができると思います。


また、SCSS記法はCSSのコードをそのまま貼付けても動作します。SASS記法だと書き直す必要があります。そのうえ、BootstrapのようなCSSフレームワークや、jQueryのプラグインなどでも、SCSS記法のほうがよく使われています。


変数で変更をしやすく


CSSには変数という機能を現段階で使用することはできません。「CSS Custom Properties」という機能も現段階ではChromeやFirefoxの最新版以外は対応していません。


ですが、CSSプリプロセッサー(CSSを作るためのツール)のひとつであるSassなら変数の機能を使用することができます。

以下の例ではブランドカラーを定義する変数$color-brandと要素間のマージンのベースになる変数$base-spacingをそれぞれ2回ずつ指定しています。


$color-brand: red !default;
$base-spacing: 1.7rem !default;

.heading {
  margin-bottom: $base-spacing;
  font-size: 2rem;
  color: $color-brand;
}

.box {
  margin-bottom: $base-spacing;
  padding: 1em;
  color: $color-brand;
}

変数を利用しないと、たった1つの共通パーツのデザイン変更で何箇所も変更しなければいけませんが、変数を使えば1箇所変更するだけで、すべての箇所を変更することができます。

// 値をredからblueに変更
$color-brand: blue !default;

// もしくは、変数を定義したファイル箇所より前に同じ変数名で定義
$color-brand: blue !default;
$color-brand: red !default;

パーシャルと@importでモジュールごとにファイルを管理する


Sassのファイル名は通常、module.scssのようにつけますが、_module.scssのように先頭にアンダースコアをつけると、そのファイルはコンパイル(CSSとして出力)をしてもCSSファイルとして個別に出力されなくなります。この機能をパーシャル(partial)と呼びます。


アンダースコアのついたSassファイルは、@importを使用することで、アンダースコアのついていないSassファイルの中で呼び出すことができます。

// style.scssのなかの記述

// 同じ階層にある_module.scssをインポートする
@import "_module1.scss";
@import "_module2.scss";

// 使用しないファイルはSassのコメントをつける
@import "_module1.scss";
// @import "_module2.scss";

HTMLに複数のCSSファイルを読み込みたい場合はHTML側でインポートしていましたが、CSSファイルを出力する段階ですることができます。Sassでは機能ごとにファイルを分割するのが基本です。


よく使うスタイルはデフォルトで置いておく


パーシャルと@importで、どのファイルを出力するかを管理できるようになったので、よく使うスタイルをまとめたファイルをつくりましょう。例えば、font-familyやグリッドレイアウトなど。


// よく使うfont-familyをまとめています。
$font-sans-serif-1: "Helvetica Neue", Helvetica, "Hiragino Sans", "Hiragino Kaku Gothic ProN", Meiryo, sans-serif;
$font-sans-serif-2: "Helvetica Neue", Helvetica, "游ゴシック", YuGothic, "Hiragino Sans", "Hiragino Kaku Gothic ProN", Meiryo, sans-serif;
$font-serif-1: "Times New Roman", "Hiragino Mincho ProN", "HG明朝E", Meiryo, serif;
$font-serif-2: "Times New Roman", "游明朝", "YuMincho", "Hiragino Mincho ProN", "HG明朝E", Meiryo, serif;

// グリッドレイアウトのベーススタイルです。
.c-grid {
  display: block;
  margin: 0;
  padding: 0;
  font-size: 0;
  list-style-type: none;
}

.c-grid__item {
  display: inline-block;
  width: 100%;
  font-size: 1rem;
  vertical-align: top;
}

CSSの構成案を導入する


ここまででファイルを作って、管理することができるようになりました。_font.scssや_grid.scssのようなファイルが散乱していませんか?ここでファイルを整理するためのルールをつくりましょう。

いちから作るより、FLOCCSITCSSSMACSSのような構成案をベースにしましょう。


個人的にはFLOCSSをベースするのがいいと考えています。FLOCSSの発案者が日本人の谷 拓樹さん(hiloki)なので、ドキュメントが日本語なこと、CSSに関するスライドをたくさんあげているので参考資料が多いことがおもな理由です。


CSS構成案をひととおり理解できていれば、どの構成案を使っても大きくは変わらないんじゃないかという印象です。どれも、影響範囲と詳細度を管理するためのツールです。


以下は僕が主に使っているディレクトリです。

  1. Foundation
  2. function
  3. variable
  4. mixin
  5. vendor(Normalize.css)
  6. base(プロジェクトにおける、基本的なベーススタイル)
  7. Layout(ヘッダーやフッターのような、ページを構成するコンテナブロック)
  8. Object(プロジェクトにおけるビジュアルパターン)
  9. component(多くのプロジェクトで横断的に再利用のできるような、小さな単位のモジュール)
  10. project(プロジェクト固有のパターンで、コンテンツを構成する要素)
  11. utility(いわゆる汎用クラスで、ほとんどの場合は単一のスタイル)

ネストは最小限に、検索しやすく


Sassはネストで親子関係などを示すことができるので、コーディングを楽にすることができます。

// Sass
.foo {
  .bar {
    color: red;
  }
}

.foo {
  &-bar {
    color: red;
  }
}

.foo {
  &:before {
    content: "";
  }
}
/* CSS */
.foo .bar {
  color: red;
}

.foo-bar {
  color: red;
}

.foo:before {
  content: "";
}

ですがネストには1つデメリットがあります。それは検索しにくい(またはできない)ことです。

デザイナーから「.foo-barを赤から青に変更してね」と言われました。Sassファイルで.foo-barを検索します。けれど検索には出てきません、.foo-barとはSassファイルで指定していないからです。

.foo {
  &-bar {
    color: red;
  }
}

また、ネストが深くなると、今どのセレクタを参照しているのかが分かりにくくなります。

.foo {
  &-bar {
    ...
    ...
    ...
    ...
    ...
    ...
  }
  &-baz {
    ...
    ...
    ...
    ...
    ...
    ...
  }
}

早く書けることや、中にローカル変数を定義できることなど、ネストのメリットはありますが、変更するときに効率が落ちてしまわないかを考えてネストを使いましょう。

個人的には検索に影響が出にくい、疑似要素や疑似クラス、.is-activeのようなステートクラス、メディアクエリに使用を制限しています。


ブレイクポイントはMapで管理する


レスポンシブWebデザインではメディアクエリを使用して、ブレイクポイントを指定することがよくあります。そこでブレイクポイントを変数化して使用する方法があります。

$md: "screen and (min-width: 768px)";

// ブレイクポイントの変数をインターポレーション(`#{}`)でコンパイルできるようにする
@media #{$md} {
  .foo {
   width: 50%; 
  }
} 

定義している値は変わりませんが、Mapというデータ型を使用するほうが柔軟に利用することができます。

$breakpoints: (
  'sm': 'screen and (min-width: 400px)',
  'md': 'screen and (min-width: 768px)',
  'lg': 'screen and (min-width: 1000px)',
  'xl': 'screen and (min-width: 1200px)',
) !default;

レスポンシブに対応したクラスをつくる@mixin


先ほど定義したMap型の変数を@mixinで呼び出してメディアクエリを使用します。

map-get()でMap型の値('screen and (min-width: 400px)'の部分)を取得しています。

$breakpoints: (
  'sm': 'screen and (min-width: 400px)',
  'md': 'screen and (min-width: 768px)',
  'lg': 'screen and (min-width: 1000px)',
  'xl': 'screen and (min-width: 1200px)',
) !default;

@mixin mq($breakpoint) {
  @if map-has-key($breakpoints, $breakpoint) {
    @media #{inspect(map-get($breakpoints, $breakpoint))} {
      @content;
    }
  } @else {
    @warn "Unfortunately, no value could be retrieved from `#{$breakpoint}`. "
    + "Please make sure it is defined in `$breakpoints` map.";
  }
}

@includeで@mixinを使用すると、.fooはこのように出力されます。

// Sass
.foo {
  @include mq(md) {
    width: 50%;
  }
}

/* CSS */
@media screen and (min-width: 768px) {
  .foo {
    width: 50%;
  }
}

Map型の変数を使用すると、これ以外にもレスポンシブに対応したクラスを生成できます。

レスポンシブに対応した表示を切り替えるクラスが欲しい。

@mixin responsive($class, $bp: $breakpoints) {
  #{$class} {
    @content;
  }
  @each $suffix, $value in $bp {
    @media #{$value} {
      #{$class}-#{$suffix} {
        @content;
      }
    }
  }
}

// Sass
@include responsive(".u-dn") {
  display: none !important;
}

/* CSS */
.u-dn {
  display: none !important;
}

@media screen and (min-width: 400px) {
  .u-dn-sm {
    display: none !important;
  }
}

@media screen and (min-width: 768px) {
  .u-dn-md {
    display: none !important;
  }
}

@media screen and (min-width: 1000px) {
  .u-dn-lg {
    display: none !important;
  }
}

@media screen and (min-width: 1200px) {
  .u-dn-xl {
    display: none !important;
  }
}

グリッドレイアウトで12カラムの横幅をパーセンテージで指定できるクラスが欲しい。

$width-cols: 12 !default;

@mixin width($cols, $breakpoint: null) {
  @each $col in $cols {
    @for $i from 1 through $col {
      .u-#{$i}of#{$col}#{$breakpoint} {
        width: percentage($i / $col) !important;
      }
    }
  }
}

@include width($width-cols);

// @requires - $breakpoints
@each $name, $breakpoint in $breakpoints {
  @media #{$breakpoint} {
    @include width($width-cols, -#{$name})
  }
}

/* CSS */
.u-1of12 {
  width: 8.33333% !important;
}

.u-2of12 {
  width: 16.66667% !important;
}

.u-3of12 {
  width: 25% !important;
}

/**
 * `.u-12of12`まで続く、以降もブレイクポイントを追加して繰り返される
 */

@media screen and (min-width: 400px) {
  .u-1of12-sm {
    width: 8.33333% !important;
  }
  .u-2of12-sm {
    width: 16.66667% !important;
  }
  .u-3of12-sm {
    width: 25% !important;
  }  
}

まとめ


  • 変数で変更をしやすく
  • パーシャルと@importでモジュールごとにファイルを管理する
  • よく使うスタイルはデフォルトで置いておく
  • CSSの構成案を導入する
  • ネストは最小限に、検索しやすく
  • ブレイクポイントはMapと@mixinで管理する
  • レスポンシブに対応したクラスをつくる@mixin

SassはCSSを楽に早く書くために使用せず、CSSを管理しやすくするために使用しましょう。紙とペンでメモをとるときに、あとで読み返せなかったら意味がないですよね?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment