WordPress / gutenberg

The Block Editor project for WordPress and beyond. Plugin is available from the official repository.
https://wordpress.org/gutenberg/
Other
10.47k stars 4.18k forks source link

Global Styles: composable styles for different contexts #27233

Closed jorgefilipecosta closed 4 months ago

jorgefilipecosta commented 3 years ago

Should we allow nested styles for semantic contexts? For example, apply a specific base font size for things inside a sidebar.

aristath commented 3 years ago

That was part of the reason why I recently converted all block-styles to use em instead of px :wink: If a sidebar is inside a group block and the group has a font-size control, then this should work out of the box

oandregal commented 3 years ago

I'd like to do some little braindump here.

At the moment, theme.json is only able to target top-level blocks ― meaning that the stylesheet generated by "global styles" creates unbounded CSS selectors: p for core/paragraph, h1 for core/heading/h1, .wp-block-quote for core/quote, etc. That stylesheet is "global" in that sense: it's not attached to any particular entity.

In the PR that introduced these semantics (and many others I find difficult to find at the moment), we also discussed how we could address nested content. Some entities we discussed were:

However, now that I've revisited those conversations and have worked more with FSE, I've realized that the main struggle the site editor is trying to fix is how to work with templates ― the same way the main struggle for the block editor was to figure out how to work with blocks.

In that sense, "global styles" is unconventional because it doesn't work with templates, it doesn't have any notion of them. Hence, my question: shouldn't it? What if there's no "global" theme.json? What if a theme.json is bounded to a template? This is, theme.json can't live in isolation but is collocated with templates: if there's a front-page.html template there can be a front-page-theme.json as well. By collocating the "theme.json" with templates we have a mechanism that:

Note that the idea would be that templates can have a theme.json, but they don't need a theme.json. You could, for example, create a single theme.json for the top-level template (index) and it'd work as today. You could also create two theme.json: one for the index template and another for the front-page template that only overwrites the specific bits you want different in the front.

What do you all think about this?

aristath commented 3 years ago

Hmmm right now we basically have 2 levels of styling:

The global styles affect the overall site styles and also act as "defaults" for blocks. If we add per-template global-styles, then we'll be adding an extra layer of complexity there and the result will be more like per-page global styles. So a completely new set of options per-template. If I change the options while editing page A, those options will only apply to that page.

If we add per-template-part global styles, we'll be able to have the "bounded" settings/options as mentioned above. So we'd be able to have different styles for the header/footer/sidebar etc as mentioned above. But template-parts are not even mandatory... I don't have to use a header template-part, it can all live in the root level. So theoretically on my theme I could add a header-theme.json file which would apply to the header template-part and allow for bounded styles like .site-header p etc. But if the user creates a template, they can just add a logo, a navigation etc directly to the page without even using the header template-part (maybe they don't even know it exists) - which would make my header styles irrelevant. The concept of template-parts is great but I don't think people building a site for the 1st time will necessarily understand them or use them, we only have a "header-content-footer" concept in our mind 'cause we've been doing this for years and understand that they are semi-separate entities. With that in mind, I'm not sure if global options specific to a template-part or even a template would be beneficial. If someone wants to have separate styles for a specific template or page, then I would assume that they will just edit the styles for each block on that specific page. If they want separate styles for a specific template-part, then they can edit the styles for each block on that template-part.

In my mind template-specific styles as well as template-part-specific styles are one-offs. They are deviations from the global, consistent styles that the global-styles enforce. As one-offs, they can/should be done on the block level, I don't think it warrants a separate json file.

oandregal commented 3 years ago

I think https://github.com/WordPress/gutenberg/pull/28533#issuecomment-769141071 by @mtias captures the direction for this. Copied verbatim below:


I see now where the difference is coming from. For me the root (or scope) is always the implicit key of the entire global style object we are dealing with. For example:

{ // implicit site root
   "styles": {},
   "settings": {},
   "blocks": {}
}

Because I think of every global styles object as something that defines a styling context and is composable. In this example site = index = root, since I guess we'd want the flexibility of specifying different settings for something like a page template vs the main index template:

// :root = body
"site": {
   "styles": {},
   "settings": {},
   "blocks": {}
}

// :root = body.page
"page": {
   ...site   /* inherits the configuration of the site and overrides specific parts */
   "styles": {},
   "settings": {},
   "blocks": {}
}

// :root = .template-part-header
"template-header": {
   ... // inherits from whatever main template contains it
   "styles": {},
   "settings": {},
   "blocks": {}
}

One scenario the above doesn't cover is a different configuration for "template-header" if it's used in "page" vs when it's used in "index", but I'm sure we can find a way to express that ("index:template-heder" and "page:template-header"). Or we might prefer to always declare sub-contexts within the "blocks" object as just "core/template-part". That's more of a detail.

I haven't been using the latest iterations in depth on a theme, so take my feedback as just my impression on the overall appearance of the system.

kjellr commented 3 years ago

Another use case here is the ability to set a specific background color (or frankly, entire palette) for a specific post/page template. For example, users might want to use a different background color for their homepage only, or they might want to use a specific accent color for certain post types.

mtias commented 3 years ago

Definitely, what the original proposal encapsulates for templates extends not just to the root one page but also to page-{id} or page-{slug}, with the cool addition that there doesn't need to be a concrete template defined as such, the theme.json object can still be attached.

jorgefilipecosta commented 4 months ago

Closing this issue as https://github.com/WordPress/gutenberg/issues/40318 can include it.