はじめに
RailsでSassを使用し、かつファイルを用途・適応範囲に応じて複数に分割したとき、どのような構成、読み込み方式にするかを実際の失敗談交えながら、記載したいと思います。
最初に「つまづいたこと」で、私が体験した発生した事象や原因などを書いていますが、必要なければ読み飛ばしてもらえればと思います。
環境
ruby: 2.6.4
rails: Rails 6.0.3.1 (sass-rails gemを使用)
まず結論
Railsで複数のSassを使用する際には、読み込みをSprocketsディレクティブ方式(require_tree)ではなく、@import
で読み込むこと
つまづいたこと
携わったプロジェクトではSassを使用しており、かつスタイルファイルをメンテしやすくするため、コントローラ単位で.scssファイルを作成していた。
stylesheets
直下のapplication.scss
で全体に共通のスタイルを設定し、stylesheets/main
配下に複数の.scssファイルを配置。
application.scss
では、以下の内容を記載していた。
- ディレクティブ方式でmain配下のscssファイルを読み込み
- その後bootstrapなどを読み込み(@import )
- 最後に共通スタイルを設定。
〜 中略 〜
*= require_tree ./main
*= require_self *= require_self
*/
@import "bootstrap/scss/bootstrap";
〜 中略 〜
// 共通スタイル
body {
font-family: ....
}
〜 中略 〜
やろうとしたこと
今回、共通で使用する変数 (ex $main-color: #3D85C6;
)を作成して、各.scssファイルで使い回そうと思い、以下のように共通変数の定義を追記した。
〜 中略 〜
*= require_tree ./main
*= require_self *= require_self
*/
@import "bootstrap/scss/bootstrap";
〜 中略 〜
// 共通変数
$main-color: #3D85C6;
// 共通スタイル
body {
font-family: ....
}
〜 中略 〜
ただ、この状態だとmain配下のscssファイルで変数を使用するとエラーになったため、変数の読み込みが必要だと思い、main配下のscssファイル側でapplication.scss
を@import
した(今思えば、なぜこんな書き方をしたのか、後悔しかない・・・)
結果、main配下のscssファイルでも、変数を使用でき、スタイルも適用されてめでたしめでたしと思っていました。
その後、起こったこと
カスタマイズを進め、applicaiton.scssに変更を加えていく中で、不可解な現象が、、、
- ブラウザの検証機能でスタイルを見ると、同じスタイルが2つある
- application.scss内のとあるクラスのスタイルから、一部プロパティを削除しても反映されない
(前述のとおり同一スタイルが2つ存在し、片方しかプロパティ削除が反映されていない)
原因
すでにお気づきかもしれませんが、「やろうとしたこと」の中で、main配下のscssファイルで、application.scssをimportしてしまったたため、
そこに記載したスタイルが二重で読み込まれてしまいました。なおかつapplication.scssでimportしたbootstrap関連のscssも二重で読み込まれてました。
ただ、applicaiton.scss内のスタイルを変更しても、反映されない原因は結局わからず・・
というわけで、main配下のscssでのimportを削除するとともに、railsで複数のscssファイルを利用するためには、どのような読み込み方法良いのか調べることになりました。。
railsで複数のscssファイルを利用際の適切な読み込み方法
調査した結果
railsguide, rails-sass(gem)のページに記載の通り、railsで複数のSass(.scssファイル)を使用する際には、Sprocketsディレクティブで読み込まずにSass@importルールを使用する必要があります。
ディレクティブ方式だと、宣言した変数やmixinが他のscssファイルから利用できない。(まさしく今回私が体験した内容)
Sassファイルを複数使用しているのであれば、Sprocketsディレクティブで読み込まずにSass @importルールを使用する必要があります。このような場合にSprocketsディレクティブを使用してしまうと、Sassファイルが自分自身のスコープに置かれるため、その中で定義されている変数やミックスインが他のSassから利用できなくなってしまいます。
Important Note
Sprockets provides some directives that are placed inside of comments called require, require_tree, and require_self. DO NOT USE THEM IN YOUR SASS/SCSS FILES. They are very primitive and do not work well with Sass files. Instead, use Sass's native @import directive which sass-rails has customized to integrate with the conventions of your Rails projects.
最終的なapplicaiton.scssの記載内容
最終的には以下のような記述内容にしました。
これにより、common.scss
で定義した変数が他のmain配下のscssファイルでも読み込むことができました。
-
applicaiton.scss
から、reuire_tree
,require_self
の記載を削除 - 元々
applicaiton.scss
に記載していた共通スタイルと変数は、common.scss
を新たに作成して移管 -
@import
でcommon(共通スタイル)、main配下のスタイルを順に読み込み
〜 中略 〜
*
*/
@import "bootstrap/scss/bootstrap";
@import "common";
@import "main/*";
参考文献
あるべきscssファイルの取り込み方法を理解するために大変参考になりました。