Exploring Global Styles

Note: The code samples here are out of date. Please be sure to check out the block editor documentation for the latest on how to implement Global Styles.

Global Styles is an aspect of full site editing that will have a major impact on theme development. To further my understanding of this feature, I explored adding support for it to the block-based version of Twenty Twenty that Jeff Ong recently shared.

Some background: Global Styles aims to bring site-wide controls for things like colors, typography, and spacing into Gutenberg. The originating GitHub thread for the effort is a great primer on its goals and scope. From a technical perspective, Global Styles currently works by using CSS variables to define styles. A set of controls are being developed to allow users to edit those variables within the Gutenberg UI.

A lot of Global Styles work is still in flux, but early pieces are available for themes to experiment with. For example, while using the latest version of the Gutenberg Plugin, themes can define a base set of Global Style variables in an experimental-theme.json file. Here’s a simple example of what one might look like, courtesy of Andrés Manerio’s global styles demo theme:

{
    "color": {
        "background": "#fff",
        "primary": "#00f",
        "text": "#000"
    },
    "typography": {
        "font-scale": 1.2,
        "font-size": "16px",
        "font-weight": 400,
        "line-height": 1.5
    }
}

Each of these are automatically rendered out as CSS variables that the theme can hook into. On the front end, this equates to:

:root {
    --wp--color--background: #fff;
    --wp--color--primary: #00f;
    --wp--color--text: #000;
    --wp--typography--font-scale: 1.2;
    --wp--typography--font-size: 16px;
    --wp--typography--font-weight: 400;
    --wp--typography--line-height: 1.5;
}

Theme authors can pull those in like any other CSS variable. For example:

p {
    color: var(--wp--color--text);
    font-size: var(--wp--typography--font-size);
    line-height: var(--wp--typography--line-height);
}

To help wrap my head around this, I took Jeff Ong’s work on the Twenty Twenty Blocks theme, and adapted it to use CSS variables as defined in a brand new experimental-theme.json file. You can browse this here:

https://github.com/WordPress/theme-experiments/pull/26

This exercise was relatively straightforward. The concept really shines when thinking a little farther out though. Once I had those new variables in place, I tried them alongside an in-progress Gutenberg PR to add a Global Styles sidebar to the beta site editor. This provides a vision of how style editing might feel in the future:

This is still very early and very buggy, but the ability to modify these values globally in a single place is still very exciting. This is something my colleagues and I are looking forward to implementing into our themes when it’s ready.

In case anyone wants to dig in to the exploration, the full code and some instructions are available over in the WordPress/theme-experiments repository. Give it a test, and try adding an experimental-theme.json file to your block-based theme experiments as well.

For more information on Global Styles, follow the project board on GitHub, and consider joining the bi-weekly Block-based Themes meeting in the #theme-review channel of WordPress.org’s Slack.

Finally, if you’ve already given Global Styles a try, I’d love to hear about it! Please share your work in the theme-experiments repository, or drop a link into the comments.

A schema for Gutenberg blocks

At Jetpack we recently created a new Gutenberg block which displays “Related Posts”. This block is similar in content to the “Latest Posts” block in WordPress.org; it’s just a list of posts. The difference is the way the posts are displayed:

There are plans afoot to update the “Latest Posts” block, so that it contains an image and a post summary (see image below).

As these two blocks grow they seem to be converging on similar layouts, but with different content.

There are similar overlaps with other blocks. For example the layout of the WordPress.org gallery block could also be used to display a list of posts, as could the recently launched Tiled Gallery block. Evidently there are many layout possibilities for a list of posts!

The problem

As the number of Gutenberg blocks grows these overlaps become more obvious. As we start to build pages with Gutenberg it starts to become apparent that this is going to get very messy very quickly.

Essentially blocks have a content and a presentation element. Taking the example we began with, we can see overlap between many different types of content:

Lists of content

One type of content is a list of text, images and links. These come in many different forms, but they share the same structure:

  • Latest posts
  • List of posts in a category
  • List of post in a tag
  • Archive of posts by month/year etc
  • List of categories/tags
  • List featured posts
  • List of images
  • List of authors
  • List of [custom post type]

Similarly, all of the above types of content could be displayed in any of the following ways:

Layouts

Here are some examples of the different types of layout that this content could use:

The challenge is that each of these different types content can be displayed in each of these different layouts. If we wanted to create blocks for each of these combinations we’d end up with over a hundred different blocks. On the other hand we could build one single block which was so complex that it could display all these combinations within one block. Neither of these would be sensible solutions.

Can we use Block Style Variations?

Block Style Variations offer an API which allows us to modify the CSS for a block – they let us overlay a presentation layer on top of an existing block. This is ideal when modifying the way a block looks. However many of the layout variations I have examined above require more than just a different CSS, they need different markup and additional JavaScript.

Separating Content and Presentation

One solution to this problem could be to separate content from presentation in our blocks. What if we were able to define semantics for the content in our blocks, which could be interpreted by different layouts? This would mean users would first think about the content they wanted to show, and then all display options would be open to them.

A Shared Data Structure

The overlap between these blocks occurs because they all share the same data structure (an array of text, image and link). It would be possible to define a standard data structure that blocks can use. When blocks share a data structure, then it should be possible for them to share common layouts. This would mean a photo gallery display could be reused to display a list of posts, or a block that displays a list of recent posts could be reused to show a list of authors.

How Could this work?

“Block Transformations” are an existing mechanism which converts one block into another. At present every transformation has to be coded separately.

Could we re-imagine the way that transformations work, so that if blocks share a common data-structure, they can easily be transformed into each other, without writing custom transformation code?

Similarly, could we make changes to the way “Block Style Variations” work, so that they can apply a layout to our structured data?

Feedback

What do you think? Is this a problem? Are there other solutions I haven’t considered? Leave a comment!