nuxt.svg

【Nuxt 2】Sassの導入

Nuxt2

Sass とは

Sass とは、Syntactically Awesome Style Sheets の略で、直訳すると「文法的に素晴らしいスタイルシート」という意味になります。 この言葉の通り、変数やミックスインなど通常の CSS より高度な機能が提供されます。

また構文も通常の CSS とは異なり、コンポーネントを作成する上ではこれだけでも十分有用な機能になります。

Sass についてはこれから説明をしますが、こちらのサイトで Sass の動作が確認できるので参考にしてください。

SCSS と SASS

Sass には SCSS と SASS という 2 つの記法があります。

SCSS は、通常の CSS と同様{}を使ってスタイルを定義します。

SCSS
.content {
  background: white;
  color: black;
}

SASS は、{}を使わずインデントによってスタイルを定義します。 また末尾のセミコロンは不要になります。

SASS
.content
  background: white
  color: black

どちらが良いかは一概には言えませんが、この記事では SCSS で説明していきます。

基本構文

ネスティング

Sass では、セレクターの親子関係をネストによって表現できます。 例えば以下のスタイルを定義したいとします。

CSS
ul {
  list-style: none;
}
ul li {
  padding: 3px 6px;
}
ul li > a {
  display: block;
  text-decoration: none;
}

これを Sass で表現すると以下のようになります。

SCSS
ul {
  list-style: none;
  li {
    padding: 3px 6px;
    > a {
      display: block;
      text-decoration: none;
    }
  }
}

ただし、ネストが深くなりすぎるとわかりにくいコードとなってしまうため注意が必要です。 スタイルの優先順位を考慮し、無駄なネストは避けるべきです。

NuxtJS ではコンポーネント単位で設定できるので、普通であればそれほど深いネストにはならないと思います。

アンパサンド

アンパサンド(&)は、自身のセレクターとの連結を意味します。 例えば以下のように:hoverのスタイルを定義したいとします。

CSS
.button {
  transition: opacity 0.4s;
}
.button:hover {
  opacity: 0.6;
}

これを Sass で表現すると以下のようになります。

SCSS
.button {
  transition: opacity 0.4s;
  &:hover {
    opacity: 0.6;
  }
}

また以下のようにクラス名の連結が可能です。 これは後に説明する BEM を意識した記述となっています。

CSS
.list {
  list-style: none;
}
.list__item {
  padding: 3px 6px;
}
SCSS
.list {
  list-style: none;
  &__item {
    padding: 3px 6px;
  }
}

スタイルのグループ化

paddingmarginは、toprightbottomleftのそれぞれの余白を設定できますが、 すべての値を設定する必要があります。

例えばtoprightだけ余白を設定したい場合は次のようにしなければなりません。

CSS
/* 以下のどちらか */
.elm1 {
  padding: 10px 10px 0 0;
}
.elm2 {
  padding-top: 10px;
  padding-right: 10px;
}

これを Sass では以下のように表現することができます。

SCSS
.elm1 {
  padding: {
    top: 10px;
    left: 10px;
  }
}

その他bordertransitionなど、ハイフン(-)でプロパティが区切られているものは、上記のようにグループ化できます。

プレースホルダーセレクター

プレースホルダーセレクターとは、スタイルを共通化することが目的の機能です。 %で共通のスタイルを定義し、@extendで適用します。 以下の例を見てください。

SCSS
/* 共通スタイルの定義 */
%common-style {
  padding: 10px;
  margin: 5px;
  border: 1px solid black;
}

.elm1 {
  color: red;
  @extend %common-style;  /* 共通スタイルの適用 */
}

.elm2 {
  color: blue;
  @extend %common-style;  /* 共通スタイルの適用 */
}

これは CSS だと以下のようになります。

CSS
.elm1, .elm2 {
  padding: 10px;
  margin: 5px;
  border: 1px solid black;
}

.elm1 {
  color: red;
}

.elm2 {
  color: blue;
}

変数

Sass では、$によって変数を定義することができます。

SCSS
/* 変数定義 */
$bg-color: white;
$fnt-color: black;
$height: 200;

/* 変数の使用 */
.content: {
  background: $bg-color;
  color: $fnt-color;
  height: #{$height}px;
}

#{変数}とすることで値として展開することができます。

Sass の変数は、JavaScript などの言語と同様にスコープという概念があります。 例えば以下のように変数を定義したとします。

SCSS
.content {
  $color: 'blue';
  .child1 {
    color: $color;
  }
  .child2 {
    color: $color;
  }
}

$colorは、.content内でのみ使用できる変数となります。 その他で使用した場合はエラーとなります。

このように、セレクター外で宣言した変数はどこでも使用できるグローバル変数となり、 セレクター内に宣言した変数はそのセレクターでしか使用できないローカル変数となります。

同じ名前の変数を定義した場合は、上書きされてしまうため注意してください。

関数

@functionを使用することで、関数を定義することができます。 考え方は他の言語と同じで、引数と戻り値を設定します。 戻り値は@returnで設定します。

SCSS
@function double($val) {
  @return $val * 2;
}

.content {
  width: #{ double(100) }px;  /* 200px */
}

ミックスイン

ミックスインとは、共通のスタイルを定義する目的で使用します。 プレースホルダーセレクターと似ていますが、引数としてデータを受け取ることができる点が大きく違います。

ミックスインの定義は@mixinで行い、@includeで呼び出します。

SCSS
/* ミックスの定義 */
@mixin common-style($border-color) {
  padding: 10px;
  margin: 5px;
  border: 1px solid $border-color;
}

.elm1 {
  color: red;
  @include common-style(red);  /* ミックスインの呼び出し */
}

.elm2 {
  color: blue;
  @include common-style(blur);  /* ミックスインの呼び出し */
}
CSS
.elm1 {
  color: red;
  padding: 10px;
  margin: 5px;
  border: 1px solid red;
}

.elm2 {
  color: blue;
  padding: 10px;
  margin: 5px;
  border: 1px solid blue;
}

制御構文

@if, @else

@if@elseで条件分岐を行うことができます。

SCSS
@function font-color($darken) {
  @if $darken {
    @return 'white';
  } @else {
    @return 'black';
  }
}

.content {
  color: font-color(true);  /* white */
}

@for

@forは、指定した回数のループ処理を行います。

SCSS
@for $i from 1 through 3 {
  .elm-#{ $i } {
    width: #{ 100 * $i }px;
  }
}
CSS
.elm-1 {
  width: 100px;
}

.elm-2 {
  width: 200px;
}

.elm-3 {
  width: 300px;
}

@while

@whileは、指定した条件を満たす間ループ処理を行います。 以下は、@forと同じ結果になります。

SCSS
$val: 3;
@while $val > 0 {
  .elm-#{ $val } {
    width: #{ 100 * $val }px;
  }
  $val: $val - 1;
}

@each

@eachは、配列の要素分のループ処理を行います。 配列はカンマ区切りで定義することができます。

SCSS
$colors: black, red, blue;

@each $color in $colors {
  .bg-#{ $color } {
    background: $color;
  }
}
CSS
.bg-black {
  background: black;
}

.bg-red {
  background: red;
}

.bg-blue {
  background: blue;
}

また、以下のようにキーと値を持つマップを定義し、使用することもできます。

$colors: (
  black: #363636,
  red: #c0392b,
  blue: #3498db,
);

@each $key, $val in $colors {
  .bg-#{ $key } {
    background: $val;
  }
}
CSS
.bg-black {
  background: #363636;
}

.bg-red {
  background: #c0392b;
}

.bg-blue {
  background: #3498db;
}

Sass ファイルの読み込み

@import

Sass ファイルを読み込むには、@importを使用します。 注意点として、読み込むファイルの名前の先頭にはアンダーバー(_)を付ける必要があります。

_reset.scssを読み込む場合は以下のようにします。

SCSS
@import 'reset';

@use, @forward

@importに代わる新たなファイル読み込みとして、@use@forwardがあります。 しかし、今回 NuxtJS に導入する Sass では利用できないため、説明は割愛します。

BEM

BEM とは、Block、Element、Modifier(修飾子)の 3 つの要素で class の命名を行う設計手法です。 これが Sass と相性が良く、また NuxtJs などのコンポーネントの作成にも役立ちます。

Block は 1 つのかたまりのことです。 NuxtJS ではコンポーネントのルート要素だと考えてください。 Element は Block、つまりコンポーネントを構成する要素になります。 Modifier は、Element の状態を表します。

これら 3 つの要素を組み合わせて、Block__Element--Modifierとなるようにクラスを命名します。 それぞれの要素の命名はケバブケース(ハイフン区切り)で行います。

簡単ですが、以下がメニューを構成した例です。

HTML
<ul class="menu">
  <li class="menu__item">Menu1</li>
  <li class="menu__item menu__item--active">Menu2</li>
  <li class="menu__item">Menu3</li>
</ul>
SCSS
.menu {
  display: flex;
  &__item {
    line-height: 40px;
    text-align: center;
    flex: 1;
    &--active {
      color: blue;
      font-weight: bold;
    }
  }
}

NuxtJS への導入

インストール

NuxtJS で Sass を導入するには、sass-loadernode-sassをインストールします。

$ npm install sass-loader node-sass

読み込み

Sass ファイルは/assetsフォルダに配備し、nuxt.config.jscssに指定します。

nuxt.config.js
export default {
  css: ['~/assets/style.scss']
}

単一ファイルコンポーネントで Sass を使用するには、<style>langで指定します。 SCSS であればscss、SASS であればsassを指定します。

<style lang="scss"></style>