Maintaining CSS on large Drupal sites or ones that go through frequent revisions can become a nightmare if you're having a free-for-all in your stylesheets. You need structure. You need SMACSS.
SMACSS is a CSS styleguide written by Jonathan Snook. In the words of the man himself,
He goes on to say,
That line was what made SMACSS appeal to me more than any other CSS architecture. Rather than getting frustrated trying to adapt a rigid framework to our own workflow or toolset, we’re encouraged to take the principles and apply them to our work in a way that makes sense to us.
The following is my take on SMACSS and how I’ve applied it to Drupal sites. I’ll focus on the 4 major CSS rule categories: Base, Layout, Module and State.
Base styles
Base styles are your site defaults. They are applied directly to element tags. These include your reset or normalize styles. I like to think of these as the styles determining how content appears within the body content of the page.
If your content can be edited with a WYSIWYG editor, such as CKEditor, you can utilize your base stylesheet in the WYSIWYG so the content editor is seeing a little more "what you get" while they develop content. For this reason, I stretch the rules a bit and include some very basic classes that are meant to be utilized by the content editor for formatting. For instance, I'll often include an .intro
class that can be applied to paragraphs to make them a bit larger or what not. Be conservative with adding classes to your base stylesheet if you add any at all.
Layout Styles
Layout styles are used for adjusting placement and flow of major areas and components on the page. In Drupal I would classify major layout as the way regions relate to one another on a page and how blocks flow within a region. If you use Display Suite you can include the way regions within your nodes relate to one another. Similarly, if Panels is more your style, the layout classes would control how your regions relate to one another and how your panes flow within those regions.
Layout rules are typically targeted with ID selectors such as #sidebar-first
and #main
. Alternative layouts can be created with parent classes. Most Drupal sites have body classes like .no-sidebars
or .two-sidebars
. These act as layout classes. So to adjust your layout, you would write a selector like .two-sidebars #main { … }
.
If you want to get hardcore SMACSSy, replace those class names with .l-no-sidebar
and .l-two-sidebars
.
The key to layout styles, is not letting them get contaminated with other CSS concerns such as typography. As mentioned above, we use Display Suite extensively. I relegate the layout of regions to direct child selectors, often based on the view mode of a given node.
<br /> .view-mode-teaser > .ds-content { layout: stuff; }<br /> .view-mode-full > .ds-aside { grid: goodness; }<br />
While this doesn’t follow SMACSS exactly in terms of naming conventions, it achieves the same goal of keeping layout compartmentalized.
Modules (a.k.a components)
At the risk of inconsistency, I'm going to refer to SMACSS modules as components. Purely because module already has a very specific meaning in Drupal and many other areas of web design such as grid layout.
Components are individual bits of HTML. Drupal is full of components: blocks, menus, nodes etc. The key to keeping components modular is the style of a component should be consistent no matter where you place it within the page, all other things equal. For instance, the search block should look the same whether it's in the header or sidebar. If you want it to look different, subclass it with
.block--secondary
or something of that nature.If you want that search block to float right within that region use a layout class. The region a block sits within should only affect its postion or flow, never its style.
Subcomponents vs Subclasses
Subcomponents are the components or elements within a specific component. Like an <li>
within a <ul>
. These are classed with the base component name followed by a single separating '-'.
Subclasses are used to further style a component beyond its default style. I prefer to use a double hyphen '--' in my subclasses. This helps me scan the stylesheet or HTML source to distinguish between the base component, subcomponents and subclasses. I might have .btn
as a base button component and .btn--download
as a subclass that may be a different color and include a download icon.
Here are some examples of classes I typically use in a Drupal theme.
<br /> /* Navigation <em>/<br /> .nav<br /> .nav-item<br /> .nav-link</p> <p>.nav--inline<br /> .nav--main<br /> .nav--footer<br /> .nav--local-tasks<br /> .nav--actions</p> <p>/</em> You could use menu in place of nav if that tickles your fancy.<br /> I prefer nav because there are different ways of creating navigation<br /> in Drupal other than the menu module. <em>/</p> <p>/</em> Nodes <em>/<br /> .node<br /> .node-title<br /> .node-header<br /> .node-content</p> <p>.node--featured<br /> .node--event<br /> .node--page</p> <p>/</em> Fields <em>/<br /> .field<br /> .field-label<br /> .field-items<br /> .field-item</p> <p>.field--meta<br /> .field--supplement<br /> .field--complement<br /> .field-label--inline</p> <p>/</em> Buttons <em>/<br /> .btn<br /> .btn--secondary<br /> .btn--download</p> <p>.btn--next<br /> .btn--previous</p> <p>/</em> Blocks <em>/<br /> .block<br /> .block-title<br /> .block-content</p> <p>.block--feature<br /> .block--callout</p> <p>/</em> Views */<br /> .articles<br /> .articles-group<br /> .articles-list<br /> .articles-item</p> <p>.articles--featured<br /> .articles--carousel<br />
States
I like the '.is-' naming convention for state rules, such as
.is-active
or .is-collapsed
. Think of these as classes that alter the style of a component based on some dynamic condition. I mostly use these for JavaScript interactions but it can also be useful for server side contexts. For instance, you might want to include an .is-unpublushed
state class on a node if it is being shown to privileged users. There are some consistency issues with '.is-' in that Drupal is full of its own state classes that do not follow this convention. I'm looking at you .active
. I'm willing to deal with that.That's the basics of how I've started implementing SMACSS in our themes. If you're working with SMACSS on your own Drupal sites, let us know in the comments below. I'll be talking about Scalable Stylesheets at BADCamp next month. If you're going to be there and are interested, I'd love to get together and nerd out on this stuff and see how we can make Drupal core markup a bit more SMACSSy.