If you are working with SASS you have probably a time bomb in your code base and you don't know.
I was totally happy on Monday when the customer told us that the application did't work in Internet Explorer.
We are working with Rails and Sass.
The problem seemed to be that the stylesheets weren't found.
Well, I have a Mac and I don't have Internet Explorer. So I used VirtualBox with the virtual machines that provides www.modern.ie to try to debug the issue.
I could see two things:
- The application worked in IE version >= 10
- In IE version < 10, the stylesheets were accessed (no error 404) but the site was showing as if there weren't any styles.
The designer gave us a hint: Perhaps we could use http://blesscss.com/.
What is it?
The problem appears here:
Microsoft's IE support documentation explains that in Internet Explorer 6-9:
- All style tags after the first 31 style tags are not applied.
- All style rules after the first 4,095 rules are not applied.
- On pages that uses the @import rule to continously import external style sheets that import other style sheets, style sheets that are more than three levels deep are ignored.
There are three possible solutions:
1. Use Bless.
- It splits a big css in various css. The first css make an "@import url" to the other css file.
- You need Node to use Bless.
- It isn't integrated in the assets pipeline of Rails.
- It is integrated in the assets pipeline of Rails.
For every solution, you need to know which css has more than 4095 rules. My question was, how do I know that?
First I obtained a list of css files with a command like that:
find . -name "*css" > css.txt
Then I loaded the css_splitter gem in my project, and in "rails c" I defined the following method:
def count
IO.foreach("css.txt") do |line|
puts line.strip
puts CssSplitter::Splitter.count_selectors(line.strip!)
end
end
Run the method and.....
The winners are!!!!
- ./public/assets/application-c5f01626ddcd1f522b8a7f16cecf3355.css with 11,575 selectors
- ./vendor/assets/stylesheets/libs/<util>/<util>.css with 9,759 selectors
The files in the project are structured like this:
app
assets
stylesheets
application.css.scss
@import "screen";
vendor
assets
stylesheets
screen.css
@import "libs/<util>/<util>";
libs
<util>
<util>.css
The assets pipeline of Rails precompiles application.css.scss with all the @import and create a file with all the selectors:
./public/assets/application-c5f01626ddcd1f522b8a7f16cecf3355.css
But, which css should I split? The one in public/assets or <util>.css?
I tried to use the gem css_splitter but I wasn't able to make it work. So I used other approach.
I installed node and npm on my machine. I executed blessc -f <util>.css. This command overwrites the original file. At the end I had three files:
vendor
assets
stylesheets
libs
<util>
<util>.css
@import url('libs/<util>/<util>-blessed2.css');
@import url('libs/<util>/<util>-blessed1.css');
<util>-blessed1.css
<util>-blessed2.css
Now the number of selectors were:
./public/assets/application-d618a047f651d19af56d0e3e9132fba3.css ------> 3,387
./vendor/assets/stylesheets/libs/<util>/<util>-blessed1.css -------------------> 4,095
./vendor/assets/stylesheets/libs/<util>/<util>-blessed2.css -------------------> 4,093
./vendor/assets/stylesheets/libs/<util>/<util>.css -------------------------------> 1,571
Ok, but where is the magic? The key is that inside <util>.css we are using @import url. We aren't composing a big file, the file is calling others files using the URL.
But, we have still a problem. Rails creates dynamic names for assets. It concatenates a digest to the asset name, for example, ./public/assets/application-d618a047f651d19af56d0e3e9132fba3.css. So we can not call simply to libs/<util>/<util>-blessed2.css.
But, we have still a problem. Rails creates dynamic names for assets. It concatenates a digest to the asset name, for example, ./public/assets/application-d618a047f651d19af56d0e3e9132fba3.css. So we can not call simply to libs/<util>/<util>-blessed2.css.
No problem, we have solution for almost everything.
We are using sass-rails, so we can use the helper asset_path inside the css file. The steps are:
- Rename ./vendor/assets/stylesheets/libs/<util>/<util>.css to ./vendor/assets/stylesheets/libs/<util>/<util>.css.erb
- Inside ./vendor/assets/stylesheets/libs/<util>/<util>.css.erb, we wrote:
@import url(<%= asset_path 'libs/<util>/<util>-blessed1.css' %>);
- In the file config/application.rb I added the new files in the property config.assets.precompile:
Remember, I only used the gem css_splitter for the selector count, don't leave it in your Gemfile!
I hope that this post helps you.
I am enjoying this wonderful chocolate with salt, I deserve it!
Nice bug and nice solution.
ResponderEliminarOther solution : write in your customer contracts that you only support the latest 2 major versions of each browser. As IE11 is the latest version, you wouldn't have to support IE9 and less :).
A nice idea :)
Eliminar