Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add: Descendent block styles mechanism. #41922

Closed
wants to merge 1 commit into from

Conversation

jorgefilipecosta
Copy link
Member

Part of #40318.

This PR allows a block to define the styles of its nested blocks using the same shape as theme.json.

This PR just works on the front end of the website the editor still does not reflects these styles.

API

A block that wants to allow the styling of its nested blocks can do so by setting support for __experimentalDescendentStyles as true.
That as part of its style attribute a block can include a blocks property and styles its descendants:
{"style":"blocks":{"core/button":{"color":{"background":"blue"}}}}

Testing Instructions

I pasted the following block on the editor

<!-- wp:group {"style":{"color":{"background":"#ff0000","text":"#ffd500"},"blocks":{"core/button":{"color":{"background":"blue"}},"core/heading":{"typography":{"fontSize":"25px"},"color":{"text":"green"}}}},"className":"has-link-color"} -->
<div class="wp-block-group has-link-color has-text-color has-background" style="color:#ffd500;background-color:#ff0000"><!-- wp:buttons -->
<div class="wp-block-buttons"><!-- wp:button -->
<div class="wp-block-button"><a class="wp-block-button__link wp-element-button">Buttons are blue</a></div>
<!-- /wp:button --></div>
<!-- /wp:buttons -->

<!-- wp:paragraph -->
<p>Default text color is yellow</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Headings are green</h2>
<!-- /wp:heading --></div>
<!-- /wp:group -->

Saved the post and verified the front end of the block looks like the following image:
image

@jorgefilipecosta jorgefilipecosta added Global Styles Anything related to the broader Global Styles efforts, including Styles Engine and theme.json [Feature] Patterns A collection of blocks that can be synced (previously reusable blocks) or unsynced labels Jun 23, 2022
* @param string $selector Original selector.
* @return string Scoped selector.
*/
public static function scope_selector( $scope, $selector ) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to reviewers: This function is exactly the same that exists in core I'm just making it public because it is useful and needed outside the class.

Copy link
Contributor

@andrewserong andrewserong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be a very cool feature @jorgefilipecosta! I've left a comment as a discussion point about the approach of using id-based classnames and individual style tags. I'm keen to hear if you have ideas about how we might solve some of those issues in the long-term with this block support and / or how it'd be expected to be handled in the style engine (if at all)? Some of these issues are a bit of a moving target at the moment, and can be difficult to refactor after the fact (Duotone is another example: #39054).

Let me know if you need any other context for the existing issues we're trying to tackle! 🙂

$block_nodes = $theme_json_object->get_styles_block_nodes();
foreach ( $block_nodes as $block_node ) {
$block_node['selector'] = WP_Theme_JSON_Gutenberg::scope_selector( '.' . $class_name, $block_node['selector'] );
$styles .= $theme_json_object->get_styles_for_block( $block_node );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there another way we can output these styles? The pattern of using id-based classnames and outputting additional style tags is something we're attempting to move away from in the style engine (#38167) and layout projects (#39336). Ideally it'd be great if we can reduce the amount we're relying on these approaches, as they're not covered by rendering in async contexts (e.g. the problems outlined in #35376)

I was wondering if it's possible for the styles for descendent blocks to somehow be output from the global styles sheet? I'm not too familiar with the work for this block support, but the idea of having the required styles available in the global style sheet is one of the things I'm exploring in the Layout block support refactor in: #40875

I'll also CC: @ramonjd for visibility here, since we've been discussing some of these concerns for future phases of the style engine lately 🙂

Copy link
Member

@ramonjd ramonjd Jul 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pattern of using id-based classnames and outputting additional style tags is something we're attempting to move away from in the style engine

Thanks @andrewserong

It's not just about the style engine, but long-standing issues about the quality and sustainability of our styles output. Also refer to https://make.wordpress.org/core/2022/06/24/block-editor-styles-initiatives-and-goals/ for background.

Two of them are to rein in the specificity issues caused by random IDs and to construct more semantic classnames that theme authors can rely on.

Are the unique ids required to target elements with custom CSS, unique to that element? Or for specificity?

Maybe there's not a better way to achieve what you're trying to do right now, but it'd be useful to see if we can come up with an alternative that won't compound the style quality issues theme users are already dealing with.

I can picture getting a lot of blow back from things like this:

.wp-descendent-blocks-styles-efc4caf478f4320f17d3346c4bd8a6a5 h1, .wp-descendent-blocks-styles-efc4caf478f4320f17d3346c4bd8a6a5 h2, .wp-descendent-blocks-styles-efc4caf478f4320f17d3346c4bd8a6a5 h3, .wp-descendent-blocks-styles-efc4caf478f4320f17d3346c4bd8a6a5 h4, .wp-descendent-blocks-styles-efc4caf478f4320f17d3346c4bd8a6a5 h5, .wp-descendent-blocks-styles-efc4caf478f4320f17d3346c4bd8a6a5 h6 {
    color: green;
    font-size: 25px;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering if it's possible for the styles for descendent blocks to somehow be output from the global styles sheet?

I'm also wondering if theme.json/global styles is a logical home for this behaviour.

How will this interact with the current block supports mechanism?

If this data lives in the block's attributes, will there be any editor UI to control descendant styles from the parent block?

I'm imagining something like this in theme.json

	"styles": {
		"spacing": {
			"margin": "44px"
		},
		"blocks": {
			"core/columns": {
				"spacing": {
					"padding": "22px"
				},
				"blocks": {
					"core/social-links": {
						"color": {
							"background": "kermit-green"
						}
					}
				}
			}
		}
	},

That would be the recipe for the following CSS:

body {
    margin: 44px;
}
.wp-block-columns {
    padding: 22px;
}
.wp-block-columns .wp-block-social-links {
    background-color: kermit-green;
}

Sorry if I'm rehashing old ground and asking a lot of questions! Just trying to get context. 🙇

@mcsf
Copy link
Contributor

mcsf commented Jul 7, 2022

Quick feedback:

  • If we proceed with this, we'll need a better name than descending styles to describe both the mechanism and its applications
  • Is the block type the right level for this setting, or would block-level be better?
  • What concrete block patterns can we implement with this change that we couldn't otherwise?

@luisherranz
Copy link
Member

What concrete block patterns can we implement with this change that we couldn't otherwise?

I think it's a natural evolution of the Gutenberg styling system. The way I see it, this cascading theme.json can be to Gutenberg what CSS cascading is to the Web.

Today, we can do some sort of theme.json cascading thanks to CSS. For example, setting the typography in a Group block will cascade it to their child blocks. But that CSS cascading is limited when compared to full theme.json cascading support.

I also like how this pattern elegantly solves issues that today require ad-hoc implementations:

The last one is a bit more complex because they also need a way to declare the default "theme.json overrides" of specific blocks, but it's still clear to me that this solution is headed in the right direction.

If we proceed with this, we'll need a better name than descending styles to describe both the mechanism and its applications

I couldn't agree more. It's even difficult to talk about this here on GitHub. theme.json overrides? Descendant styles/settings? 😄🤯

Is the block type the right level for this setting, or would block-level be better?

Could you please explain that one to me? I'm not sure what's the difference between the two.

The way I see it, to avoid ending up with long lists of wrappers, each container block should be able to declare descendant styles/settings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Patterns A collection of blocks that can be synced (previously reusable blocks) or unsynced Global Styles Anything related to the broader Global Styles efforts, including Styles Engine and theme.json
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants