2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ちょっとがんばるWebサイト開発 on Webpack5 - Sass(SCSS)を導入してWebデザインの開発環境を強化する

Last updated at Posted at 2023-03-08

前書き

本記事のゴール

この記事では、Sass (SCSS) を導入してWebデザインの開発環境を強化するための方法を理解することを目指します。

この記事で解説する内容

  • Sassの概要について説明します
  • Sass (SCSS)をプロジェクトに導入する方法について説明します
  • Sass (SCSS)を利用した簡単な例を紹介します

この記事で解説しない内容

  • Sassの詳細な文法については説明しません

[参考] Sass関連記事

シリーズ記事

この記事はシリーズ 「ちょっとがんばるWebサイト開発 on Webpack5」 の記事です。
シリーズ全体の概要は 以下のリンク先記事 にまとめられています。

この記事では Webpack5 (version5.X.X) を対象としています。

背景知識

Sassとは何か

Sass (Syntactically Awesome Style Sheets) はスタイルシートを記述するための言語仕様です。

Webサイト開発において最もよく用いられるスタイルシート言語は CSS (Cascading Style Sheet) だと思いますが、生のCSS言語による開発は困難が生じる場合が多くあります。そうした問題を解決し、より効率的なコーディングを可能にするという目的で作られたのがSassです。

Sassでは、CSS言語の機能を内包しつつ、CSS言語にはない便利な構文や機能を提供しています。例えば、Sassではネストを利用して階層構造を表現したり、関数・ミックスイン・継承の機能等を利用して再利用性の高いコードを記述したりすることができます。一般的なプログラミング言語の構文を利用することで、より効率的にスタイルシートの開発ができるようになることが期待されます。

Sassには2種類の記法 SASSSCSS が存在します。このうち特に人気があるのがSCSS言語で、階層構造の表現方法がわかりやすくCSS言語との互換性もあるといった利点から多くの人に利用されています。そのため、この記事でもSCSS言語による実装に焦点を当てて説明していきます。

SCSS言語で実装されたファイルは、CSSファイルを生成するためのソースファイルとして利用します。SCSSで作成したスタイルシートを利用したい場合には、SCSSファイルをコンパイルした結果得られるCSSファイルを読み込むという形で利用します。

Sassを使うと何が良いのか

CSS言語によるWebデザイン実装には2つの難しさがあると考えています。

1つ目は「再利用性の低さ」です。
CSS言語はWebサイトのデザインには欠かせない言語であり、かつ学習コストもかなり小さいため、非常に多くの人が触れたことのある言語だと思います。一方で、CSS言語は文法等が単純な割に最も保守管理が困難なプログラミング言語の1つであるように思います(個人の感想です)。

一般的なプログラミング言語では、変数・関数宣言の仕組みが標準で備わっています。同一の値や処理ブロックを複数箇所で利用したい場合には変数や関数を定義しておくというのはプログラミングの定石です。また、値の意味を明示するために変数を利用するということもあるでしょう1

しかし、CSS言語には限定的な機能しか実装されていません。CSS言語にも変数宣言の仕組みはありますが、格納できる値の種類はCSSプロパティ値のみとなっています。また、関数宣言のような複数の処理をブロックにまとめて再利用する仕組みはありません2。ほとんど同一の記述を複数箇所に置くことになるため、可読性や保守性が低くなる傾向にあります。

[参考] CSSカスタムプロパティ

2つ目は「可読性の低さ」です。
Webサイトのデザインでは、CSSファイルはHTMLファイルにスタイル定義を提供する役割を担っています。スタイルの適用先であるHTMLファイルは階層的なドキュメントツリーを構成していることはご存知の通りですが、それにも関わらずCSSファイルは階層的なスタイル定義(入れ子構造を含むスタイル定義)を行うことはできません。もう少し詳細に言えば、CSS言語ではスタイル定義の際にセレクタを階層的に指定することは許されていません。

階層的なスタイル定義を行う場合には、階層を構成するすべてのセレクタをすべて並べて要素群を指定する必要があります。例えば #header ID要素配下の .logo クラス要素に対するスタイル定義を行う場合には、以下のようにセレクタを記述します。

/* `#header` ID要素配下の `.logo` クラス要素 */
#header .logo {
  /* スタイル定義 */
}

この記法では、HTMLの階層構造が深くなるにつれてセレクタ指定が大変になることが予想されます。あえてHTMLの階層構造を崩してスタイル定義を行うことになるため、可読性も高くありません。

ちなみに、CSSのセレクタでは空白1つで意味が大きく変わります。例えば上記のセレクタ指定と下記のセレクタ指定はどちらも妥当なCSSの記法ですが、意味が全く異なります。空白1つで階層を意味するCSSのセレクタが直感的かどうかは意見が分かれるような気がします。

/* `#header` ID要素かつ `.logo` クラス要素 */
#header.logo {
  /* スタイル定義 */
}

こうした課題を解決するために、これまでに様々なCSS設計方法が提案されています。有名なものをいくつか挙げると、 BEM (Block Element Modifier)OOCSS (Object-Oriented CSS) などがあります。こうしたCSS設計手法をプロジェクトに導入することで可読性や保守性の向上を期待することはできますが、それらを厳密に運用することは実践的に大変です。

[参考] CSS設計手法

Sass(SASS/SCSS) はCSSの可読性や再利用性を向上するより良いアプローチの1つです。

Sassでは変数・関数宣言やミックスインを利用することができるため、スタイル定義ブロックの再利用性を高めることができます。ほとんど同一の記述を繰り返すことも少なくなるため、コード全体の記述量を減らすことができ、可読性を高めることができます。
また、Sassでは階層的なスタイル定義を行うことが可能なため、より直感的にコーディングすることができます。階層的なセレクタ指定を行う場合でも、CSS言語のような冗長な記述を避けることができるため、コーディングの効率向上も期待することができます。

方法

サンプルコードをGitHubで公開しています。記事と併せてご覧ください。
/website/website-dev-on-webpack5/scss-on-webpack5

実装例の説明では、ファイル/フォルダパスを ルート相対パス の形式で記述しています。ここでルートはプロジェクトルートまたはWebサイトのドキュメントルートに相当します。

準備

WebpackおよびSCSS等のnpmパッケージの利用には Node.js が必要です。
インストールが未実施の場合には、以下のリンクからインストールしておいてください。

また、動作確認を行うためのNode.jsプロジェクトを作成しておきます。
適当な名前のディレクトリ(ここでは my-scss-project )を用意した上で、そのディレクトリにおいて npm init コマンドを実行することでNode.jsプロジェクトを新規作成することができます。

ターミナル
# my-scss-projectディレクトリの作成
mkdir /path/to/my-scss-project
cd /path/to/my-scss-project

# Node.jsプロジェクトの作成
npm init

npm init コマンドを実行するとプロジェクトに関する情報を入力するよう促されますが、今回は適当な設定にしておいて問題ありません。今後必要に応じて適宜変更しましょう。
コマンド実行完了後、 /package.json という設定ファイルが新規作成されていることを確認したら事前準備完了です。

手順概要

  1. npmパッケージを導入する
    SCSSからCSSを生成するのに必要なnpmパッケージ webpack webpack-cli sass sass-loader css-loader mini-css-extract-plugin をプロジェクトに追加します。

  2. Webpackの設定ファイルを記述する
    SCSSからCSSを生成する手順やルールを設定ファイル /webpack.config.js に記述します。

  3. SCSSファイルを作成する
    CSSファイルを生成するSCSSファイル /src/source.scss を作成します。

  4. SCSSファイルをコンパイルしてCSSファイルを生成する
    Webpackを実行することでSCSSファイルのコンパイルを実行し、CSSファイル /dist/target.css を生成します。

手順詳細

[手順1] npmパッケージを導入する

今回はWebpackを利用してSCSSファイルのコンパイルを行います。
まず初めに、Webpackを利用するのに必要な webpack webpack-cli パッケージをインストールします。
Webpack5(version5.X.X)をインストールするため、バージョン指定を行っています。

ターミナル
npm install --save-dev webpack@5 webpack-cli@5

次に、SCSSをコンパイルするのに必要な sass sass-loader css-loader mini-css-extract-plugin パッケージをインストールします。

ターミナル
npm install --save-dev sass sass-loader css-loader mini-css-extract-plugin

[手順2] Webpackの設定ファイルを記述する

Webpackは、適切に設定を記述することで様々な処理を実行することができます。
ここではSCSSファイル /src/source.scss をコンパイルして /dist/target.css を生成するための必要最小限のWebpack設定を以下に示します。

/webpack.config.js
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = function() {
  return {

    mode: "development",

    entry: {
      /**
       * /src/source.scss -> OUTPUT_DIRECTORY/target.css
       */
      target: path.resolve(__dirname, "src", "source.scss"),
    },

    output: {
      /**
       * OUTPUT_DIRECTORY = /dist
       */
      path: path.resolve(__dirname, "dist"),
    },

    module: {
      rules: [
        {
          test: /\.scss$/,
          use: [
            /**
             * SassLoader -> CssLoader -> MiniCssExtractPluginLoader
             */
            MiniCssExtractPlugin.loader,
            "css-loader",
            "sass-loader",
          ],
        }
      ]
    },
    
    plugins: [
      new MiniCssExtractPlugin(),
    ],

  }
}

上記設定で特に注目すべきポイントは以下の2点です。

  1. Webpackのエントリ設定箇所に、入力SCSSファイル/出力CSSファイルのパスを指定する
  2. Webpackのルール設定箇所に、拡張子 *.scss のファイルに対して3つのローダー sass-loader css-loader MiniCssExtractPlugin.loader を適用するというルールを記述する

上記のWebpack設定には同シリーズ別記事 「ちょっとがんばるWebサイト開発 on Webpack5 - CSSをコピー&ペーストする」 と共通する部分が多数あります。共通部分に関する説明として、同シリーズ別記事の説明を一部改変して引用したものを載せておきます。

1つ目のエントリ設定は、ソースCSSファイルをWebpackのビルド対象とするために必要なものです。
Webpackは、原則としてエントリ設定で指定されたファイル群とそれが依存するファイル群をビルド対象とし、そのファイル群に対して各種最適化/変換処理を行います。
entry: { target: path.resolve(__dirname, "src", "source.scss") } という設定を記述することで、ソースSCSSファイル /src/source.scss をWebpackのビルドプロセスに入力することができ、各種最適化/変換処理の結果を配信用ディレクトリに出力することができます。

2つ目のルール設定は、CSSファイルをコピー&ペーストするために必要なものです。
Webpackは、ルール設定で指定された内容に従って最適化/変換処理等を行います。
{ test: /\.scss$/ } および { use: [ MiniCssExtractPlugin.loader, "css-loader", "sass-loader" ] } という設定を記述することで、拡張子 *.scss のファイルに対して sass-loader の変換処理、 css-loader の変換処理、 MiniCssExtractPlugin.loader の変換処理をこの順で適用することができます。

同シリーズ別記事 「ちょっとがんばるWebサイト開発 on Webpack5 - CSSをコピー&ペーストする」 では、2つのプラグイン css-loader MiniCssExtractPlugin.loader を利用してCSSファイルを処理していました。この2つに加えて sass-loader プラグインを利用することで、SCSSファイルを処理することができるようになります。
ここで sass-loader は、SCSSスタイルをCSSスタイルに変換し、出力結果を css-loader に渡す役割を果たしています。

[参考] Webpack設定

[参考] sass-loader / css-loader / mini-css-webpack-plugin

[手順3] SCSSファイルを作成する

手順3では、コンパイル対象となるSCSSファイルを作成します。
上記設定ファイル /webpack.config.js では入力SCSSファイルパスを /src/source.scss に指定したので、その位置に source.scss ファイルを作成しましょう。
ファイル内容はどんなものでも構いませんが、ここでは例として以下のように記述することにします(折りたたみ要素の中にあります)。

/src/source.scss の入力内容例
/src/source.scss
$color-red: red;
$color-green: green;

#main {
  h1 {
    color: $color-red;
  }
  p {
    color: $color-green;
  }
}

[手順4] SCSSファイルをコンパイルしてCSSファイルを生成する

手順1〜3でSCSS→CSS変換のための準備が完了しました!
それではWebpackを用いて /src/source.scss から /dist/target.css を生成してみましょう。
ターミナルで npx webpack コマンドを実行することでビルド作業が開始します。

ターミナル
# ディレクトリ移動
cd /path/to/my-scss-project

# Webpackコマンド実行
npx webpack

ビルドが正常に完了すれば、CSSファイル /dist/target.css が生成されていることを確認できると思います。ファイルの内容を確認すると、SCSSで記述された部分が展開されてCSSになっているはずです(折りたたみ要素の中にあります)。 sass-loader css-loader の変換プロセスにおいてコメントが挿入されていることに注意してください。プロジェクトの開発段階ではこの情報をデバッグ等に利用することができます。

 /dist/target.css の出力内容例
/dist/target.css
/*!**********************************************************************************************************!*\
  !*** css ./node_modules/css-loader/dist/cjs.js!./node_modules/sass-loader/dist/cjs.js!./src/source.scss ***!
  \**********************************************************************************************************/
#main h1 {
  color: red;
}
#main p {
  color: green;
}

上記のWebpack設定ではSCSS→CSS変換の際に不必要なJavaScriptファイル /dist/target.js が生成されるようになっています。不必要なJavaScriptモジュールを削除したい場合には WebpackRemoveEmptyScripts プラグイン等を利用すると良いでしょう。この記事では詳細な使用方法については省略します。

[参考] WebpackRemoveEmptyScripts プラグイン
https://github.com/webdiscus/webpack-remove-empty-scripts

後書き

サンプルコード
/website/website-dev-on-webpack5/scss-on-webpack5

  1. マジックナンバーをなくすことでプログラムの可読性や保守性が高まると言われています。特にCSS言語では属性と値の組を大量に取り扱うため、その値の意味を把握しやすくすることは非常に重要です。

  2. 一般的なプログラミング言語の「処理ブロック」は、CSSにおいてはスタイル定義の集合に相当すると考えることができます。CSS言語でも @import 文を利用することでファイル単位の処理ブロックを扱うことはできますが、一般的なプログラミング言語の「関数」と比較するとその再利用性はあまり高くありません。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?