Implementing Global Styles in Block-Based Bosco

Editing the global styles of the Block-Based Bosco theme in the site editor

The full-site editing feature contains several sub-features. One of the key features are global styles. It will change the way developers create themes profoundly.

But what are global styles? And how does this feature simplify theme development? This article shows an example implementation in the full-site editing Block-Based Bosco theme.

What are global styles?

There are two aspects to this question.

The first is the technical aspect: global styles are a JSON configuration file. When you place such a file into the root directory of a block-based theme, Gutenberg will automatically apply it.

As with every configuration file, there is a specification you need to follow. While you can consult the documentation in the Gutenberg developer handbook, I would hold off on that. There’s a lot of information on that page, and not a lot of examples.

This makes the feature seem a lot more complex than it is. This article will introduce the concepts bit by bit, so I encourage you to first read through it before diving deeper into the subject.

The second aspect is the design objective for that feature. Meaning what is the reasoning behind this feature? The main objective for global styles is to have a single file to control all appearance related Gutenberg features.

When WordPress 5.0 introduced the block editor, it was in a quite unfinished state. Since then the Gutenberg team added features incrementally–or some might argue hazardly. And for theme developers it has been a painful experience, and the current system has reached its limits.

Limitations of the current Gutenberg customization tools

Right now theme creators have to deal with a lot of different variables:

  1. The blocks and their settings.
  2. The default WordPress block styles.
  3. Their own theme styles.
  4. Default and custom editor styles.
  5. Customization options like typography and color settings.

Furthermore developers cannot control all of these elements. An example are block settings. Yet other elements use CSS, but require painstaking work to get to the desired end result. And if there are APIs in Gutenberg, their design is often lacking.

An example would be the colour settings. To remove these, you need to use the following code:

add_theme_support( 'disable-custom-colors' );Code language: PHP (php)

To me, this makes no sense, especially because there is a remove_theme_support() function in WordPress which is designed to do just that: remove support for a feature in a theme.

With all that complexity and confusion, global styles are an opportunity to redesign the theme customization experience–both for users, and developers.

Let’s have a look at how Block-Based Bosco uses global styles.

Implementing Global Typography Styles

Block-Based Bosco uses a single serif font called Lora. The initial release used the following CSS to apply this font to all elements:

:root {
   font-size: var(--wp--custom--typography--root-size);
   font-family: Lora, Georgia, serif;
   line-height: var(--wp--custom--typography--line-height);
 }Code language: CSS (css)

Of course this only works well on the frontend. In the backend, you cannot set a font for all elements. This will cause issues with the WordPress user interface.

If you are wondering about the CSS variables like --wp--custom--typography--root-size, these were previously implemented as custom properties in the experimental-theme.json file:

"global": {
  "settings": {
    "custom": {
      "typography": {
        "rootSize": "16px",
        "lineHeight": 1.45
      }
    }
  }
}Code language: JSON / JSON with Comments (json)

Now global typography settings combine these styling instructions into a single setting:

"global": {
  "styles": {
    "typography": {
      "fontFamily": "Lora, Georgia, serif",
      "fontSize": "1rem",
      "lineHeight": "1.45"
    }
  }
}Code language: JSON / JSON with Comments (json)

Having a single place for typography settings is nice. But these styles work on the frontend (what visitors see) and in the backend (as editor styles). This is a major step forward when it comes to having a more consistent look between the editing interface and the end result on the site.

But of course not all elements on the site have these typography settings. So let’s see how we can use global styles to implement the heading styles.

Refining The Heading Styles

Each heading HTML tag from <h1> to <h6> had its own set of CSS rules:

h1 {
  font-size: 1.811rem;
  font-weight: bold;
  line-height: 1.3;
  margin: 0 0 1.811rem 0;
}

h2 {
  font-size: 1.618rem;
  font-weight: bold;
  line-height: 1.3;
  margin: 0 0 1.618rem 0;
}

h3 {
  font-size: 1.159rem;
  font-weight: bold;
  line-height: 1.3;
  margin: 0 0 1.159rem 0;
}

h4 {
  font-size: 1rem;
  font-weight: bold;
  line-height: 1.3;
  margin: 0 0 1rem 0;
}

h5 {
  font-size: 1rem;
  font-weight: bold;
  font-style: italic;
  line-height: 1.3;
  margin: 0 0 1rem 0;
}

h6 {
  font-size: 1rem;
  font-style: italic;
  font-weight: normal;
  margin: 0 0 1rem 0;
}Code language: CSS (css)

When writing global styles, you use block slug as a selector instead of using an HTML tag name. This selector is referred to as a context.

The global context applies to all blocks. This is a good baseline, and so now we can target the individual heading blocks and override specific styles:

"core/heading/h1": {
  "styles": {
    "typography": {
      "fontSize": "1.811rem",
      "lineHeight": "1.3"
    }
  }
},
"core/heading/h2": {
  "styles": {
    "typography": {
      "fontSize": "1.618rem",
      "lineHeight": "1.3"
    }
  }
},
"core/heading/h3": {
  "styles": {
    "typography": {
      "fontSize": "1.159rem",
      "lineHeight": "1.3"
    }
  }
},
"core/heading/h4": {
  "styles": {
    "typography": {
      "fontSize": "1rem",
      "lineHeight": "1.3"
    }
  }
},
"core/heading/h5": {
  "styles": {
    "typography": {
      "fontSize": "1rem",
      "lineHeight": "1.3"
    }
  }
},
"core/heading/h6": {
  "styles": {
    "typography": {
      "fontSize": "1rem",
      "lineHeight": "1.3"
    }
  }
}Code language: JSON / JSON with Comments (json)

Now that we have generic styles for headings, we still need to look at uses of these HTML tags. Post titles for example are <h2> tags, but they require a different font size to fit with the design.

Again this particular block can be targeted with a selector:

{
  "core/post-title/h2": {
    "styles": {
      "typography": {
        "fontSize": "2.4rem"
      }
    }
  }
}Code language: JSON / JSON with Comments (json)

Gutenberg then takes care of generating the right CSS styles so that the browser applies the desired font settings:

h2 {
	font-size: 1.618rem;
	line-height: 1.3;
}

h2.wp-block-post-title {
	font-size: 2.4rem;
}Code language: CSS (css)

But typography is just one aspect of a theme’s design. How about colors?

Adding Color Palettes

The Block-Based Bosco theme only uses a handful of colors:

  1. White for the background.
  2. Black for the text.
  3. Red for links.
  4. Grey for post meta and separators.

Initially these colors were only set in the CSS stylesheet, and users could override these using Gutenberg’s color settings.

But this causes issues if a user wants to undo a color customization. If he wants to reset a color to the default, there’s no way to find out what the exact color was.

I therefore added the colors as a global palette:

{
  "global": {
    "settings": {
      "color": {
        "palette": [
          {
            "slug": "black",
            "color": "#222"
          },
          {
            "slug": "white",
            "color": "#fff"
          },
          {
            "slug": "light-grey",
            "color": "#ccc"
          },
          {
            "slug": "dark-grey",
            "color": "#757575"
          },
          {
            "slug": "red",
            "color": "#c00"
          }
        ]
      }
    }
  }
}Code language: CSS (css)

Gutenberg makes these colors available as CSS variables. They can be referred to in the stylesheet, or in other global style settings. This leads to consistent settings across both of these files.

{
  "global": {
    "styles": {
      "color": {
        "background": "var(--wp--preset--color--white)",
        "text": "var(--wp--preset--color--black)",
        "link": "var(--wp--preset--color--red)"
      }
    }
  }
}Code language: JSON / JSON with Comments (json)

This reuse is a powerful tool, and allows to make styling elements both simpler, and more customizable for the user.

Styling Elements in Full-Site Editing

The header of Block-Based Bosco is simple: A centered linked site title, and site tagline.

A screenshot of the Block-Based Bosco theme header.

This is the implementation in the block-based template part:

<!-- wp:site-title /-->
<!-- wp:site-tagline /--> Code language: HTML, XML (xml)

And this is the CSS that goes along with it:

.editor-styles-wrapper h1.wp-block-site-title,
 .wp-block-site-title {
   color: var(--wp--preset--color--red);
   margin: 0;
   text-align: center;
 }
 .wp-block-site-title a {
   border: none;
   text-decoration: none;
 }
 .editor-styles-wrapper p.wp-block-site-tagline,
 .wp-block-site-tagline {
   font-size: 1.618rem;
   font-weight: bold;
   margin: 0;
   text-align: center;
 }Code language: CSS (css)

The first refactoring I did was use the block alignment controls instead of CSS to center it:

<!-- wp:site-title {"textAlign":"center"}  /-->
<!-- wp:site-tagline {"textAlign":"center"}  /-->Code language: HTML, XML (xml)

The difference might seem minor, but it’s a big win for users. With the CSS rules, the site title appeared centered, but there wasn’t an obvious reason why:

A screenshot of the Block-Based Bosco theme in the site editor: the text alignment controls do not show that the text is aligned, although visually it is.
The alignment options are all unselected, although the text is centered.

If the alignment is done through the Gutenberg interface the user interface reflects this:

A screenshot of the Block-Based Bosco theme in the site editor showing that if a block attribute is used, the text alignment controls and the visual result align.
The Align text center option is selected if a block attribute is used.

Upon reflection, these “invisible defaults” are everywhere. It’s just that we have been used to this for so long that we do not see this as not making sense.

Another example would be headings. They are usually bold, but the block editor interface does not recognize them as being bolded.

Without global styles, typography settings are visible, but not preselected in the interface.

With global styles, theme authors will be able to set all of these and other text options (italic, uppercase, etc.) for these blocks. And users will both be able to see which stylings have been applied, and they can remove or customize them.

In the future all font-styles will be preset based on the global styles.

This is currently not yet possible, but it is on the roadmap of the Gutenberg team.

With this in mind, I was able to refactor the site header styles to these global styles:

{
  "core/site-title": {
    "styles": {
      "typography": {
        "fontSize": "1.811rem",
        "lineHeight": "1.3"
      }
    }
  },
  "core/site-tagline": {
    "styles": {
      "typography": {
        "fontSize": "1.618rem"
      }
    }
  }
}Code language: JSON / JSON with Comments (json)

And this CSS:

.editor-styles-wrapper h1.wp-block-site-title,
 .wp-block-site-title {
   margin: 0;
 }
 .wp-block-site-title a {
   text-decoration: none;
 }
 .editor-styles-wrapper p.wp-block-site-tagline,
 .wp-block-site-tagline {
   font-weight: bold;
   margin: 0;
 }Code language: CSS (css)

Soon these styles will be reduced to only having the margins in there. And even these could potentially be removed with the experimental custom spacing feature.

A better theming future?

Block-Based Bosco is a simple theme. But even for such a simple theme, I was very pleasantly surprised with how much easier it is to implement theme styles with the experimental-theme.json file. Overall the direction that the Gutenberg team is taking is the right one.

There’s still lots of work to do though. It’s quite frustrating to work with a giant JSON file, especially without any validation or error reporting. If there’s even just a tiny error in the file, the styles don’t get applied without even a hint at what might be wrong,

In addition the current documentation is severly lacking. I’ve spend a lot of time experimenting with full-site editing so far, so I was able to figure things out. But I had to resort to reading Gutenberg’s source code to get the necessary insights into the workings of global styles. So it’s clear that this needs a lot more work to that developers can understand the feature right away after consulting the documentation.

Also the result of the global styles in the site editor is not consistently working. I’m not sure whether it’s this particlar feature, or just the site editor being partially broke–as it has been since its introduction.

Like many Gutenberg features, this could really be a big selling point to theme developers. Unfortunately the lack of polish and stability of Gutenberg, the absence of complete and comprehensive documentation, as well as sample implementations make it really hard to get onboard.

As I said before full-site editing is rough right now–and that’s putting it kindly. But it has so much potential that I’m optimistic about its future. As long as the WordPress leadership doesn’t shove it into WordPress Core half-baked, as it has done with so many other Gutenberg features before.

Closing words

Using global styles was just one of the aspects of full-site editing that I learned building Block-Based Bosco. By now I’ve been building themes with blocks since August 2020.

I share my knowledge about building full-site editing in the Building Block Themes course. If you want to learn how build a full-site editing compatible theme, check out the course.

Level Up Your WordPress Development Skills With One Email Per Week

Every Sunday, I send out tips, strategies, and case studies designed to help agencies and freelancers succeed with modern WordPress.

My goal is to go off the beaten path, and focus on sharing lessons learned from what I know best: building websites for clients.

100% free and 100% useful.

Feel free to check out the latest editions.