David Khourshid
This tutorial is out of date and no longer maintained.
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:
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 its 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
partiallayout/
- contains styling for larger layout components; e.g. nav, header, footer, etc.pages/
- contains page-specific styling, if necessarythemes/
- contains styling for different themesutils/
- 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 partsEach 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:
@import 'base/module';
@import 'components/module';
@import 'layout/module';
@import 'pages/module';
@import 'themes/module';
@import 'utils/module';
@import 'vendors/module';
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 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;
}
}
This button might look exactly how we want it to, but there are a few potential issues with the SCSS code above:
8px
, 12px
, 16px
, #d9534f
, #fcfcfc
, 0.3s
, etc..button
changes, it must be changed for every instance of .button
in the projectLet’s use Sass (SCSS) to mitigate these issues.
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:
These parts can be applied to our previously defined button component.
When adding variables for a component, two main questions should be asked:
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'
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)
.
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 @extend
ed 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;
}
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.
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!
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!