Railsの適切なSCSSアセット構造


86

したがって、app/assets/stylesheets/次のようなディレクトリ構造があります。

   |-dialogs
   |-mixins
   |---buttons
   |---gradients
   |---vendor_support
   |---widgets
   |-pages
   |-structure
   |-ui_elements

各ディレクトリには、複数のsassパーシャルがあります(通常は* .css.scssですが、1つまたは2つの* .css.scss.erb)。

私は多くのことを想定しているかもしれませんが*= require_tree .、application.cssにあるため、railsはそれらのディレクトリ内のすべてのファイルを自動的にコンパイルする必要がありますよね?

最近、すべての色変数を削除してルートapp/assets/stylesheetsフォルダー(_colors.css.scss)のファイルに配置することにより、これらのファイルを再構築しようとしました。次に、app/assets/stylesheets次のようなファイルをmaster.css.scssというルートフォルダーに作成しました。

// Color Palette 
@import "colors";

// Mixins
@import "mixins/buttons/standard_button";
@import "mixins/gradients/table_header_fade";
@import "mixins/vendor_support/rounded_corners";
@import "mixins/vendor_support/rounded_corners_top";
@import "mixins/vendor_support/box_shadow";
@import "mixins/vendor_support/opacity";

Railsがアセットのコンパイルの順序をどのように処理するかはよくわかりませんが、明らかに私の好みではありません。インポートされている変数またはミックスインがあることを認識しているファイルがないようです。そのため、エラーがスローされ、コンパイルできません。

Undefined variable: "$dialog_divider_color".
  (in /home/blah/app/assets/stylesheets/dialogs/dialog.css.scss.erb)

Undefined mixin 'rounded_corners'.
  (in /home/blah/app/assets/stylesheets/widgets.css.scss)

変数$dialog_divider_colorは_colors.css.scssで明確に定義されており、_master.css.scss色とすべてのミックスインをインポートしています。しかし、どうやらレールはそのメモを受け取らなかったようです。

これらのエラーを修正する方法はありますか、それともすべての変数定義を個々のファイルに戻し、すべてのミックスインインポートに戻す必要がありますか?

残念ながら、この男はそれが可能だとは思わないようですが、私は彼が間違っていることを望んでいます。どんな考えでも大歓迎です。

回答:


126

CSSの問題は、すべてのファイルを自動的に追加したくないということです。シートがブラウザによってロードおよび処理される順序は重要です。したがって、常にすべてのcssを明示的にインポートすることになります。

例として、normalize.cssシートがあり、すべての恐ろしいさまざまなブラウザー実装の代わりにデフォルトの外観を取得するとします。これは、ブラウザが最初にロードするファイルである必要があります。このシートをcssインポートのどこかにランダムに含めると、ブラウザのデフォルトスタイルだけでなく、それ以前にロードされたすべてのcssファイルで定義されているスタイルも上書きされます。これは、変数とミックスインについても同じです。

Euruko2012でRoyTomeijによるプレゼンテーションを見た後、管理するCSSがたくさんある場合は、次のアプローチを選択しました。

私は通常、このアプローチを使用します。

  1. 既存のすべての.cssファイルの名前を.scssに変更します
  2. application.scssからすべてのコンテンツを削除します

@importディレクティブの追加を開始しapplication.scssます。

Twitterのブートストラップと独自のCSSシートをいくつか使用している場合は、スタイルをリセットするシートがあるため、最初にブートストラップをインポートする必要があります。だからあなたはあなたのに追加@import "bootstrap/bootstrap.scss";しますapplication.scss

bootstrap.scssファイルは次のようになります。

// CSS Reset
@import "reset.scss";

// Core
@import "variables.scss";
@import "mixins.scss";

// Grid system and page structure
@import "scaffolding.scss";

// Styled patterns and elements
@import "type.scss";
@import "forms.scss";
@import "tables.scss";
@import "patterns.scss";

そしてあなたのapplication.scssファイルは次のようになります:

@import "bootstrap/bootstrap.scss";

インポートの順序により、その後にインポートされた@import "variables.scss";他の.scssファイルにロードされた変数を使用できるようになりました。したがってtype.scss、ブートストラップフォルダだけでなくmy_model.css.scss。でも使用できます。

この後、partialsまたはという名前のフォルダを作成しますmodules。これは、他のほとんどのファイルの場所になります。インポートをapplication.scssファイルに追加するだけで、次のようになります。

@import "bootstrap/bootstrap.scss";
@import "partials/*";

今、あなたがあなたのホームページの記事をスタイルするために少しcssを作るならば。作成するだけでpartials/_article.scss、コンパイル済みに追加されapplication.cssます。インポート順序により、独自のscssファイルで任意のブートストラップミックスインと変数を使用することもできます。

私がこれまでに見つけたこの方法の唯一の欠点は、railsが常にそれを行うとは限らないため、partial/*。scssファイルの再コンパイルを強制しなければならない場合があることです。


4
おかげで、これは私が行ったアプローチです。作成するたびに含めるすべてのファイルを手動で追加する必要があるため、このソリューションは嫌いですが、CSSが関係している場合は、順序が重要であるように思われます。通常、これはCSSの記述としては悪いことだと思いますが、ベンダーが提供するもの(つまり、上記のブートストラップ)を使用している場合は、上書きしたい傾向があるため、これが正しいアプローチであることに惜しみなく同意します。
デビッドサベージ

1
ありがとう!とても素敵なアプローチと良い説明です!言及する価値のある1つのプロジェクト:このFireBugプラグインであるFireSassは、コンパイルされたapplication.cssの行ではなくmy_model.css.sassの行番号を示します
BBQ Chef

このアプローチでは、デフォルトのリンクの色をすべてのパーシャルに適用される赤に変更したい場合、どのように行いますか?どこに置きますか?
chh 2014

1
このアプローチは、The Asset Pipeline RailsGuideでも推奨されていることに注意してください。「複数のSassファイルを使用したい場合」を検索します。
ybakos 2014年

1
@Lykosはい、からすべてを削除しapplication.css、名前をに変更しapplication.scssます。なぜならrequire_tree、すべてが含まれていて、通常は順序を制御したいからです
Benjamin Udink ten Cate 2016年10

8

ファイル間で変数などを使用するには、@ importディレクティブを使用する必要があります。ファイルは指定された順序でインポートされます。

次に、application.cssを使用して、インポートを宣言するファイルを要求します。これは、必要な制御を実現する方法です。

最後に、layout.erbファイルで、使用する「マスター」cssファイルを指定できます。

例がより役立ちます:

アプリに、「application」と「admin」という異なるcssのセットを必要とする2つのモジュールがあるとします。

ファイル

|-app/
|-- assets/
|--- stylesheets/
|     // the "master" files that will be called by the layout
|---- application.css
|---- application_admin.css
|
|     // the files that contain styles
|---- config.scss
|---- styles.scss
|---- admin_styles.scss
|
|     // the files that define the imports
|---- app_imports.scss
|---- admin_imports.scss
|
|
|-- views/
|--- layouts/
|---- admin.html.haml
|---- application.html.haml

内部のファイルは次のようになります。

-------- THE STYLES

-- config.scss
// declare variables and mixins
$font-size: 20px;

--  app_imports.scss
// using imports lets you use variables from `config` in `styles`
@import 'config'
@import 'styles'

-- admin_imports.scss
// for admin module, we import an additional stylesheet
@import 'config'
@import 'styles'
@import 'admin_styles'

-- application.css
// in the master application file, we require the imports
*= require app_imports
*= require some_other_stylesheet_like_a_plugin
*= require_self

-- application_admin.css
// in the master admin file, we require the admin imports
*= require admin_imports
*= require some_other_stylesheet_like_a_plugin
*= require_self


-------- THE LAYOUTS

-- application.html.haml
// in the application layout, we call the master css file
= stylesheet_link_tag "application", media: "all"

--  admin.html.haml
// in the admin layout, we call the admin master css file
= stylesheet_link_tag "application_admin", media: "all"

7

次のフォルダ構造を作成します。

+ assets
|
--+ base
| |
| --+ mixins (with subfolders as noted in your question)
|
--+ styles
  |
  --+ ...

フォルダにbase「globals.css.scss」というファイルを作成します。このファイルで、すべてのインポートを宣言します。

@import 'base/colors';
@import 'base/mixins/...';
@import 'base/mixins/...';

application.css.scssには、次のものが含まれている必要があります。

*= require_self
*= depends_on ./base/globals.css.scss
*= require_tree ./styles

そして最後のステップとして(これは重要です)、@import 'base/globals'変数またはミックスインを使用するすべてのスタイルファイルで宣言します。このオーバーヘッドを考慮するかもしれませんが、私は実際には、すべてのファイルでスタイルの依存関係を宣言する必要があるという考えが好きです。もちろん、スタイル定義を追加しないため、globals.css.scssにミックスインと変数のみをインポートすることが重要です。そうしないと、スタイル定義がプリコンパイルされたファイルに複数回含まれることになります...


私はこれを試しましたが、正しく動作させることができませんでした(それでも変数エラーが欠落していました)。たぶん私は何かを正しくしなかったかもしれませんが、CSSの順序が重要であるため、最終的には各ファイルを手動でリストするアプローチが正しい方法だと思います。
デビッドサベージ

このアプローチを引き続き使用できます。「require_tree ...」の代わりに、個々のファイルごとに1行追加するだけです。これにより、SASSはファイルを正しい順序でインポートします。現在使用しているソリューションについては、私が見つけた次の投稿をご覧ください:stackoverflow.com/questions/7046495/…必ずapplication.cssファイルにdepends_ondirectivieを含めてください。
emrass 2012

4

この質問によると、インポートを定義し、テンプレート間で変数を共有するためにのみ使用できapplication.css.sassます。

=>名前の問題のようです。

もう1つの方法は、すべて含めてこのパイプラインを無効にすることです。


これは基本的に、ベンジャミン・ウディンク・テン・ケイトがあなたの回答の後半で提供したものと同じですが、彼の解決策がより説明的であるため、彼に賞金を授与します。
デビッドサベージ

1

私は非常によく似た問題を抱えていました。パーシャルをインポートするときに、@ importステートメントにアンダースコアを付けることができました。そう

@import "_base";

の代わりに

@import "base";

奇妙なバグかもしれません...

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.