使用Rails 3.1资产管道有条件地使用特定的CSS

167

我正在使用Rails 3.1.rc5构建我的第一个独立应用程序。我的问题是,我希望网站能根据需要有条件地呈现各种CSS文件。我正在使用Blueprint CSS,并尝试让Sprockets / Rails大部分时间呈现screen.css,仅在打印时呈现print.css,并且只在从Internet Explorer访问站点时呈现ie.css

不幸的是,在application.css清单中的默认*= require_tree命令会将assets/stylesheets目录中的所有内容都包括进来,导致CSS混乱。我的当前解决方法是一种粗暴的方法,即逐个指定每个文件:

在application.css中:

*= require_self
*= require home.css
...
*= require blueprint/screen.css

在我的样式表局部文件中(使用Haml):

<!--[if lt IE 9]
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
![endif]-->
= stylesheet_link_tag "application"
= stylesheet_link_tag 'blueprint/print', media: 'print'
<!--[if lt IE8]]
= stylesheet_link_tag 'blueprint/ie'
![endif]-->
= javascript_include_tag "application"

这个代码能用但不是特别优美。我花了几个小时的时间进行搜索才找到了这个程度,但我希望还有一些更简单的方法可以实现,只是我可能错过了它们。如果我能够有选择地渲染某些目录(而不包括子目录),整个过程就会不那么死板。

谢谢!

3个回答

223

我发现了一种方法,可以通过使用资产管道并将样式表分组的方式使其更加灵活和具备未来性。这个解决方案虽然与你的解决方案没有太大区别,但它允许你自动添加新的样式表,而不必再次编辑整个结构。

你需要做的是使用单独的清单文件来分解事物。首先,你需要重新组织你的app/assets/stylesheets文件夹:

app/assets/stylesheets
+-- all
    +-- your_base_stylesheet.css
+-- print
    +-- blueprint
        +-- print.css
    +-- your_print_stylesheet.css
+-- ie
    +-- blueprint
        + ie.css
    +-- your_ie_hacks.css
+-- application-all.css
+-- application-print.css
+-- application-ie.css

然后你需要编辑三个清单文件:

/**
 * application-all.css
 *
 *= require_self
 *= require_tree ./all
 */

/**
 * application-print.css
 *
 *= require_self
 *= require_tree ./print
 */

/**
 * application-ie.css
 *
 *= require_self
 *= require_tree ./ie
 */

接下来,您需要更新应用程序的布局文件:

<%= stylesheet_link_tag "application-all", :media => "all" %>
<%= stylesheet_link_tag "application-print", :media => "print" %>

<!--[if lte IE 8]>
    <%= stylesheet_link_tag "application-ie", :media => "all" %>
<![endif]-->

最后,不要忘记在你的config/environments/production.rb中包含这些新的清单文件:

config.assets.precompile += %w( application-all.css application-print.css application-ie.css )

更新:

正如 Max 指出的那样,如果你遵循这个结构,你必须注意图片的引用。你有几个选择:

  1. 将图片移动以遵循相同的模式
    • 请注意,这仅适用于图片不是全部共享的情况
    • 我希望这对大多数人来说都不可行,因为它会使事情变得太复杂
  2. 限定图像路径:
    • background: url('/assets/image.png');
  3. 使用 SASS 助手:
    • background: image-url('image.png');

1
虽然这是文件的良好组织,但我认为它仍然以与问题本身相同的方式解决了基本问题。 - semperos
5
实际上在Rails资产管道指南中类似这样的内容会很好。谢谢。 - Bashar Abdullah
3
有一个需要注意的地方:如果按照这种结构使用简单的.css文件,那么您所有的图像都将无法显示。例如,background: url('image.png')将被转换为路径/assets/all/image.png(请注意路径中的all)。相反,应该使用这个:background: url('/assets/image.png)。如果有更简单的解决方案,请发布出来。除了使用具有帮助程序方法的SASS以外,可能会正确解析路径之外,没有其他解决方法。 - Max
1
@ExiRe,是的。任何不遵循标准模式的样式表或JS文件/清单都需要添加到预编译数组中(请参见:http://guides.rubyonrails.org/asset_pipeline.html#precompiling-assets)。 - gcastro
为了简化这个过程,您可以在每个子目录中放置一个清单文件,并使用此 Dir.glob(Rails.root.join('app/assets/*/*/manifest.*').to_s).map{|p| File.join(p.split(File::SEPARATOR)[-2..-1])} 来预编译所有清单。 - spyle
显示剩余9条评论

10

今天遇到了这个问题。

最终将所有IE特定的样式表放入lib/assets/stylesheets中,并为每个IE版本创建一个清单文件。然后在application.rb中将它们添加到预编译列表中:

config.assets.precompile += ["ie9.css", "ie7.css", "ie8.css", "ie.css"]

在你的布局中,有条件地包含这些清单文件,你就可以开始了!


2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接