7

Note: This question refers to a Rails project with Sass & Compass. Using the Rails Asset Pipeline? Then have a look at this question.

We are developing a big application with many use cases and many individually styled pages, partly for multiple contexts. Which simply means a lot of style information.

With the newest section of our application, we have broken Internet Explorer's limit of 4095 selectors per stylesheet. (Want a proof of this limitation? http://marc.baffl.co.uk/browser_bugs/css-selector-limit/)

Okay. So, why do we not simply split the application style sheet into multiple ones by design?

Well, mixins and selector inheritance will not work across multiple Sass files (not partials), right?

I'd say the quality of the stylesheets is rather good, we cannot optimize away the exceeding amount of selectors. (There is rather more to come.) I also believe that minimizing the amount of selectors should not be our primary optimization goal. The Sass core team advises to use selector inheritance instead of mixins where applicable in order to save CSS file size. By doing so, the number of selectors tends to grow though.

So what should I do?

I am thinking about writing a script that generates additional css files, partitioning my big application.css file. These would only be loaded in IE then (so that I don't have multiple requests in modern browsers). I would need a simple css parser for that in order to cut the application.css file after max. 4095 selectors at a valid position. And I would need an compass compile - after hook so that developers don't need to generate the IE files by hand in order to test it.

Please, tell me, that you got a better idea!

Best, Christian

Community
  • 1
  • 1
crispy
  • 5,737
  • 4
  • 33
  • 45
  • Have you tried using @import in your CSS to get around the 4095 cap? (Shouldn't it be 4096?) – LastCoder Aug 05 '11 at 13:50
  • In Sass, you @import partials that become part of a large CSS file. And yes, it's 2^12 - 1. – crispy Aug 05 '11 at 14:03
  • 1
    Don't forget that IE also has a limit on the number of CSS files (31, I think), so if you're splitting the file, beware of that also. – Spudley Aug 08 '11 at 11:55
  • Yeah, of course. But I think 31 * 4095 selectors should do it. ;) It is also said that each stylesheet can only by 288KB of size. I cannot confirm that; my stylesheet with 4095 selectors is 363KB and works just fine. – crispy Aug 09 '11 at 06:32

3 Answers3

6

Mixins are usable across multiple files. However, it is logically not possible that @extend may work with multiple files. It is the purpose of this directive to result in a single rule (which should not be duplicated across multiple files). Therefore, I cannot split up files.

Thus, I implemented a splitter: https://gist.github.com/1131536

After these two commits have found their way into Sass and Compass, you can use the following hook in your Rails config/compass.rb in order to automatically create the additional stylesheets for IE:

on_stylesheet_saved do |filename|
  if File.exists?(filename)
    CssSplitter.split(filename)
  end
end

Update:

The CssSplitter mentionend above has been release as a gem: https://github.com/zweilove/css_splitter

jhilden
  • 145
  • 1
  • 6
crispy
  • 5,737
  • 4
  • 33
  • 45
  • I was able to install this successfully, with one caveat: the new stylesheets aren't automatically included in the head of my file. Thus, the following code needs to be included along with other stylesheet links: `<% Dir.glob("public/stylesheets/compiled/screen_*").each do |file| %>` `<%= stylesheet_link_tag file.sub(/public\/stylesheets\//, '').sub(/\.css/, ''), :media => 'screen, projection' %>` `<% end %>` – Ryan Atallah Jan 27 '12 at 05:49
  • Is there a solution to this problem available yet for the asset pipeline? If the compass `on_stylesheet_saved` callback is never called, how can I pass the compiled css files to the CssSplitter through a Sprockets engine? I've tried @crispy's fix located https://gist.github.com/2398394, but it doesn't appear to work (evidenced by my own experiences and other comments). – Ryan Atallah Aug 25 '12 at 21:41
  • There is a solution available for the asset pipeline: http://stackoverflow.com/questions/12126118/rails-asset-pipeline-solution-for-ie-4096-selector-stylesheet-limit/12134327#12134327 – crispy Aug 26 '12 at 22:21
  • Unfortunately this CssSplitter doesn't handle splitting CSS files which use media queries :( – Pete Hodgson Jan 11 '13 at 18:57
1

An easy way to do it is http://blesscss.com/. Simply :

  • install node.js
  • Execute npm install bless -g
  • blessc source.css output.css
Yassin
  • 1,376
  • 18
  • 18
1

If you can't reduce the number of selectors, there is no choice other than to split the CSS file.

Your proposed solution for doing so already sounds optimal, if a little complicated to implement.

thirtydot
  • 224,678
  • 48
  • 389
  • 349