Maintaining CSS doesn't get a lot of press. It's usually much more interesting to read about transition, animations and all the stuff. But today, I want to share with you some small tips I developed to better maintain my CSS. This is especially important as a project usually needs different style for mobile, tablet and big screens.
While I understand that everyone's setup is different, I also believe that there are things that we share. And one thing that we, rails developer, share is Sprockets. I got to be honest though, I didn't always like sprockets. Oh no. When it was introduced, I thought it was black magic, I had issues with stuff like precompiling assets, production vs development environment, etc.
Now, I have come to like it. I don't love it, I like it. Big difference. Enough about that, I'm not doing therapy here, I am sharing tips! So, how do I manage my CSS?
3 environments with media queries
I understand that there are usually 3 environments that I want my CSS to adapt to. Using media queries, I define three stylesheet in my layout.
<%= stylesheet_link_tag "browser", media: "(min-width: 1025px)", "data-turbolinks-track" => true %> <%= stylesheet_link_tag "tablet", media: "(min-width: 641px) and (max-width: 1024px)", "data-turbolinks-track" => true %> <%= stylesheet_link_tag "mobile", media: "(max-width: 640px)", "data-turbolinks-track" => true %>
The medias are mutually exclusives on purpose. I don't want them to overlap at any point as it would quite the confusions. I like things to be simple to reason about.
From there, I use the @import rule that CSS comes with and that sprocket leverages.
@import is to CSS what #include is to C
Actually, @import is even more flexible than #include. You can pass wildcards so it will import whole directories. So, I'll create my three environment files at the root of my stylesheet folder and include their own folders and a shared folder. The shared folder is very important as this is the reason why I find this method so enjoyable.
I start by styling everything in my shared folder and when I need to style an element differently depending on the environment, I move that style out of the shared folder and into the three environment folder.
Here's how my 3 files are setup.
@import 'browser//'; @import 'shared//';
@import 'tablet//'; @import 'shared//';
@import 'mobile//'; @import 'shared//';
I can lay out my files and folders as I'm pleased inside those folders which makes it very easy for me to organize my stylesheets.
What goes where
I said above that I start by writing all my styles in the shared folder first. I do this because I don't want to be overwhelmed with decision when I write my styles. Whenever I am in doubt, I write the style in the shared folder. That means I spend less time thinking about architectural decision and more about getting the job done.
Writing into the environment's folder is reactionary. I only write it there when I want to achieve something that I can't in the shared environment.
As soon as I do that, I look at the current rules and check if I'm not overwriting rules that I could extract from the shared environment and distribute it in each environment's folder. This way, I keep my styles simple.
This is a general guideline and you may have different priorities or ideas about how to organize your CSS. That is okay and this approach leaves you with enough room to accommodate any guidelines your team may have.
From that point, there's only one thing that I need to cover so you can use this approach: configure your stylesheets for production.
Compile your assets for production
If you don't do this step, your application will not use stylesheet in production. So you understand how important this step is. Essentially, you need to add a rule that will tell sprockets to compile those three environments files.
YourApp.configure do config.assets.precompile << /^(browser|mobile|tablet)\.(css)$/ end
With this regular expression, rails will precompile your assets and store them for your web server to use.
This is not rocket science, but it's often those small, low impact tips that help me become a better overall developer.