WordPress / gutenberg

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

Block styles: reflect inherited global styles values in block appearance controls #64670

Open ramonjd opened 2 months ago

ramonjd commented 2 months ago

The tracking issue logs tasks associated primarily with the following issue:

Blocks can "inherit" styles from theme.json and user global styles. These styles are loaded into the Block Editor as global styles CSS, meaning that block will display its inherited styles in the editor canvas.

A block's design tool controls however only reflect applied block-level styles and not any global styles values.

Consequently, even though a block may appear to have, for example, red text in the Block Editor canvas (assuming that style is defined in theme.json), the block's color controls will feature empty values.

To avoid confusion to users, a block's style controls should reflect, as much as possible, the styles that a block inherits.

Constraints

The tracking issue is deliberately limited in scope to displaying values from the merged theme.json/global styles object.

Enqueued stylesheets and theme.json custom CSS for example will affect a block's appearance in the editor canvas but they cannot be reliably parsed. Similarly, other styles inherited via the CSS cascade such as a parent block's inner element styles, or a parent with block style variation applied's inner block type styles, would likely require querying the browser element itself.

A possible "Phase 2" could be to test the performance of extracting values using getComputedStyle().

Tasks (WIP)

A corollary, and follow-up issue, is to enable "unsetting" global styles at the block level:

Related

ramonjd commented 2 months ago

Just jotting down some notes...

I've been playing around with a simple merge function (using deepmerge.all) to get an idea of the various inheritances.

1. mergedBaseThemeUserStyles[styleProperty] 
2. mergedBaseThemeUserStyles.elements[elementName][styleProperty]
3. mergedBaseThemeUserStyles.blocks[blockName][styleProperty]
4. mergedBaseThemeUserStyles.blocks[blockName].variations[variationName][elementName][styleProperty]
5. mergedBaseThemeUserStyles.blocks[blockName].variations[variationName][styleProperty]

styleProperty is an optional key as I think we pass around the full style object for blocks.

Without taking into account any special cases, it kinda works in the simple unit test I wrote, with some questions/caveats:

Missing from the above hierarchy, is the following case, even if it is one:

  1. We want the inherited styles for block 1
  2. block 1 lives inside block 2
  3. block 2 has style variation X applied to it
  4. style variation X contains styles for ['block 1']

Is that what we generally name style variation overrides?

aaronrobertshaw commented 2 months ago

Some good questions there, I'm still in the process of getting my head around all the permutations here.

Missing from the above hierarchy, is the following case, even if it is one:

In addition to what you coined as "style variation overrides", there's a similar case with a parent block instance that defines element styles.

In both cases, we'd need to be able to determine that some ancestor had applied either a block style variation or instance element styles. Different variations or element styles could be applied at different levels within the ancestor tree requiring multiple merges to arrive at something close to the final set that is seen in the editor canvas.

This sounds rather complex and resource-intensive. Further complicating this scenario, block style variations can define element styles as well as element styles within block types, within that variation.

As noted in this issue's constraints section, this is probably best delayed until we can validate approaches for the simpler use cases outlined via the above merge strategy.

jasmussen commented 2 months ago

Thanks for looking at this. As you start to dive in, I'd encourage looking for quick wins we can ship. Perfection might be good eventually, but we can also start with less, potentially. So even if one or other item on this list is addressed, it'll leave things in a better place.

ramonjd commented 2 months ago

As you start to dive in, I'd encourage looking for quick wins we can ship. Perfection might be good eventually, but we can also start with less, potentially.

Agree 100%

It's a complex area this one, and it looks like there'll be compromises to contend with at most corners, e.g., how to represent inherited element styles such as h1, so the smaller the steps, the better! 😄

aaronrobertshaw commented 2 months ago

I also agree with the "small steps and quick wins" approach.

My only concern is getting into a situation where the values in the block inspector controls appear even more hit-and-miss than they do now. This isn't to suggest we shouldn't proceed as planned but more that I'd like to keep in mind the problem we're trying to solve for the end user.