Правильна структура активів SCSS у рейках


86

Отже, у мене є app/assets/stylesheets/структура каталогів, яка виглядає приблизно так:

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

У кожному каталозі є декілька частин sass (зазвичай * .css.scss, але один або два * .css.scss.erb).

Можливо, я припускаю багато, але rails ПОВИНЕН автоматично зкомпілювати всі файли в цих каталогах через *= require_tree .в application.css, так?

Нещодавно я спробував реструктуризувати ці файли, видаливши всі кольорові змінні та помістивши їх у файл у кореневій 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, я вирішив застосувати наступний підхід, якщо у вас є багато CSS для управління.

Я зазвичай використовую такий підхід:

  1. Перейменуйте всі існуючі файли .css на .scss
  2. Видаліть весь вміст із application.scss

Почніть додавати директиви @import до application.scss.

Якщо ви використовуєте twitters bootstrap і кілька власних аркушів css, вам потрібно спочатку імпортувати bootstrap, оскільки він має аркуш для скидання стилів. Тож ви додаєте @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.

Єдиним недоліком цього методу, який я знайшов на даний момент, є те, що іноді доводиться примусово перекомпілювати часткові файли / *. Scss, оскільки рейки завжди це роблять за вас.


4
Дякую, ось такий підхід я в підсумку пішов. Я ненавиджу це рішення, тому що ви повинні вручну додавати кожен файл, який ви включаєте, кожен раз, коли ви створюєте його, але, здається, коли задіяний CSS, порядок має значення. Зазвичай я б сказав, що це просто погане написання CSS, але якщо ви використовуєте речі, які постачаються від постачальника (тобто, bootstrap, як ви вже згадували вище), ви, як правило, хочете перезаписати речі, тому я із невдоволенням погоджуюсь, що це правильний підхід.
David Savage

1
Дякую! Дуже приємний підхід та гарне пояснення! Один проект, про який варто згадати: Цей плагін FireBug, FireSass , показує номер рядка my_model.css.sass замість рядка скомпільованого application.css
шеф-кухар BBQ

За такого підходу, якщо я хочу змінити свій колір посилання за замовчуванням на червоний, який стосується всіх моїх частин, як би ви це зробили? Де б ви його поклали?
chh

1
Зауважте, що такий підхід також рекомендується у Посібнику з рейок трубопроводів активів . Шукайте "Якщо ви хочете використовувати кілька файлів Sass".
ybakos

1
@Lykos так, ви видаляєте все з application.cssі перейменовуєте на application.scss. Тому що require_treeвключає майже все, і ви хочете, як правило, контролювати порядок
Бенджамін Удінк тен Кате

8

щоб використовувати змінні та подібні файли у файлах, потрібно використовувати директиву @import. файли імпортуються в зазначеному порядку.

потім використовуйте application.css, щоб вимагати файл, який декларує імпорт. це спосіб досягти потрібного контролю.

нарешті, у файлі layout.erb ви можете вказати, який "майстер" css-файл використовувати

приклад буде більш корисним:

припустимо, у вашому додатку є два модулі, які потребують різних наборів css: "application" та "admin"

файли

|-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 має значення.
David Savage

Ви все ще можете скористатися таким підходом: Замість "require_tree ..." просто додайте рядок для кожного окремого файлу. Це змусить SASS імпортувати файли у правильному порядку. Що стосується рішення ви зараз використовуєте, будь ласка, подивіться на цей пост , що я тільки що знайшов: stackoverflow.com/questions/7046495 / ... Переконайтеся в тому , щоб включити depends_on directivie в файлі application.css.
emrass

4

Відповідно до цього питання , ви можете використовувати ТІЛЬКИapplication.css.sass для того, щоб визначити імпорт та обмін змінними між вашими шаблонами.

=> Здається, це лише питання назви.

Іншим способом може бути включення всього і вимкнення цього конвеєру .


Це, по суті, те саме, що Бенджамін Удінк десять Кейт запропонував у другій частині Вашої відповіді, але присудження йому нагороди як його рішення є більш пояснювальним.
David Savage

1

У мене була дуже подібна проблема. Мені допомогло підкреслення підкреслення оператора @import під час імпорту часткового. Тому

@import "_base";

замість

@import "base";

Це може бути дивна помилка ...

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.