【问题标题】:Proper SCSS Asset Structure in RailsRails 中正确的 SCSS 资产结构
【发布时间】:2012-02-26 16:17:12
【问题描述】:

所以,我有一个看起来像这样的app/assets/stylesheets/ 目录结构:

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

在每个目录中,有多个 sass partials(通常是 *.css.scss,但有一个或两个 *.css.scss.erb)。

我可能做了很多假设,但是由于 application.css 中的 *= require_tree .,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 是如何处理资产编译的顺序的,但这显然对我不利。似乎没有一个文件意识到它们有任何变量或 mixin 被导入,因此它会引发错误并且我无法编译。

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

有什么方法可以修复这些错误,还是我需要将所有变量定义放回每个单独的文件,以及所有 mixin 导入?

不幸的是,this guy 似乎不认为这是可能的,但我希望他是错的。任何想法都非常感谢。

【问题讨论】:

    标签: css ruby-on-rails asset-pipeline sass


    【解决方案1】:

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

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

    在 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";
    

    由于导入的顺序,您现在可以在其后导入的任何其他.scss 文件中使用加载了@import "variables.scss"; 的变量。因此它们可以在引导文件夹中的type.scss 中使用,也可以在my_model.css.scss 中使用。

    在此之后创建一个名为 partialsmodules 的文件夹。这将是大多数其他文件的位置。您可以将导入添加到 application.scss 文件中,如下所示:

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

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

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

    【讨论】:

    • 谢谢,这是我最终采用的方法。我讨厌这种解决方案,因为您必须在每次创建文件时手动添加包含的每个文件,但似乎在涉及 CSS 时,顺序确实很重要。通常我会说这只是糟糕的 CSS 编写,但如果你使用的是供应商提供的东西(即上面提到的引导程序),你往往想要覆盖东西,所以我勉强同意这是正确的方法。
    • 谢谢!一个非常好的方法和一个很好的解释!一个值得一提的项目:这个 FireBug 插件,FireSass,显示了 my_model.css.sass 的行号,而不是编译后的 application.css 的行
    • 使用这种方法,如果我想将我的默认链接颜色更改为适用于我所有部分的红色,你会怎么做?你会把它放在哪里?
    • 请注意,The Asset Pipeline Rails Guide 也推荐这种方法。搜索“如果你想使用多个 Sass 文件”。
    • @Lykos 是的,您从application.css 中删除所有内容并将其重命名为application.scss。因为require_tree 包含所有内容并且您通常希望控制订单
    【解决方案2】:

    创建以下文件夹结构:

    + 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 中导入 mixins 和变量,因为它们不会添加样式定义。否则样式定义将多次包含在您的预编译文件中...

    【讨论】:

    • 我试过了,但始终无法正常工作(仍然出现缺少变量错误)。也许我没有做正确的事情,但我认为最终手动列出每个文件的方法是正确的方法,因为 CSS 顺序确实很重要。
    • 您仍然可以使用这种方法:而不是“require_tree ...”,只需为每个单独的文件添加一行。这将使 SASS 以正确的顺序导入文件。关于您现在使用的解决方案,请查看我刚刚找到的这篇文章:stackoverflow.com/questions/7046495/… 请确保在您的 application.css 文件中包含 depends_on 指令。
    【解决方案3】:

    要跨文件使用变量等,您需要使用@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"
    

    【讨论】:

      【解决方案4】:

      根据this question,您可以使用application.css.sass 来定义模板之间的导入和共享变量。

      => 似乎只是名字的问题。

      另一种方式是include everything and disable this pipeline

      【讨论】:

      • 这与 Benjamin Udink 10 Cate 在您回复的第二部分中提供的基本相同,但在他的解决方案中授予他赏金更具解释性。
      【解决方案5】:

      我有一个非常相似的问题。对我有帮助的是在导入部分时在@import 语句中加上下划线。所以

      @import "_base";
      

      而不是

      @import "base";
      

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

      【讨论】:

        【解决方案6】:

        我的解决方案是使用 application.css.scss 包含所有导入:

        @import "./inputs";
        @import "./buttons";
        @import "./rails";
        @import "./base";
        @import "./checked-border";
        @import "./tailwind-extended";
        @import "./helpers";
        @import "./custom";
        @import "./overrides";
        

        然后加上:

        @import "./constants";
        

        到使用常量的文件

        【讨论】:

          猜你喜欢
          • 2014-10-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-06-09
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多