Aesthetic Sass 1: Architecture and Style Organization

Sass is a very powerful extension language for CSS that gives you the ability to improve the organization of both stylesheet files and styles within these stylesheets.

Proper architecture of the files in your CSS project will ensure that you and your teammates know exactly where specific styles are, as well as where to insert new styles or modify existing styles.

Organization within the stylesheets is very important, too – the naming system, styles, and specificity of your components should be consistent across your entire project. They should also be organized in a way that mitigates conflicts and prevents leaked styles between selectors.

The articles in the Aesthetic Sass series assume basic knowledge of the Sass (SCSS) extension language. If you are new to Sass, I highly recommend you get started with this article or visit these other resources:

Architecture

Properly architecting your Sass project is a crucial starting point to having a maintainable, scalable, and well-organized project. Sass makes separating your project into logical “modules” simple with the @import directive, which acts differently than the native CSS @import directive in that it includes .scss or .sass files before the final CSS output.

You can read the documentation on the @import directive to get a good idea of how you can use it to include partial files.

There are many project architectures that you can employ in your project, and each might have their pros and cons. The important thing is that you choose one and stick with it. In this article, The 7-1 Pattern by Hugo Giraudel will be used. To summarize, there are seven folders and one main.scss file for output:

  • base/ – contains global styles, such as resets, typography, colors, etc.
  • components/ – contains each self-contained component in its own .scss partial
  • layout/ – contains styling for larger layout components; e.g. nav, header, footer, etc.
  • pages/ – contains page-specific styling, if necessary
  • themes/ – contains styling for different themes
  • utils/ – contains global mixins, functions, helper selectors, etc.
  • vendors/ – contains 3rd-party styles, mixins, etc.
  • main.scss – output file that brings together all of the above parts

Each folder should have a single .scss partial file that collects the other files in the same directory – such as _module.scss (my preference) or _glob.scss. Then, you can reference each of these in the main.scss file:


// main.scss
@import 'base/module';
@import 'components/module';
@import 'layout/module';
@import 'pages/module';
@import 'themes/module';
@import 'utils/module';
@import 'vendors/module';

Component Styling with SCSS

Most major CSS architectures — including SMACSS, OOCSS, and Atomic Design — emphasize the importance of modularity, or viewing your UI as a collection of components.

Generally speaking, components are reusable, self-contained, independent units of a user interface. Components may be composed of other components, such as a search form (composed of a text input and a button), and they may have variants, such as a smaller or different color buttons.

As previously stated, we can leverage Sass to organize our styles, both project-wide and within our components. To demonstrate this, let’s create a simple button component without architectural nor organizational concern:


.button {
    display: inline-block;
    padding: 8px 16px;
    font-size: 12px;
    font-weight: bold;
    color: #d9534f;
    text-transform: uppercase;
    background-color: transparent;
    border: 1px solid #d9534f;
    transition: all 0.3s ease-in-out;
    
    &:hover {
        background-color: #d9534f;
        color: #fcfcfc;
    }
}

Screen Shot 2015-03-23 at 7.46.34 AM

This button might look exactly how we want it to, but there are a few potential issues with the SCSS code above:

  • Too many magic numbers such as 8px, 12px, 16px, #d9534f, #fcfcfc, 0.3s, etc.
  • Inflexible theme – it’s not trivial to create a similar button with different colors
  • Explicit selector – if .button changes, it must be changed for every instance of .button in the project
  • Potential incoherency – there is no guarantee that this button’s style will fit within the general style of the project

Let’s use Sass (SCSS) to mitigate these issues.

Component Style Organization

Getting up and going with an overall file structure for your project is a relatively easy task, and the style organization within each component stylesheet will ensure that components are flexible enough to adapt to any theme and fit cohesively with all of the other components. This is the key to having an aesthetic look and feel in your website or web app. A non-trivial, well-structured component will include most of the following component-specific parts:

  • Variables – for relating component-specific values to others and preventing magic numbers
  • Mixins – for dynamically generating variations of the component (not necessary if few variations exist)
  • Structure – the CSS component layout/structure, excluding any non-layout rules, such as color
  • Relationships – any component-specific CSS with regard to relationships (via combinators) with other components
  • Themes – thematic CSS for non-layout component styling, such as background, colors, shadows, etc.
  • Exported Selectors – the manifested CSS classes/selectors, if they are to be expose

These parts can be applied to our previously-defined button component.

Variables

When adding variables for a component, two main questions should be asked:

  1. “What is this?”
  2. “How does this relate to my project’s general style?”

With this in mind, these are the variables extracted from our button example:


$button-padding: 0.5rem 1rem;
$font-size: 12px;             // 1 factor below base 16px in modular type scale
$button-bgcolor: #d9534f;     // the primary brand color
$button-border-width: 1px;    // border width for all form inputs
$button-color-hover: #fcfcfc; // the light/white brand color

This is a great start – now all of the magic numbers make sense. Once all of the necessary related base and component styles are defined, you can take this one step further by explicitly relating each variable:


// Pseudocode, for this example
$button-padding: 0.5rem 1rem;
$font-size: type-scale(-1);                // utility function
$button-bgcolor: $color-primary;           // from 'base/_colors.scss'
$button-border-width: $input-border-width; // from 'component/_input.scss'
$button-color-hover: $color-light;         // from 'base/_colors.scss'

Mixins

A component-specific @mixin can give you the ability to dynamically define a stylistic variant of a component. Pragmatically, it’s a good idea to limit what the @mixin can vary – you probably don’t want the border width to change, nor the font size to have too many variations; otherwise, it might look dissimilar from the other components.

The general structure of our example button should stay the same project-wide, but the button color will vary:


@mixin scotch-button-theme($color, $color-text-hover: $color-light) {
    color: $color;
    border-color: $color;
    background-color: transparent;
    
    &:hover {
        color: $color-text-hover;
        background-color: $color;
    }
}

Now, many different color variations of the same button can be created easily; e.g. @include scotch-button-theme(blue).

Structure

Component structure consists of rules that are not subject to many thematic variations – i.e. the layout of the component. A flexible pattern for defining component structure is to put it in a Sass %placeholder that is only @extended once by a real selector. This way, you can decide later to “remove” that component from the output CSS just by removing its real selector, without any adverse side-effects from other components that might be using that component. It also allows you to define the real selector only once, making renaming and referencing the selector easy.

Here’s the structure for our example button component. Notice how it has fewer thematic rules:


%button {
    display: inline-block;
    padding: $button-padding;
    font-size: $button-font-size;
    font-weight: bold;
    text-transform: uppercase;
    border-width: $button-border-width;
    border-style: solid;
}

Exported Selectors

This style can now be exported as a class, which I have decided to rename to .scotch-button. Included in the exported class selector is the button’s main structure and its theme:


.scotch-button {
    @extend %button;
    @include scotch-button-theme($color-primary);
 
    &.secondary {
        @include scotch-button-theme($color-secondary);
    }
}

Did you notice the .scotch-button.secondary variant? The only difference between a normal Scotch button and a secondary one is the color. Another benefit of having exported selectors separate from the actual style declarations in %placeholder is that it gives the flexibility to use different naming systems, such as BEM. In the above example, &.secondary would become &--secondary for BEM.

Conclusion

Proper architecture and style organization is crucial to developing well-developed stylesheets – they promote modular, flexible, and scalable component styles. Instead of asking yourself “where do I put this style?” or “what does this magic number mean?”, consider adopting an architecture and style organization strategy at the onset of your Sass project, like the ones described in this article.

Stay tuned for the next article in this series, Aesthetic Sass 2: Colors and Palettes!

David Khourshid

David Khourshid is a front-end web developer in Orlando, Florida. He is passionate about JavaScript, Sass, and cutting-edge front-end technologies. He is also a pianist and enjoys mathematics, and is constantly finding new ways to apply both math and music theory to web development.