Rails中正确的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如何处理资产编译的顺序,但是显然这对我不利。似乎没有文件意识到要导入任何变量或mixins,因此会引发错误,因此我无法编译。

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正在导入颜色和所有我的mixins。但是显然,rails没有得到该备忘录。

有什么办法可以解决这些错误,还是需要将所有变量定义以及所有mixin导入放回到每个文件中?

不幸的是,这个家伙似乎并不认为有可能,但我希望他错了。任何想法都将不胜感激。

Answers:


126

CSS的问题是,您不想自动添加所有文件。浏览器加载和处理工作表的顺序至关重要。因此,您最终总是会明确地导入所有CSS。

例如,假设您有一个normalize.css工作表,以获取默认外观,而不是所有可怕的不同浏览器实现。这应该是浏览器加载的第一个文件。如果只是将此表随机包含在CSS导入中的某个位置,则它将不仅覆盖浏览器的默认样式,而且覆盖所有在其之前加载的CSS文件中定义的样式。变量和混入也是如此。

Euruko2012上看到Roy Tomeij的演讲后,如果您要管理大量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在bootstrap文件夹中使用,也可以在中使用my_model.css.scss

之后,创建一个名为partials或的文件夹modules。这将是其他大多数文件的位置。您可以将导入添加到application.scss文件中,使其看起来像:

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

现在,如果您花一点点css在首页上设置文章样式。只需创建partials/_article.scss,它将添加到已编译application.css。由于导入顺序的原因,您还可以在自己的scss文件中使用任何引导混合和变量。

到目前为止,我发现这种方法的唯一缺点是,有时您必须强制重新编译partial / *。scss文件,因为rails不会总是为您执行此操作。


4
谢谢,这是我最终使用的方法。我讨厌这种解决方案,因为每次创建文件时都必须手动添加其中包括的每个文件,但是似乎涉及CSS时,顺序确实很重要。通常,我会说那只是CSS编写的错误,但是,如果您使用的是供应商提供的功能(例如,如上所述的引导程序),则倾向于覆盖某些内容,因此,我勉强同意这是正确的方法。
David Savage

1
谢谢!一个很好的方法和一个很好的解释!一个项目值得一提:这萤火虫插件,FireSass,显示my_model.css.sass而不是编译application.css线的行号
烧烤厨师

使用这种方法,如果我想将默认链接颜色更改为适用于所有局部的红色,您将如何做?你会放在哪里?
chh 2014年

1
请注意,《资产管道指南》中也建议使用此方法。搜索“如果要使用多个Sass文件”。
ybakos 2014年

1
@Lykos是的,您从中删除了所有内容application.css并将其重命名为application.scss。因为require_tree只包含所有内容,您通常希望控制订单
本杰明·乌丁克

8

要在整个文件中使用变量等,您需要使用@import指令。文件按照指定的顺序导入。

然后,使用application.css要求声明导入的文件。这是实现所需控制的方法。

最后,在您的layout.erb文件中,您可以指定要使用的“主” css文件

这个例子会更有用:

假设您的应用程序中有两个模块需要不同的CSS集:“应用程序”和“管理员”

文件

|-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'在每个样式文件中声明要使用变量或混入的位置。您可能会考虑这种开销,但是我实际上很喜欢这样的想法,即必须在每个文件中声明样式的依赖性。当然,重要的是,您只能将mixin和变量导入globals.css.scss中,因为它们不会添加样式定义。否则,样式定义将多次包含在您的预编译文件中。


我尝试了此方法,但始终无法使其正常工作(仍然会丢失变量错误)。也许我没有做正确的事,但是我认为最后手动列出每个文件的方法是正确的方法,因为CSS顺序确实很重要。
David Savage '02

您仍然可以使用这种方法:代替“ require_tree ...”,只需为每个文件添加一行。这将使SASS以正确的顺序导入文件。关于您现在使用的解决方案,请看一下我刚刚发现的这篇文章:stackoverflow.com/questions/7046495/…请确保在application.css文件中包含depends_on指令。
Emrass

4

根据此问题,您只能使用application.css.sass来定义模板之间的导入和共享变量。

=>这似乎只是名称问题。

另一种方法可以包括所有内容并禁用此管道


这基本上是本杰明·乌丁克(Benjamin Udink)十个凯特(Cate)在您的回应的第二部分中提供的,但是授予他赏金是因为他的解决方案更具解释性。
David Savage '02

1

我有一个非常类似的问题。帮助我的是,在导入部分文档时,在@import语句下划线。所以

@import "_base";

代替

@import "base";

这可能是一个奇怪的错误...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.