[Dart Sass対応] 便利なSassの使い方ガイド ~ 複数のscssファイルを分割してみる


2019/12/09

今回のお代は、ちょっと地味な(?)テクニック
「sassのファイル分割」に関してです。

とはいえ、従来のcssの時代にも
@import構文によって、外部のcssのソースコードを読み込むことはできました。

しかし、
@importが呼び出されるたびにリソースを参照しにいく仕様であり、ファイル分割を多用するとオーバヘッド時間が増加し、'cssのファイル分割はよろしくない'という議論もあったようです。

(ただ、今どきのモダンなjavascriptのフレームワークだと、開発者がリソースのオーバヘッド時間の最適化を意識せずとも、しっかりminifyして全部パッケージしてくれているので有り難い時代になりました。)

ということで、cssもコードの保守性・可読性の観点から、ファイル分割を使わない手はない、と思います。

そしてこの程、
公式のLibSass非推奨化のアナウンスを受けて、全面的に@import構文も今後は非推奨になりました。

とうことで結論から言うと、Sassも
@use構文でファイル分割していけばよいのですが、簡易的な使いどころの例交えながらご解説していきます。


分割の基本

複数のSassファイルを分割して利用する用法としては特に難しい点はありません。

まずモジュールとして読み込む方のファイルはルール上、
分割して読み込まれるファイル名には、_(アンダーバー)などから始めること、となっております。

例えば、Sassを含むプロジェクトが以下のようなファイル構造になっているとします。

            
            $ tree
.
└ app
   ├── app.html
   ├── app.html
   ├── app.js
   ├── parent.scss
   ├── _child1.scss
   ├── _child2.scss
   └── _child3.scss
        
起点となっているparent.scss側から、分割ファイルの_child*.scssを呼び出す場合、

            
            @use 'child1';
@use 'child2';
@use 'child3';
//...中略
        
としてソースコードの任意の場所に展開できるようになります。

リソースの管理上、ディレクトリ構造を一段下位に落としたい場合で使う場合の方が多いとおもいます。

そこでプロジェクト構造を以下のようにしてみます。

            
            $ tree
.
└ app
   ├── app.html
   ├── app.html
   ├── app.js
   ├── parent.scss
   └ children
      ├── _child1.scss
      ├── _child2.scss
      └── _child3.scss
        
@useの呼び出しは呼び出し側のリソースから見た相対パスですので、以下のように修正します。

            
            @use 'children/child1';
@use 'children/child2';
@use 'children/child3';
//...中略
        


応用例 〜 文字ブルブル

Sassのリソースファイルが別々に管理する場合の利点は様々あると思います。

例えばスタイルを機能ごとに切り出して、別ファイルとして管理させてみます。

今回は一例として、背景色や文字フォントなどの静的なスタイルとは別に、アニメーションのみを記述したscssファイルを抽出してみます。

単純なcssアニメーションとして、
一度はやってみたい「文字ブル」をangular(動作確認環境angular@~10.1.0)でやらせてみます。

プロジェクト

サクッとangularプロジェクトにコンポーネントを一つ作ります。

            
            $ ng g c components/mySplitScss
        
すると、ファイルは以下のように仕上がっているはずです。(node_modules内はスキップ、一部ファイル割愛)

            
            $ tree -I node_modules -L 5
.
├── angular.json
├── package.json
├── src
│   ├── app
│   │   ├── app.component.html
│   │   ├── app.component.scss
│   │   ├── app.component.spec.ts
│   │   ├── app.component.ts
│   │   ├── app.module.ts
│   │   └── components
│   │        └── my-split-scss
│   │             ├── my-split-scss.component.html
│   │             ├── my-split-scss.component.scss
│   │             ├── my-split-scss.component.spec.ts
│   │             └── my-split-scss.component.ts
#...以下略
        
このコンポーネントのフォルダ内に_animation.my-split-scss.component.scssの空ファイルを新規作成します。

すると、以下のようなフォルダ構造になっていると思います。

            
            $ tree -I node_modules -L 5
.
├── angular.json
├── package.json
├── src
│   ├── app
│   │   ├── app.component.html
│   │   ├── app.component.scss
│   │   ├── app.component.spec.ts
│   │   ├── app.component.ts
│   │   ├── app.module.ts
│   │   └── components
│   │        └── my-split-scss
│   │             ├── my-split-scss.component.html
│   │             ├── my-split-scss.component.scss
│   │             ├── _animation.my-split-scss.component.scss
│   │             ├── my-split-scss.component.spec.ts
│   │             └── my-split-scss.component.ts
#...以下略
        
ファイルの分割は準備できましたので、コードの中身を実装していきます。

コードの実装

コンポーネントの文字プルしたい要素に、shaky-textのクラスを指定します。

my-split-scss.component.htmlに以下の内容にします。

            
            <div class="shaky-text">
    <p>寒い</p>
</div>
        
続いてメインのscssファイルです。

以下の内容で
my-split-scss.component.scssを編集します。

            
            @use 'animation.my-split-scss.component';

.shaky-text {
    font-size: 1.8rem;
    color: #8f8f8f;
    &:hover {
        animation: shake .2s 10;
    }
}
        
@importから@useへマイグレーションする場合には、@useはファイル冒頭で宣言されなけえばならないので、使う位置に注意します。

ここでマウスホバーした時のアニメーションを指定してみます。

通常@keyframesアニメーションをファイルを分割せずに同ファイルに追加していくと、キーフレームの記述を長く複雑にするほどソースコード全体として可読性が失われてしまいます。

@useでキーフレームの定義だけ外部のファイルへ移すだけでも、メインのスタイルファイルの中身がスッキリと見通し良くなります。

また複数のアニメーションがあっても、ファイルごとに1つのアニメーションを整理させることで、後でアニメーションだけを再利用したい場合に役立ちます。

それでは
_animation.my-split-scss.component.scssのファイルには、アニメーションのキーフレームの内容だけを記述します。

            
            @keyframes shake {
    0% {
        transform: translate(0px, 0px) rotateZ(0deg);
    }
    25% {
        transform: translate(4px, 4px) rotateZ(0deg);
    }
    50% {
        transform: translate(0px, 4px) rotateZ(0deg);
    }
    75% {
        transform: translate(4px, 0px) rotateZ(0deg);
    }
    100% {
        transform: translate(0px, 0px) rotateZ(0deg);
    }
};
        

ビルド

上記のコードをビルドすると以下のような文字ぷるぷるアニメーションに仕上がっているはずです。

今回はとても簡単なアニメーションの例ですが、さらに複雑化していく場合にはSassコードによるファイル分割管理が欠かせなくなると思います。


まとめ

ここまででSassの@use構文を利用する勘どころを掴んでいただけたと思います。

とは言いつつ当の執筆者は当初からnode-sassユーザーであったので
@import構文ばかり使っていたのですが、この最近でdart-sassに乗り換えたばかりです。

@use構文は完全な@import構文の書き換えとはなっていないので、これから作り溜めてきたSassアセットたちを計画的にマイグレーションさせる作業に取り掛かっています。

今後も面白いお役立ちテクニックがあればこのブログで紹介していこうと思います。
記事を書いた人

記事の担当:taconocat

ナンデモ系エンジニア

主にAngularでフロントエンド開発することが多いです。 開発環境はLinuxメインで進めているので、シェルコマンドも多用しております。 コツコツとプログラミングするのが好きな人間です。