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
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
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.
An easy way to do it is http://blesscss.com/.
Simply :
install node.js
Execute npm install bless -g
blessc source.css output.css
Related
This is what I want my gem to do...once included in a Rails gem file, it will allow the developer to specify which stylesheet is the main, and which is a 'secondary'. The idea being, that all the styles in the first stylesheet take precedence over all the others - but when a style does not exist in the main, it uses the ones in secondary.
For instance, if there is body in main.css and in secondary.css, it always uses the style from main.css. But if there is alert-message in secondary.css, but not in main, the developer can use alert-message, without any fear of conflicts.
The idea basically is to allow you to leverage existing frameworks or minified stylesheets that might have classes that clash with your main.css without having to worry that your entire site/app will be messed up.
It would be awesome if I could get a general overview of the entire Rails/Ruby gem creating process - as this would be my first. Then maybe some discussions about how I might go about solving this particular problem (from a high-level is fine).
I imagine that it would require a lot of work. You'd have to extend (or write your own) CSS parser. Or come up with another way of specifying which classes are "main".
I think, the solution is much less complicated. Simply include your "main" stylesheet after all "secondaries". That'll overwrite the classes, if there are conflicts.
I would like to know what are the best ways to organise CSS code in Rails project?
I'm interested in how you do it and why.
If you would like to break up your css into multiple files during development you can add cache => true to stylesheet_link_tag and rails will automatically concatenate them into a single file in production. This also works for javascript_include_tag.
http://guides.rubyonrails.org/layouts_and_rendering.html#linking-to-javascript-files-with-javascript_include_tag
Generally, you should not have the client download a massive amount of CSS snippets, but pack them into a single file on the server to avoid rendering latencies. So you have the tradeoff of having functionality divided up into multiple files put wanting to send only one file to the client.
You could use SASS to have each piece of code inside a single include file and just include all of them together. This gives you the added advantage of mixins (kind of like macros) and variables among other awesome things.
Another possibility would be to use plain CSS and use something like Jammit to pack the stuff up to send to the client.
Regarding actual setups, I tend to have one file resetting the styles to a known default, a file for the basic layout (columns, default spaces, ...), and one file each for each area of concern for your specific design (headers, buttons, ...)
James and Holger's answers are very good.
Besides organizing CSS in my projects, I also had to change colour schemes a couple of times..
Trying to do consistent changes throughout many CSS files can be pretty painful (results may vary).
I ended up extending the Rails start-up procedure a little, to include a custom module "site_settings.rb"
through which I can define variable for colors and other CSS attributes, which I can then use throughout my CSS input files.
Whenever Rails starts up, and one of the input files has changed, it auto-generates the CSS files.
http://unixgods.org/~tilo/Ruby/Using_Variables_in_CSS_Files_with_Ruby_on_Rails.html
Since Rails 3.1 is out and sprockets replaced Jammit, here an excerpt form the Rails guides concerning the asset organization:
Asset Organization
Assets can be placed inside an application in one of three locations: app/assets, lib/assets or vendor/assets.
app/assets is for assets that are owned by the application, such as custom images, JavaScript files or stylesheets.
lib/assets is for your own libraries’ code that doesn’t really fit into the scope of the application or those libraries which are shared across applications.
vendor/assets is for assets that are owned by outside entities, such as code for JavaScript plugins.
we are working on a large web application with Rails for quite a while and produced a lot of css for our templates. Stylesheet definitions are organised in a bunch of css files that have grown with the project. As people are not always as disciplined as they should be, it seems to me that a lot of definitions have become deprecated and useless.
Is there an (semi-)automatic way to get rid of this stuff? How do you identify useless css in your project?
You can use the Dust-Me Selectors plugin for Firefox or the CSS redundancy checker.
Both are great tools that I use often and they save you hours of searching and deleting.
Another tool worth making note of also is the CSS Tidy open source project. This minifies your CSS, especially useful in these cases when you have a huge site with a huge CSS file :)
I believe the sourcecode for the CSS Redundancy checker can be found here. Ran it through the JSLint plugin at jsFiddle.net but gave me some errors, saved it for everyone here.
Not exactly a 'rails' solution but you don't always need one. I use the Dust-Me Selectors firefox plugin to find unused selectors. Works for me.
edit: kyle beat me to it
We didn't have a particularly large CSS file (about 3500 lines) and we found it sufficient to grep the codebase for each selector. (Obviously this can be semi-automated with shell pipes, xargs and friends).
Following this process, we ended up deleting a few too many CSS styles, thanks to some of our CSS style names being dynamically generated (a bad idea in retrospect).
For more detail about our workflow and results, I co-wrote a few thousand words about our experience turning the CSS from a Rails 2.x app into an asset pipeline ready, responsive and modular Rails 4.2.x SASS setup.
CSS Refactoring: From append-only to modular CSS
I'm currently working on a large, highly trafficked Ruby on Rails website and in order to get our page load times down, we are looking at spriting our background images. There seem to be a lot of tools out there but many are in the early stages of dev and many don't support some of the features we need.
Features which are important to us:
x or y repeating
automation with our rake build
transparency
generates sprite image and css automatically
mature
easy to maintain
open source
If it was written in Ruby, that would be a bonus but is not essential as long as it can integrate with a rake/cap setup.
Are there any css sprite tools out there which fit most(all?) of these criteria?
Rather than spriting images, why not use data-uri? Jammit can generate CSS files with small images compiled in as data-uri objects. This is actually even more performant than sprite sheets, because it means that you only have one HTTP connection for the stylesheet, rather than one for the stylesheet and one for the sprite sheet.
To use it, you just have your small images (icons, repeating backgrounds, etc) referenced with /embed/ in the path somewhere, and it'll generate data-uri, MHTML, and plain versions of your stylesheets for serving to various browsers.
Jammit also does compilation of multiple stylesheets (and Javascripts) into one file (per type), and can make use of some Javascript templating stuff too, if you want to get super-optimized with your AJAX responses.
Downsides are that a) if you reference an image more than once, it gets compiled in for each reference, and b) changing an image results in clients needing to re-download your whole stylesheet. However, since those assets generally change fairly rarely, it can be a solution that results in far faster page loads without adding any additional overhead to your development process.
To mitigate both of those, you could have a separate stylesheet that is just for image references, so you'd have one stylesheet for normal layouts, and then another that all your data-uri resources get compiled into. This would result in two HTTP requests, but it means that you could change your CSS or your embedded images without forcing a re-download of the whole other half of your styling.
One big negative about Chris's suggestion to use data-uri via Jammit, is that it doesn't support IE6/7.
There's this new gem called active_assets that gives you full sprite integration with your rails stack. Check it out at github. The gem let's you define your sprites including the list of images to include in the sprite and then generates the sprite and the corresponding stylesheet. The readme at the above link has all the info.
I've got some experience using haml (+sass) on rails projects. I recently started using them with blueprintcss - the only thing I did was transform blueprint.css into a sass file, and started coding from there. I even have a rails generator that includes all this by default.
It seems that Compass does what I do, and other things. I'm trying to understand what those other things are - but the documentation/tutorials weren't very clear.
These are my conclusions:
Compass comes with built-in sass mixins that implement common CSS idioms, such as links with icons or horizontal lists. My solution doesn't provide anything like that. (1 point for Compass).
Compass has several command-line options: you can create a rails project, but you can also "install" it on an existing rails project. A rails generator could be personalized to do the same thing, I guess. (Tie).
Compass has two modes of working with blueprint: "basic" and "semantic" usage. I'm not clear about the differences between those. With my rails generator I only have one mode, but it seems enough. (Tie)
Apparently, Compass is prepared to use other frameworks, besides blueprint (e.g. YUI). I could not find much documentation about this, and I'm not interested on it anyway - blueprint is ok for me (Tie).
Compass' learning curve seems a bit stiff and the documentation seems sparse. Learning could be a bit difficult. On the other hand, I know the ins and outs of my own system and can use it right away. (1 point for my system).
With this analysis, I'm hesitant to give Compass a try.
Is my analysis correct? Are Am I missing any key points, or have I evaluated any of these points wrongly?
The ideal goal is separation of style and content: it's not always possible 100%, but it can be done reasonably well by using semantic markup. Blueprint and other CSS frameworks utterly fail at this.
The original idea behind Compass was to avoid polluting HTML with the visual markup that Blueprint generates: if you're writing class="column-4" in your markup, then you might as well put style="width:160px" in there instead. Semantically it's the same meaning, and the same amount of repetition to maintain.
Compass turns a Blueprint class like .column-4 into a mixin which you can apply to a meaningful selector:
#sidebar
+column(4)
This way, you only need to maintain it in the stylesheet, not across a number of templates and HTML files.
Compass is project-aware. It will handle compiling your whole tree of stylesheets, even automatically on save when you run compass watch.
There are some very helpful functions provided by compass, for example:
image_url is a configurable function that can handle relative or absolute paths or even set up rotating asset hosts if you need to.
The CSS3 module takes care of all the browser-specific style rules for rounded corners, shadows, etc.
General utilities provide helpers for the stuff you do all the time, but with less repetition (especially for the cross-browser issues). These are some basic ones I use a lot:
+clearfix and +pie-clearfix (cross-browser clearing methods)
+float ensures you don't forget display:inline in front of it for IE... (if the time comes to drop the old IEs, it's one single change.)
+replace-text hides text and positions an image replacement background.
+hover-link adds the :hover underline rule to a base link style
You can check these out on the new docs site for Compass.
Then, Compass provides the facilities for a number of other style frameworks in addition to the built-in Blueprint. Do check out Susy for example, which is a Sass-native layout framework, not just a CSS port. It specializes in flexible and fluid grids.
'Semantic mode' refers to the possibility to use more semantic class names than the ones css frameworks ship with: .article vs .grid_1. which i personally think is a big +.
I'm not sure if these resources have only shown up recently, but have you seen the Compass CSS3 helpers and the General utilities - (both well documented in my opinion) - they've really sped up my interface builds a great deal.
Another great resource is the Compass plugins page.
Personally I like to copy these utility Sass files out the rubygem and manually include them in my project's Sass files as it feels pretty weird referencing Sass which is stored out of the project.
Compass looked like a great solution for me as well, but after trying it on a project I didn't really see the great advantage of using it for me. Like you, I'm just fine with blueprint, and I didn't see the need to add yet another layer on top of haml/sass.
I eventually stripped the compass from that project and just go with a sass version of the blueprint CSS files, and go from there. I store any custom/additional styles in a separate sass file and that's it. No need for compass or anything like that if you just want to keep it simple.