Skip to content

🖍Global Style System #19611

Closed
Closed

Description

👋 Hello everyone!

First off, Happy New Year at all! I hope you all had the happiest of holidays.

I'd like to expand upon the original "Block Style System" issue @mtias started at #9534.

I originally proposed a concept last year in November. Even before then, the thread has evolved a lot, with a lot of exciting ideas and feedback.

This Github issue is also very much related to #19255. Serving as the technical complementary piece to the Global Styles / FSE design work that is happening!

Recap

The idea is to provide a unified system for Gutenberg blocks (core + 3rd party) and themes to work well with each other. They also have to understand and respect user overrides. These defined styles can be applied globally throughout the user's site (e.g. Declaring font scale, or colors, or how all Buttons look).

At the moment, Gutenberg only supports style customization at the per-block level. So updating a Button in one post, will not retroactively update Buttons on other pages.

Terminology

"Builders" - People who create things to help create content. Examples: Block creators, themers, plugin authors.
"Users" - People who create content.
"Backend" - Gutenberg's Editor. What the User uses to create content.
"Frontend" - Rendered site. What the User sees.


Demo

Screen Capture on 2020-01-13 at 16-33-31

I think a good way to start this one would be an interactive demo!
The demo can be found here:

👉https://9w53w.csb.app/

CodeSandbox (for code/preview):
https://codesandbox.io/s/github/itsjonq/wp-gs

Github Repo for source code:
https://github.com/itsjonq/wp-gs

In the demo, click on "Toggle Inspector" to see the style configs (outlined below)

To simulate the "loading" of a theme, go to:
https://codesandbox.io/s/github/itsjonq/wp-gs

Uncomment the following line:

//import "./load-theme";

And click the refresh icon in the browser preview (right)


Note: The code I have is mostly prototype code. Code to discover and realize the various moving pieces, and how they all fit together. I wrote it outside the context of Gutenberg to make iterations/builds faster. It also enabled me to publish it onto CodeSandbox for live code/preview purposes.


The Parts

01-parts

For my proposal, global styles is a system of setting and rendering a (giant) config. These mechanisms can be represented by 5 parts (above).

  1. Default theme styles
  2. Theme styles (e.g. Twenty Twenty)
  3. User styles
  4. Merged styles
  5. CSS Variable rendering

1. Default Theme Styles

These determine the default properties how the sites/blocks will render. These are the bare-bone essentials for rendering site's front-end. They are not opinionless, but very close to being so.

They also help establish structure when it comes to adding/updating values. For example, colors and fontSizes will always exist.

The current structure follows the semantics outlined by Theme UI spec, which is a (mostly React) based theming convention that's gaining in popularity. Of course, we don't have to use this schema :).

What qualifies as default styles?

Some core colours and typography would be a great start.

Gutenberg's core blocks have style opinions. They kind of have to. For certain blocks to be functional, they need some styling in order to work correctly on the front-end. These would qualify for default styles as well.

2. Theme styles

In the future, once Global Styles x Gutenberg is in place, one way a Gutenberg supported theme may want to customize blocks would be to include a theme.json file. The key/value pairs follow the same schema.

The .json file works similarly to the current add_theme_support() php function, but I feel like it's easier to declare.

These will add to/override the values from default styles.

3. User styles

The ability for the user to customize these values would be presented in the Global Styles editor/tool interface. The concept is very similar to the customizer.

The experience of this can be seen in my demo.

Global Styles x Blocks

In addition to updating colors or typography, (in the future) this interface can update (style based) attributes for blocks. Using a registration system (like how core/custom Gutenberg blocks are registered), block style attributes can appear in this global editing experience.

Hierarchy

User styles overrides theme styles.
Theme styles overrides defaults.

Leading us to...

4. "Merged" styles

This is the consolidation of User > Theme > Default styles. These are consolidated and enhanced to prepare the values to be rendered.

Enhanced with "plugins"

03-transforms

A mechanism I built into the system allows for Builders to modify/enhance values from the style config. For example, in the above screenshot, the original single text value has become an array of various color shades. This is applied to any color value under the colors key.

With my prototype, this is how a plugin may look like:
https://github.com/ItsJonQ/wp-gs/blob/master/src/global-styles/plugins/color-scheme-plugin.js

By interpolating/enhancing values, we can improve and simplify the values to be rendered with CSS

5. CSS Variable rendering

Finally, the defined and enhanced styles are rendered via CSS variables. The last stage of the system flattens and transforms the data into CSS variables.


Global Styles x Blocks

For blocks to start using global styles, their CSS will need to be refactored to use the CSS variables outputted by system.

Example:

.wp-block-button {
	box-sizing: border-box;
	border: 1px solid var(--wp-gs-color-primary-dark20);
	display: inline-flex;
	font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
		"Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans",
		"Helvetica Neue", sans-serif;
	line-height: 1.2;
	font-weight: bold;
	text-decoration: none;
	cursor: pointer;

	background-color: var(--wp-gs-button-backgroundColor);
	border-radius: var(--wp-gs-button-borderRadius);
	border-width: var(--wp-gs-button-borderSize);
	box-shadow: var(--wp-gs-button-dropShadow);
	color: var(--wp-gs-button-textColor);
	padding: var(--wp-gs-button-padding);
}

Global Styles x Themes

With this system, the overhead of styling blocks outputted from Gutenberg has been tremendously reduced. By leveraging a theme.json file, the Themer has a lot of controls over the visuals of the WordPress x Gutenberg. Better yet, they will be able to confidently adjust the visuals of custom blocks as well (assuming they're using global styles).


Rendering on the Front End

Similar to how Gutenberg blocks are saved/rendered, we can save and store the outputted HTML from Global Styles. This HTML contains the generated variables, which can be injected into the head via PHP, meaning there's not variable/style consolidation required on load. It's already been done.

Any change made to global styles will trigger a save, following the mechanism that Gutenberg has for its blocks.

This style generation mechanism needs to be triggered regardless if Gutenberg is loaded or not. For example:

A user installs and opens WordPress for the very first time. They download and activate a custom theme (with global styles support). They view their site, without having written a page/post yet. The site should render correctly.


Customizing rendering of "sections"

Since UI on the front-end will be rendered with CSS Variables, we will be able to customize how blocks render in "sections" in a robust manner.

For example, your site is white with black text, but your sidebar is black with white text.

Certain blocks that get added to your sidebar need to adjust their colors to be readable. From a technical standpoint, this can now be done by inline styling a CSS variable, example:

<div class="wp-sidebar-block" style="--wp-gs-colors-text: white;">
  ...
</div>

For those who made it to the end of this very long post, thank you!

🙏 🙏 🙏 🙏

There are a lot of moving parts for this idea. We're still very early days. I'm sure there are a lot of nuances and edge cases that I haven't thought of yet. Which is why I'd love to hear from everyone!

Thoughts and feedback are 💯 welcome.

Thank you so much for your time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    Global StylesAnything related to the broader Global Styles efforts, including Styles Engine and theme.jsonNeeds Technical FeedbackNeeds testing from a developer perspective.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions