views:

56

answers:

2

I have a number of pages in my app that are showing partial FOUCs (flashes of unstyled content) upon loading, which occurs because some of them have stylesheets and/or javascript defined at the head of the document rather than in the layout. The fundamental issue is that the DOM is firing before these stylesheets are loaded.

In order to solve this issue, I imagine there are a few possibilities:

  1. Delay the DOM firing until after the additional stylesheets are loaded. This would work but it would slow the site down as we would be forcing the DOM to wait for at least two stylesheets to load in series.
  2. Leave it where it is, FOUCs and all.
  3. Move the required stylesheets to the layout to be loaded with the rest on the first go. This is performance-optimal but it interferes with a confusion of mine. I have lots of pages that use the same layout but each needs different modifying stylesheets. For example, users may use the application layout but need the users.css file, whereas products may use application layout but need a products.css file. The endpoint of this option is lots of almost identical layouts, the only difference being what css to include (horribly unDRY).
  4. An elegant technical solution I am not aware of in my intermediacy.

What is the proper way of having different stylesheets included, and is it possible to do this without duplicating layout code?

+1  A: 

Not sure if this will meet your approval, but this is what I'd do.

Modify you main layout by removing all non-generic stylesheet_link_tag invocations. Replace them with this:

= stylesheet_link_tag 'style_used_in_every_page'
- @stylesheets.each do |css|
  = stylesheet_link_tag css

And in your controller, specify which stylesheets to use for views from that controller:

def UsersController < ApplicationController
  @stylesheets = ['users', 'admin', 'print']
end

Does that make sense? Haven't tested it, but it should get you on the right track.

nfm
Thanks for your answer nfm!
sscirrus
A: 

layouts/application.erb

<body id="body-<%= content_for :body_name %>">
  ...
</body>

public/stylesheets/combined.css

#header {
  /* styles for all pages */
}

body#body-products {
  /* styles for the products page only */
}
Justice
Justice, thank you for your answer. I understand that this would select only the styles I want to apply for a particular page. Would I be correct that this would still load a huge stylesheet for each page?
sscirrus
Yes. But stylesheets typically aren't that big, and the single stylesheet, comparatively small as it is, would be cached by the browser anyway.
Justice
So it would be fine to have a combined.css sheet of maybe 3-5K rows serving up to 15-20 different discrete stylesheets.
sscirrus
Yes. Just to be sure, profile how many bytes of transfer it is (the web server should send it down gzipped) and how many milliseconds it takes. But text is highly compressible, and your combined stylesheet, when compressed for transfer, doesn't sound large at all. Also, look into CSS minification, which strips out redundant whitespace and comments. You would develop the combined.css file, and the minification step would produce combined.min.css, which is what your page would reference.
Justice
Very useful. Thank you.
sscirrus