{"id":6236,"date":"2013-12-02T13:18:45","date_gmt":"2013-12-02T10:18:45","guid":{"rendered":"http:\/\/railsware.com\/blog\/?p=6236"},"modified":"2021-08-11T18:41:22","modified_gmt":"2021-08-11T15:41:22","slug":"organizing-stylesheets-in-ruby-on-rails-project","status":"publish","type":"post","link":"https:\/\/railsware.com\/blog\/organizing-stylesheets-in-ruby-on-rails-project\/","title":{"rendered":"Organizing stylesheets in Ruby on Rails projects"},"content":{"rendered":"\n<p>The asset pipeline in <a href=\"https:\/\/railsware.com\/blog\/ruby-on-rails-guide\/\" target=\"_blank\" rel=\"noopener noreferrer\">Ruby on Rails<\/a> is a very powerful, but somewhat confusing feature. By default, Rails scaffold generates a stylesheet per controller so that your styles were organized according to your application\u2019s domain model. Which is not really convenient when you are building a modular codebase and reusable components. We need to come up with some custom CSS architecture that will allow us easily create, modify and reuse elements.<\/p>\n\n\n\n<p>The asset pipeline basically performs the following: precompiles, concatenates, minifies assets and places them in the public\/assets folder. The asset pipeline is powered by the two technologies: <a href=\"https:\/\/github.com\/sstephenson\/sprockets\" target=\"_blank\" rel=\"noopener noreferrer\">Sprockets<\/a> and <a href=\"https:\/\/github.com\/rtomayko\/tilt\" target=\"_blank\" rel=\"noopener noreferrer\">Tilt<\/a>.<\/p>\n\n\n\n<p><strong>Tilt<\/strong> is the template engine that is used by Sprockets. It allows file types like sass, erb, coffee, etc. to be used in the asset pipeline.<\/p>\n\n\n\n<p><strong>Sprockets<\/strong> itself performs the asset packaging, i.e. takes the assets from all the specified paths, compiles them together and places them in the public\/assets folder.<br>How does Sprockets know which files to concatenate and in which order? Here comes a keystone of the asset pipeline &#8211; a manifest file. It uses directives to declare the files to be included and an order of inclusion. You can have as many manifest files as you need &#8211; one per layout or one pre page, that&#8217;s entirely your choice.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">CSS Preprocessing<\/h2>\n\n\n\n<p>Asset pipeline makes it easy to use any CSS preprocessors like <a href=\"http:\/\/lesscss.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">LESS<\/a>, <a href=\"http:\/\/sass-lang.com\/\" target=\"_blank\" rel=\"noopener noreferrer\">SASS<\/a> or <a href=\"http:\/\/learnboost.github.io\/stylus\/\" target=\"_blank\" rel=\"noopener noreferrer\">Sylus<\/a>. We usually work with SASS because it\u2019s awesome and it comes with a Rails app from the start.<\/p>\n\n\n\n<p>Every CSS preprocessor allows you to use functions, variables, mixins and other useful stuff that is shared across all modules and files. But in order to use them, SASS source code should be first combined and then compiled to CSS.<\/p>\n\n\n\n<p>In this case, there is an issue with using Sprockets <em>\/\/=require<\/em> syntax to specify which files should be combined together. Sprockets compiles your Sass source code first as independent stylesheets, and then merges the resulting CSS into a single file. That&#8217;s why you need to import your mixins.sass at the top of each file, otherwise you&#8217;ll see an exception if you try to use any mixin. By using the <em>@import<\/em> syntax, you are instructing the Sass compiler to combine the Sass source code first, and then perform the compilation.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">File organization<\/h2>\n\n\n\n<p>In most Rails projects, there are several layouts that have different styles, but there&#8217;s still common codebase that should be shared. So, here are some guidelines on how to organize you assets files and directories, so that they were easily extendable and had a flexible and well defined structure.<\/p>\n\n\n\n<p><strong>Base styles.<\/strong><br>All base styles that will never be changed &#8211; i.e. reset, grids, spaces and helpers &#8211; go to the base folder and are added to every manifest.<\/p>\n\n\n\n<p><strong>Manifests files per layout.<\/strong><br>First of all, you should create one manifest file per layout (if these layouts have different styles). By manifest I mean not sprockets manifest, but .sass file with all @imports of necessary files (variables, mixins, objects and modules).<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">  \/\/ Base styles\n  @import \"base\/mixins\"\n  @import \"base\/reset\"\n  @import \"base\/grids\"\n  @import \"base\/spaces\"\n  @import \"base\/helper\"\n\n  \/\/ Layout specific styles\n  @import \"application\/typography\"\n  @import \"application\/layout\"\n\n  \/\/ Objects\n  @import \"application\/objects\/buttons\"\n  @import \"application\/objects\/inputs\"\n  .......................\n\n  \/\/ Modules\n  @import \"application\/modules\/profile\"\n  @import \"application\/modules\/dashboard\"\n  .......................\n<\/pre>\n\n\n\n<p><strong>Folder for each manifest.<\/strong><br>There should be one folder for each manifest file with the same name. <em>application<\/em> folder for <em>application.sass<\/em> file as a default layout. This folder will contain layout styles, typography, all objects and modules that are used in this particular layout.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">stylesheets\n  \u251c\u2500\u2500 base\n  \u2502   \u251c\u2500\u2500 mixins.sass\n  \u2502   \u251c\u2500\u2500 reset.sass\n  \u2502   \u251c\u2500\u2500 grids.sass\n  \u2502   \u251c\u2500\u2500 spaces.sass\n  \u2502   \u2514\u2500\u2500 helpers.scss\n  \u251c\u2500\u2500 application.sass\n  \u251c\u2500\u2500 application\n  \u2502   \u251c\u2500\u2500 layout.sass\n  \u2502   \u251c\u2500\u2500 typography.sass\n  \u2502   \u251c\u2500\u2500 objects\n  \u2502   |   \u251c\u2500\u2500 buttons.sass\n  \u2502   |   \u251c\u2500\u2500 inputs.sass\n  |   |   \u2514\u2500\u2500 ..........\n  \u2502   \u251c\u2500\u2500 modules\n  \u2502   |   \u251c\u2500\u2500 profile.sass\n  \u2502   |   \u251c\u2500\u2500 dashboard.sass\n  |   |   \u2514\u2500\u2500 ..........\n  \u2502   \u2514\u2500\u2500 responsive\n  \u2502       \u251c\u2500\u2500 tablet.sass\n  \u2502       \u251c\u2500\u2500 mobile.sass\n  |       \u2514\u2500\u2500 ..........\n  \u2514\u2500\u2500 shared\n      \u251c\u2500\u2500 popup.sass\n      \u251c\u2500\u2500 markdown.sass\n      \u2514\u2500\u2500 ..........\n<\/pre>\n\n\n\n<p>Inside every manifest folder you can put responsive styles under <em>responsive<\/em> folder, divide your interface into objects and modules and put them inside the proper folder. This keeps your styles independent and modular. If you need to reuse some styles of different manifest folder &#8211; move them to a shared folder that is located on the same level as manifests.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>Proper assets organization is really important, because if you&#8217;re not doing it from the start, you will easily get lost in your stylesheets a month after the development has started. Conventions will help avoid messing styles of different layouts and slice your styles into smaller reusable parts. And, as a result, you will find everything in a designated place.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The asset pipeline in Ruby on Rails is a very powerful, but somewhat confusing feature. By default, Rails scaffold generates a stylesheet per controller so that your styles were organized according to your application\u2019s domain model. Which is not really convenient when you are building a modular codebase and reusable components. We need to come&#8230;<\/p>\n","protected":false},"author":23,"featured_media":9460,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[3],"tags":[],"coauthors":["Alex Chaplinsky"],"class_list":["post-6236","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development"],"acf":[],"aioseo_notices":[],"categories_data":[{"name":"Engineering","link":"https:\/\/railsware.com\/blog?category=development"}],"post_thumbnails":"https:\/\/railsware.com\/blog\/wp-content\/themes\/railsware\/vendors\/images\/article-thumbnail-default.jpg","amp_enabled":true,"_links":{"self":[{"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/posts\/6236","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/users\/23"}],"replies":[{"embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/comments?post=6236"}],"version-history":[{"count":60,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/posts\/6236\/revisions"}],"predecessor-version":[{"id":13938,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/posts\/6236\/revisions\/13938"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/media\/9460"}],"wp:attachment":[{"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/media?parent=6236"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/categories?post=6236"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/tags?post=6236"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/coauthors?post=6236"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}