34

问题

Microsoft 的 IE 支持文档解释说,在 Internet Explorer 6-9 中:

  1. 前 31 个样式标签之后的所有样式标签都不会应用。
  2. 不应用前 4,095 条规则之后的所有样式规则。
  3. 在使用@import 规则持续导入外部样式表的页面上,导入其他样式表的页面,超过三层深度的样式表将被忽略。

脚本演示有很多证据表明这个问题。另见祝福

需要解决方案

我们需要一种方法来拆分资产管道中 Sprockets 生成的已编译样式表,以保持最大选择器计数低于 4096,并在已部署的 Rails 应用程序的 HTML 中链接到它们。我们如何将已处理资产(特别是样式表)的编译输出作为参数传递给可以修改文件的方法?

请参阅以下尝试以了解起点。如果有人可以帮助我找到一种方法来使任一操作(或全新的解决方案),那就太棒了!

现有的解决方案尝试

  • Bless是为了解决这个问题而创建的,它通过拆分样式表以将每张表的最大选择器计数保持在限制之下。Bless 在 node.js 中的服务器上运行。我还没有看到一个 Ruby 等效的。Eric Fields 尝试将使用 compass 编译的资产提供给 Bless(在节点中运行),但该解决方案依赖于 Compass 处理资产编译,因此似乎不适用于资产管道。请注意,Bless 不是链接到多个样式表,而是将@include语句添加到第一个表中,这可能是避免接触标记的方法。

  • 当 Christian Peters (@crispy)发现这个问题时,他实现了一个像 Bless 这样的分离器,它也将 Compass 输出传递到一个自定义模块,这在 Rails 3.1 之前工作得很好。后来,他使用 SprocketsEngine 调整了他的拆分器,以便与 Rails Asset 管道集成。我已经尝试实现新代码,但它似乎不能自动运行(尽管在控制台中手动调用拆分器时工作正常)。

相关信息

有关 IE 6-9 中的 CSS 限制的更多信息,请参阅以下相关问题:

4

2 回答 2

10

我们有一个自动化的(尽管有点尴尬)解决方案在生产中用于具有资产管道的 Rails 3.1 应用程序。Ryan 已经在他的问题中引用了该解决方案,但我试图提出一个更全面的答案。

资产管道通过不同的 Sprocket 引擎对资产进行管道传输。

因此,您可能有一个ie.css.sass.erb通过 ERB Sprocket 引擎运行然后传递给 Sass Sprocket 引擎等的 a,但它始终是一个文件输入和一个文件输出。

在这个特殊问题中,我们希望有 1 个入站文件和 n 个出站文件。我们还没有找到使用链轮实现这一点的方法。但我们找到了解决方法:

提供一个ie.css.sass包含完整样式表和一个ie_portion2.css.sass.split2只导入完整 ie.css 文件的文件:

//= include 'ie.css'

对于split2文件扩展名,我们注册了一个 Sprockets Engine:

require 'css_splitter'
Rails.application.assets.register_engine '.split2', CssSplitter::SprocketsEngine

在使用 split2 扩展评估资产时,我们将其内容传递给 CssSplitter 并指示它提取第 2 部分(> 4095 个选择器):

require 'tilt'
module CssSplitter

  class SprocketsEngine < Tilt::Template
    def self.engine_initialized?
      true
    end

    def prepare
    end

    def evaluate(scope, locals, &block)
      part = scope.pathname.extname =~ /(\d+)$/ && $1 || 0
      CssSplitter.split_string data, part.to_i
    end
  end
end

这也适用于其他部分(split3,...)。

CSS 拆分器识别出样式表可以拆分为少于 4096 个选择器的部分的有效位置,并返回请求的部分。

结果是一个 ie_portion2.css,您必须在头部链接并单独预编译。

我希望我修改后的CSS Splitter Gist足够完整,可以使用该解决方案。

更新:

上面提到的 CssSplitter 现已作为 gem 发布:https ://github.com/zweilove/css_splitter

于 2012-08-26T22:14:19.097 回答
7

我在生产中使用的解决方案非常简单,不是自动化的,但效果很好。对我来说,这是显而易见的事情,所以也许你已经考虑过了并且不喜欢它——不管怎样,我们开始吧:

我假设您正在使用 sass,如果没有,我认为您应该:)



首先,将您application.css.scss的文件拆分为单独的文件,例如: application_a.css.scssapplication_b.css.scss



其次,在您的application.css.scss文件中,使用:

@import "application_a"
@import "application_b"



第三,在您的布局模板中,包括完整的文件或两个部分:

<!--[if !IE]><!-->
  # link to application.css.scss
<!--<![endif]-->

<!--[if IE]>
  # link to application_a.css.scss
  # link to application_b.css.scss
<![endif]-->

旁注:不要通过资产管道生成样式表清单文件,通过 sass 和它的@import语句来生成,其他一切都会导致问题。

于 2012-08-26T11:23:58.170 回答