-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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 a CSS class to all static blocks with className supports #42269
base: trunk
Are you sure you want to change the base?
Add a CSS class to all static blocks with className supports #42269
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be the hell of testing in real life. But YES I love this idea.
So if we want to apply this to the list block as well, I guess the only change that needs to be done is changing the |
Exactly! ...and updating all the test snapshots :( |
YES YES YES!! EVERY BLOCK SHOULD HAVE A CLASS! PLEASE FOR THE LOVE OF GOD I WILL KISS YOU!!
<p class="wp-block-paragraph"></p>
<h1 class="wp-block-heading wp-block-heading--h1">Level One Heading</h1>
<h2 class="wp-block-heading wp-block-heading--h2">Level One Heading</h2>
<h3 class="wp-block-heading wp-block-heading--h3">Level One Heading</h3>
<h4 class="wp-block-heading wp-block-heading--h4">Level One Heading</h4>
<h5 class="wp-block-heading wp-block-heading--h5">Level One Heading</h5>
<h6 class="wp-block-heading wp-block-heading--h6">Level One Heading</h6>
<ul class="wp-block-list wp-block-list--ul">
<li class="wp-block-list__list-item">List Item</li>
<li class="wp-block-list__list-item">List Item</li>
<ul/>
<ol class="wp-block-list wp-block-list--ol">
<li class="wp-block-list__list-item">List Item</li>
<li class="wp-block-list__list-item">List Item</li>
<ol/> EDIT. Got a little carried away there, sorry. I will help test this. |
Yes. This would be really helpful for anyone who develops themes. It has caused me no end of headaches not to have a simple and low-specificity way of targeting these core blocks without also targeting every single paragraph, list and heading.
It FEELS a bit wrong, but maybe it's ok.
Handling this via block deprecation (as discussed in #42122 (comment)) seems like it's a more 'correct' and probably simpler way to do this, and I wonder if that option has been dismissed too quickly. I get that old blocks aren't automatically migrated, but maybe that's a separate issue that would be better handled by a one-off migration tool. Re: Classic Block? So currently a paragraph "block" and a paragraph within a classic block are identical on the frontend, but with this pull they're treated differently. It's probably not a good idea to start adding classes to content within a classic block, but there's also no way to target elements within a classic block since the classic block itself isn't tagged. My personal preference would be to wrap the classic block in a |
lib/experimental/blocks.php
Outdated
$initial_whitespace = $matches[1]; | ||
$old_tag_ends_at = strlen( $matches[0] ); | ||
|
||
return $initial_whitespace . $new_tag . substr( $block_content, $old_tag_ends_at ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
function gutenberg_add_class_name_to_wrapping_tag( $block_content, $added_class_name ) {
return new WP_Html_Modifier( $block_content )
->find()
->add_class( $added_class_name );
}
``
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
update post-merge of the Tag processor.
we probably don't need a function for this anymore, though it's not a problem. this code should add the class name to the first tag in the block, which is assumed to be the wrapper.
$tags = new WP_HTML_Tag_Processor( $block_content );
if ( $tags->next_tag() ) {
$tags->add_class( wp_get_block_default_classname( $block->name ) );
}
return $tags->get_updated_html();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO we should pursue this approach. It looks very promising.
Thank you @Mamaduka ! I still want to make this happen, I just wasn't confident about this PR's approach to parsing HTML so I explored a reliable canonical approach with @dmsnell: WP_HTML_Walker: Inject dynamic data to block HTML markup in PHP #42485. That proposal is now ready for comments and reviews. I'd like to use it in this PR once it's finalized. |
One of the points of making this work dynamically server-side is to be able to toggle it on / off or even filter out what it prints. Should we have a mechanism to opt-in / out via filters? Should it be a flag in theme.json? |
@mtias Filters sound good to me. I'm not sure how a flag in theme.json would work, though. Are you thinking of a global feature switch? Or a per-block flag? |
in |
e0bd2ee
to
2e30c81
Compare
Now that the [Heading block] Add a wp-block-heading CSS class is merged and we have the Here's the solution blueprint:
The filter could perhaps be global and hinge on the Any volunteers for this one? I am currently focusing on the WordPress sandbox demo and won't have the bandwidth to revisit this PR soon. |
3d4d09a
to
0b1998c
Compare
What happened here? 😕 |
…rkup of every block with supports.classNam set to true.
@get I've replaced the original branch with take two, and accidentally closed the PR in the process :-) |
I found an easy way to proceed with this PR. It now just adds the technical capability and does not migrate any block yet. Notice how short it is now! Should we store the CSS class in the block markup, though? Because this PR requires setting
Advantage: the class name "just works" in the block editor Disadvantage: the class name pollutes the block markup An alternative would be to only add the class name to the rendered HTML without ever storing it in the markup. That would require a new supports API to:
That hypothetical API could be called, say, |
I love how terse this is now. Great work 👏 What were the concerns about having classnames in the stored markup? Is this concern documented or was it discussed elsewhere? |
Thanks for the ping!
From memory some of the prior arguments for avoiding storing things in serialized markup where we can include:
I can't remember where the earlier discussions were, I'm sorry! But the number of PRs and regressions surrounding either missing deprecations, or deprecations that require adjustment, means that I'm typically fairly cautious about changing core block markup. There are lots of times when it's necessary, but it's also pretty cool if we can build dynamic features that augment markup rather than needing it to be baked into post content.
While it would be a new API, it also sounds like it'd be quite a small API, and could potentially avoid having to add additional deprecations? If so, that sounds like it could be worth it to me. I'll copy in @aaronrobertshaw and @glendaviesnz on the discussion (just for visibility), since they've been looking at deprecations PRs lately. Thanks for looking into all this! |
I think I found one of the instances, in this comment: #38998 (comment)
If it needs to be toggled, then that points to the new API idea of |
Thanks for the ping @andrewserong and for all the hard work here @adamziel 👍 As has already been discussed, anything we can do to avoid changing saved markup for blocks and thereby also avoid deprecations is a win. One thing we should be careful of is creating a greater disparity between the editor and the frontend. It might already be part of the proposed approach but I'd like to see the same classes available on both, just without the While it might not be a problem, the addition and use of these class names might have some flow-on effects for theme.json and global styles. We have several blocks currently using simple elements as their selector. For example, take the paragraph block that uses We probably then need to consider updating the block.json selectors as part of the process of adopting |
In reference to the excellent contrbutions to the discussion above, should we then consider what @adamziel suggested above? That would:
As @aaronrobertshaw says it's important to retain the 1:1 between editor and front end where possible. I fear that if there are classes like It might be nonsense but could we consider using existing supports.className: {
serialize: false
} |
FWIW I also agree that we should avoid serializing anything unnecessary to the block markup, and I believe that is consistent with the philosophy of Gutenberg. |
Can we expect that this update will be merged? |
It's unlikely to make it to WP 6.2. The last comment indicates we'll need to revise the PR in a new direction. I'm not aware of anyone currently working on this however. |
It could be also as simple as supports.className: 'dynamic' // or `view` The question is whether this class should be also injected in |
What?
Ensures all static blocks with
supports.className === true
are rendered with an appropriatewp-block-$name
class name.It's what #42122 does for the heading block, only generalized to all blocks.
This is possible thanks to WP_HTML_Tag_Processor.
Why?
Precisely targeting blocks with CSS requires having class names that currently aren't there.
How?
By adding a
render_block
hook with the logic previously created just for the heading block.Alternatives considered
I explored leaning on
get_block_wrapper_attributes
, but it falls short:style
andclass
properties, meaning a heading block with an anchor set would lose itsid
.$block_content
but not block attributes.$block_content
.Testing Instructions
(ignore these for now)
block-library/src/paragraph/block.json
and setsupports.className
totrue
wp-block-paragraph
CSS class.cc @mtias @draganescu @spacedmonkey @dmsnell @ZebulanStanphill @getdave @scruffian @Mamaduka @carolinan @luminuu