When working on large projects, even the best CSS comments in the world only get you so far. The bigger the project gets, the more troublesome the inability to properly segment CSS becomes. Eventually, you start clobbering yourself, duplicating code, and finding it increasingly difficult to troubleshoot bugs. Last year, I finally ported the Onehub CSS framework to Sass. This provided a perfect opportunity to develop a proper organizational structure to try and avoid these kinds of problems.
Among the many benefits of Sass, is the ability to break your CSS into any number of folders and files using partials. Partials are not compiled down to actual CSS files; they are designed to be imported into other files. Creating them is as easy as appending an underscore to the beginning of your filename. This immense flexibility presents a rather subjective question:
How should I organize my project?
The following project structure is where I eventually landed. It has proven to be both easily maintainable and highly flexible.
/framework /modules /vendor /section _bootstrap.scss section.scss
This directory contains only partials and is reserved for project-wide CSS. Ideally, all of the CSS in here is as close to project-agnostic as possible. In other words, there are several files in here that could show up in any of your projects.
_defaults.scss // Global variables and Compass defaults. _media-queries.scss // Variables and mixins for breakpoints.
This directory also contains only partials and is reserved for reusable UI patterns. As a general rule of thumb, anytime you anticipate needing the same CSS more than once, you should modularize it. The more your project matures, the more CSS you should be able to compartmentalize into modules. Preferably, each module contains a mixin at the top with corresponding declarations at the bottom for including that mixin. Crafting your modules in this fashion helps you start thinking about CSS in a more modular way. They are also easier to expand upon and/or extend in the future.
_buttons.scss _icons.scss _forms.scss
This directory can contain both partials and files and is reserved for third-party CSS. I typically start with partials only, removing the underscore only if/when I need to link to a particular vendor file. In most cases, every file in here will simply be the original vendor CSS files with their extensions changed to .scss. With that in mind, this directory also contains an override partial. Any time you need to override a vendor style, write that CSS there. This allows you to upgrade a plugin at any time without losing any custom changes that you’ve made.
Section folders are where any CSS that has not (yet) been modularized lives. Depending on the project, you might have a dozen section folders or none. For smaller projects, these could be as simple as:
For larger projects though, these folders are used to signify unique areas, such as:
If you really want to keep your files neat and tidy, you could even nest additional section folders inside of each other. Be creative. The only rule I follow here is that for every top-level section folder, I create a matching top-level section file.
As the name implies, this file is designed to bootstrap any section file with the global styles for the project. This file should contain very little CSS, consisting mostly of import directives. If you’re leveraging Compass, import that here. If you’re not using Compass, you should be. If you’ve populated /framework appropriately, import the entire thing. Lastly, import any vendor files and modules that will be required by every section.
@import ‘compass’; @import ‘compass/reset’;@import ‘framework/all’;@import ‘vendor/jquery.ui.core’; @import ‘vendor/overrides’;@import ‘modules/buttons’; @import ‘modules/icons’;
Now, you can import all of your global styles into any section file with a single line of code.
Section files are the ones that will ultimately become your actual compiled stylesheets. They live at the root and, like your bootstrap partial, should consist mostly of import directives. In a perfect world, each section file would:
- Bootstrap itself
- Import any additional modules/vendor used in that section
- Import all partials from the matching section folder
For example, the section file for your Admin area might look something like:
// admin.scss@import ‘bootstrap’;@import ‘modules/forms’;@import ‘admin/accounts’; @import ‘admin/dashboards’;
The flexibility that Sass brings to your projects can be both a blessing and a curse. Fortunately, a little bit of structure can go a long way towards reinforcing your process. This is just one example of how you can organize your Sass projects to try and avoid the inherent complexities of CSS files from the past. If you have ideas on how my implementation could be improved or a structure of your own to share, let me know. Branch this post or hit me up @wanderingmatt.