Sass in the Real World: book 1 of 4

Working with partials, manifests and globbing

With CSS, all of your code is contained in a single document and with each new feature this document increases in complexity while decreasing in readability and maintainability. Sadly, these same poor development practices have made their way into Sass development as well. To add insult to injury, it is not uncommon to see files with large blocks of code that include functional Sass like variables, functions, mixins as well the presentational selector specific Sass. While this will work in a pinch, it is not best practice to have all your code in one place.

Sass gives us the power to break our code into smaller, easier to manage chunks of code called partials. In this section we will discuss how to best break apart our Sass and how to stitch it back together via techniques like manifests and globbing.

Partials

Breaking code down to smaller chunks can be a difficult process if you do not have a good convention to follow. In the next chapter I will go into greater detail about how to best manage resources like variables, functions, mixins and presentational styles, but for now, let's understand that it is a better management technique to break out your mixins, functions, variables and presentational styles into different partials.

A partial is any file with an underscore _ preceding the name. When Sass sees these files, it will not process them into CSS files. A partial requires that it be imported into another file that will inevitability be processed into CSS in order for it to be output.

In the following example, you will see a simple Sass architecture that illustrates this principal. Notice how application.sass is the only file that does not contain an underscore _ in the name as this will be the file that is output to CSS.

stylesheets/
|-- application.sass    // Sass manifest file
|
|-- _reset.sass         // Partials
|-- _variables.scss             |
|-- _functions.scss             |
|-- _mixins.scss                |
|-- _base.sass                  |
|-- _layout.sass                |
|-- _module.sass                |
|-- _state.sass                 |
|-- _theme.sass         // Partials

You are not limited by the number of CSS files you need to output. This strategy could be used for the creation of browser or device specific styles as well. As illustrated in the following example, I have added more files for browsers like Internet Explorer and devices like mobile and tablets that I intend to output CSS.

stylesheets/
|-- application.sass        // Core manifest file
|-- IE8.sass                // Browser manifest file
|-- mobile.sass             // Device manifest file
|-- tablet.sass             // Device manifest file
|
|-- _reset.sass             // Partials
|-- _variables.scss                 |
...
|-- _module.sass                    |
|-- _state.sass                     |
|-- _theme.sass             // Partials

Manifests

When using a Sass file architecture made up mostly of partials, except for the ones that we intend to output as CSS, these output files will be your Sass manifest file(s). A manifest will manage all of the Sass partials to be imported, as well import any Compass extensions or additional Sass code libraries in your project.

Unlike standard CSS, Sass' @import directive is part of the preprocess compile of your code. This does not require additional HTTP requests when sent to the client as all your CSS will be compiled, and minified if desired, into a single document. As your project scales, you are encouraged to break your files into smaller manageable chunks of code and reassemble via a manifest.

In the following example see how I use the @import directive to load all the partials into a single document and output as CSS. Another thing to note is the absence of a file type extension. Sass or SCSS, just like Honey Badger, @import doesn't care.

@import "variables";
@import "functions";
@import "mixins";
@import "reset";
@import "base";
@import "layout";
@import "module";
@import "state";
@import "theme";

The order in which you list your imports is the order that Sass will follow when processing your code. If the selector you wrote requires a mixin to be loaded before it is used, be sure to list the file containing the mixin prior to the file that uses the mixin.

It is common place in architectures like this that all logical Sass are imported first. In the previous example you can see that I loaded all the site's global variables, then functions followed by mixins. Once these files are loaded into memory, the following Sass files, who's functions are to create CSS, will be able to take advantage of the logical Sass code. This is a pattern we will want to repeat as we get deeper into a more complex file architecture.

Take note, loading logical code into memory for remaining Sass files to take advantage of, only works with imported partials. Remember that any file without a preceding underscore will be processed and output into a CSS file. If this requires any logic to be present in order to process rules, those files must be imported first.

In the following example I will illustrate how a stand alone CSS file needs to import Sass logic before it can process the CSS rules contained within.

@import "variables";
@import "functions";
@import "mixins";

.foo {
  background-color: $default-color;
  ...
}
...

When loading additional Sass code libraries such as Compass, in order to take advantage of the library's power, you are required to load these libraries first.

On the other hand, when loading CSS from plug-in apps, is most likely that you will want to load these last as not conflict with custom selectors you have written.

As well, if these plug-in styles require customization, importing them last will allow you to take full advantage of any libraries you have imported and custom code you have written.

The following example notice how I imported Compass first so that my project specific code can take full advantage of the Compass library. At the end of the manifest I then import my plug-in flipclock library.

// Included libraries
@import "compass/css3";

// Project specific code
@import "reset";
@import "variables";
@import "functions";
@import "mixins";
@import "base";
@import "layout";
@import "module";
@import "state";
@import "theme";

// Imported plug-in libraries
@import "flipclock";

While using a Sass manifest file is a great solution, there are some additional patterns we can use in order to keep this file from becoming a giant dumping ground.

A pattern I leverage is the use of additional manifests within sub-directories. Let's say for example that you begin to create a large resource of mixins in your project. As this file grows in size, it becomes increasingly harder to mentally parse. The suggested pattern is to break this file into smaller, more digestible chunks of code and place them into a directory. Using a manifest file within that directory, you import a single reference into your application manifest and add new imports to your more specific manifest.

The following example illustrates an updated file structure with a mixins directory containing a Sass manifest file. Notice the _manifest file contained within the mixins sub-directory.

stylesheets/
|-- application.sass        // Sass manifest file
|
|-- _reset.sass             // Partials
|-- _variables.scss                 |
|-- _functions.scss                 |
|-- _base.sass                      |
|-- _layout.sass                    |
|-- _module.sass                    |
|-- _state.sass                     |
|-- _theme.sass             // Partials
|
|-- _mixins/                // Directory
|  |-- _manifest.scss
|  |-- _grid_calc.scss
|  |-- _arrow_tooltip.scss

This update requires a very simple update to my site manifest file. In the following example you will see that I updated from a simple reference to a mixin Sass file, mixins.scss, to a manifest file contained within a sub-directory, mixins/manifest.

The naming of this file _manifest.scss is purely convention. Feel free to name this file anything you like, as long as it makes sense to you and your team.

// Included libraries
@import "compass/css3";

// Project specific code
@import "reset";
@import "variables";
@import "functions";
@import "mixins/manifest";  // import sub-directory manifest
@import "base";
@import "layout";
@import "module";
@import "state";
@import "theme";

// Imported vender libraries
@import "flipclock";

Globbing

Another technique available, although not native to Sass, is file globbing. Globbing refers to pattern matching based on wildcard characters that allows Sass to assemble all the partials within a directory without a specific manifest file. Whereas I stated earlier, the order in which files are imported and processed is dictated by the order in which they are listed, this is not the case with globbing. Without a specific list to go by, Sass will assemble the files in alphabetical order.

Globbing is not the answer to all importing cases. For example, if you have a sub-directory for a UI pattern or module, it is common place to see files like _variables.sass, _mixins.sass and _module.sass within the directory. By order of the alphabet, the _variables.sass file will be loaded last. This will break the Sass processor as it is likely that the mixin or module will require a value for a variable listed in _variables.sass. In these cases I am left with coming up with a naming convention to ensure the appropriate alphabetical order. That is a really bad idea.

I strongly recommend that in the cases where a specific order of importing is required, globbing is not the answer and make use of the sub-directory manifest pattern.

On the other hand, if you have a library of code where it doesn't matter at all what the order of import is, then this is a great solution. For example, a sub-directory of animation mixins is a great use for globbing. A directory of functions, again, a great use for globbing.

Globbing is used by a lot of developers. If you are a Rails developer, this feature is made available to you via the sass-rails Gem. If you are not using Rails, Chris Eppstein has made this feature available to all users via a plug-in Gem.

In the following example I will illustrate how globbing allows me to do away with sub-directory partials. See how all the files contained within mixins are imported via the wildcard /* expression.

...
@import "functions";
@import "mixins/*";   // import sub-directory manifest
@import "base";
...

The wildcard expression / is optimal if there are no sub-directories contained within the directory you are globbing. In the situation I am using additional sub-directories, the expression of /**/ is required.

...
@import "functions";
@import "mixins/**/*";   // import sub-directory manifest
@import "base";
...

Keeping your code modular and managing an easy-to-follow manifest file will reap great rewards as your project scales. This process also will assist you in the future as you begin to engineer smarter and smarter code that you would like to reuse between projects.