Maintainable CSS architecture in the Gutenberg era

I had fun time talking about maintainable CSS architecture in the Gutenberg era in WordCamp London and in WordCamp EU.

Especially in #WCEU I had a change to talk about CSS with lot’s of people. Thank you all for your questions and challenging the thinking behind my talk ideas.

In this post I’ll go through the CSS architecture in text format. Or you can skip it and check the slides or code:

Watch the video

At the moment track 3 video is also in Youtube and talk start at time 2:48.


I had couple of general ideas about the topic:

  • Writing scalable and maintainable CSS using ITCSS, BEM and CSS guidelines.
  • How to avoid repeating CSS in front-end and in the block editor.
  • How to automate block editor styles from front-end styles.

Pick CSS methodology

There are many CSS methodologies out there.

It’s important that you pick something, whatever rocks your boat. That’s the most important part of the maintenance. Otherwise you’ll end up adding the CSS in random places in random ways. And adding more specificity every time you are in trouble, not good.

I personally mix ITCSS and utility classes in PHP based WordPress theme.

High level goals

All of the different CSS methodologies have similar goals.

  • No conflicts with other components or visual regression when writing or updating CSS.
    • How many times we have broke something else when updating one line of CSS.
  • It should be super clear where to add or update CSS.
  • It should scale for bigger changes.
  • More efficient workflow for developers (teams) when CSS structure is clear.
  • No deep specificity.
    • How many times we have added more specificity to modify components. And then more. And then more. And then more. This needs to stop.
  • No conflicts with JS.
    • If component uses JS, developers should instantly know about it.

Harry Roberts have outlined similar CSS architecture in his guidelines. Also Jarno Rantanen has nice CSS architecture examples.

ITCSS CSS architecture

ITCSS triangle explaining the layers.
Photo credit ITCSS article.

ITCSS stands for Inverted Triangle CSS. It separates CSS codebase to several sections (layers). And every sections adds more specificity to CSS in the right order.

Here is example what CSS sections could look like in WordPress theme:

  1. Settings: global variables like fonts and colors.
  2. Tools: mixins and functions.
  3. Generic: Resets and box-sizing.
  4. Elements: unclassed HTML elements like <h1> and <blockquote>.
  5. Layouts (objects): undecorated design patterns, such as global layouts and wrappers.
  6. Blocks: styles for Core and custom blocks.
  7. Components: styles for components, such as navigation and pagination.
  8. Custom layer: If there is need for custom layer, feel free to add it in. It’s OK to be before blocks and components.
  9. Utilities: Utility classes which overwrites previous layers styles, like .screen-reader-text and prefers-reduced-motion.

For more details this is great article about using ITCSS: Scalable and Maintainable CSS Architecture.

All I can say is that I have successfully used ITCSS architecture in several large scale projects. It works.

CSS class prefixes

When working on large team with different backgrounds, class prefixes can help understand what job that class are doing. And in what layer they belong in, for example:

  • .l- for layouts, such as .l-grid
  • .c- for components, such as .c-menu
  • u- for utilities, such as .u-reset-list

Brad Frost have more details and examples in brilliant article CSS Architecture for Design Systems.

CSS guidelines and linting

Follow CSS guidelines and let linting do the hard work enforcing those guidelines. I personally use

And then enforce them using stylelint.

BEM naming convention

BEM stands for “Block Element Modifier”. It helps with our goals to keep specificity low.

  • Block is the primary component block, such as .menu.
  • Element is a child of the primary block, such as .menu__item.
  • Modifier is a variation of a component style, such as .menu–primary.

In HTML BEM classes can look like this:

<nav class=”menu menu--primary”>
   <ul class=”menu__items”>
      <li class=”menu__item”><a class=”menu__anchor”>Home</a></li>
      <li class=”menu__item”><a class=”menu__anchor”>About</a></li>

In CSS we could nest BEM rules like this:

.menu {
   &--primary {}
   &__items {}
   &__item {}
   &__anchor {}

// Compiled CSS
.menu {}
.menu--primary {}
.menu__items {}
.menu__item {}
.menu__anchor {}

And it would compile in CSS like this:

// Compiled CSS
.menu {}
.menu--primary {}
.menu__items {}
.menu__item {}
.menu__anchor {}

It’s perfectly fine not to nest CSS rules though. Ones again Brad have good article about nest or not to nest CSS selectors?

I dequeue block editor styles

I dequeue Core block styles from front-end and editor.

	function() {
		// Overwrite Core block styles with empty styles.
		wp_deregister_style( 'wp-block-library' );
		wp_register_style( 'wp-block-library', '' );
		// Overwrite Core theme styles with empty styles.
		wp_deregister_style( 'wp-block-library-theme' );
		wp_register_style( 'wp-block-library-theme', '' );

Then I enqueue almost the same stylesheet for the editor than in the front-end. The goal is to avoid much manual work. You can compare these stylesheets in the Github:

By default these are the styles which needs some extra work in the editor:

  • Typography.
  • Post title.
  • Block width, wide, and full widths.
  • Search block.
  • code block.

Adding editor-styles-wrapper class

For editor styles there needs to be .editor-styles-wrapper class added so that editor styles doesn’t leak outside the editor. There are couple of ways to do this automatically.

Nesting in SASS could look like this:

@import "settings/variables.css";
@import "tools/mixins.css";

// Editor CSS wrapper.
.editor-styles-wrapper {
   @import "elements/index.css";
   @import "blocks/index.css";

I personally use PostCSS editor styles plugin which basically adds .editor-styles-wrapper class automatically to editor styles. Config for this can be seen on postcss.config.js file.

Torque Magazine video

I also had a quick chat about with Torque Magazine. Thanks for the invite!