Drupal 8 Theming: Defining file organization with SMACSS

Drupal 8 Theming: Defining file organization with SMACSS

Drupal 8 is here, and so is the new theming engine powered by Twig. As Drupal themers new to D8, we’ll begin to learn the new syntax and evolve to configuring our themes with .yml files. Along with these API changes, there are also new conceptual changes that, maybe, haven’t garnered the same level of attention. Our previous article covered the introduction and concepts of libraries in Drupal 8’s new theme layer. Continuing from there, let’s review how you can use the SMACSS structure to define your file organization.

What is SMACSS?

SMACSS is one of many modular CSS philosophies. You may also have heard of OOCSS, Atomic CSS, and BEM to name a few more. These development philosophies focus on the organization and componentization of CSS. They aim to provide guidelines for code that have a clear separation of concerns. Given the use of SMACSS in Drupal 8, we are going focus on the file organization aspect of this philosophy.

Components & CSS (or SASS) partials

As mentioned above, this philosophy focuses on the componentization of your CSS. What does this mean? A CSS component is a standalone section of code that styles a very specific element on a webpage. This could be your main navigation, a call to action block, or a news teaser. When you have defined a component, it is recommend that the code is in its very own file -- these are called CSS (or SASS) partials. This means you may have dozens of CSS files, and many of them may only be 10 - 25 lines long. Now that we have dozens of separate CSS files, what do we do with them?

Folder Structure

We focused on components above because they will probably make up the majority of your code partials when you are implementing a modular CSS philosophy. However, there are additional categories of code. These categories directly correlate to the folder structure that is recommended by SMACSS.

  • Base: First, your base folder will contain a reset.css or normalize.css file if applicable. After that, this is where you want to store all of the styles for your base HTML elements. So this could be: h1, h2, h3, strong, em, blockquote, etc.
  • Layout: This refers to the larger structural layout of your website. Many of us rely on a SASS or CSS grid system like Bourbon Neat, Foundation or Susy. This is a great example of how to separate layout styles from our components.
  • Components: A component should be a responsive, reusable element that can be placed anywhere on your site. This means it will not have any predefined size and it will not care which page region it is placed in. When this type of configuration is required, you should be using additional layout classes that can be added to a component as needed. Note: If you read more into SMACSS, you will notice this category is actually called modules. In the context of Drupal, we use component to avoid confusion with core or contrib modules.
  • Theme: Commonly described as visual styling for a component. However, I prefer to think of it as style overrides because your component will have visual styling as well. The theme category comes into play when a single theme needs an alternate visual style -- like a colour scheme. This folder could contain additional files like dark.css or red.css that will apply styles that override what was previously defined in the component.

Apply SMACSS to your Drupal 8 theme

As we reviewed in our previous article, you now define libraries that group your theme assets.

The following examples use Basic as the default theme. Basic is a grid based starter theme available for Drupal 7 and Drupal 8. If you were to use the examples below, you would replace the label basic with the name of your theme.

THEME.info.yml

name: Basic
description: HTML5 and SASS theme.
type: theme
core: 8.x

# Regions
regions:
  header: Header
  content: Content
  footer: Footer

# Scripts & Styles
libraries:
  - basic/global

We will build on this as we take a more in depth look at THEME.libraries.yml.

THEME.libraries.yml

global:
  css:
    base:
      css/normalize.css: {}
      css/base.css: {}
    layout:
      css/layout.css: {}
    components:
      css/components.css: {}
    theme:
      css/theme.css: {}
      css/print.css: { media: print }
  js:
    js/modernizr.js: {}
Configuration Options

With this implementation, Drupal will always load your assets in this order: base, layout, components, and theme. Even if you rearrange the order in THEME.libraries.yml, this load order will be maintained. This is because these categories have predefined weights. However, you do have the ability to modify this by adding a custom load weight.

THEME.libraries.yml

global:
  css:
    base:
      css/normalize.css: {}
      css/base.css: {}
    layout:
      css/layout.css: {}
    components:
      css/components.css: {}
    theme:
      css/theme.css: { weight: -10 }
      css/print.css: { media: print }
  js:
    js/modernizr.js: {}
Defining your own categories

Yes, you can do that! First you need to define this category with a new constant. You can do this in your THEME.theme file. The integer you provide is the load weight. When comparing this weight to the existing categories, it is helpful to know that:

  • Base = -200
  • Layout = -100
  • Component = 0
  • Theme = 200

With these default weights in mind, you can decide where your new category should be loaded.

THEME.theme

// Define custom SMACSS categories for theme.
const CSS_PRINT = 500;

THEME.libraries.yml

global:
  css:
    base:
      css/normalize.css: {}
      css/base.css: {}
    layout:
      css/layout.css: {}
    components:
      css/components.css: {}
    theme:
      css/theme.css: {}
    print:
      css/print.css: { media: print }
  js:
    js/modernizr.js: {}
But, but, I don’t wanna…

Well, no need to whine, just don’t. Dump all your files under theme.

THEME.libraries.yml

global:
  css:
    theme:
      css/styles.css: {}
      css/print.css: { media: print }
What about SASS?

I joke above, but I do understand developers have their own workflows that may conflict with defining stylesheets this manner. Many of us have embraced a component based folder structure where we already organize our sass partials into a similar structure. We let Sass compile our code to a single css file. We can’t really apply this workflow to a theme if we wish to embrace the SMACSS structure being outlined in THEME.libraries.yml. This is where placing a single Sass compiled file under theme could be the best option.

Moving forward

As we all move forward developing and adapting our theme development workflows for Drupal 8, it will be interesting to to see how we individually decide to either use or ignore these new processes that have been laid before us. Let’s keep talking about this as we begin to test these workflows in our early Drupal 8 projects.