Repository navigation
Editor: Add a background clip block support to facilitate text gradients - #13491
aaronrobertshaw wants to merge 9 commits into
Conversation
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
582fe2b to
71ac410
Compare
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
|
FYI, things are evolving on the Gutenberg PR this backports. I'll mark this as in draft until that stabilizes. |
71ac410 to
1295d58
Compare
|
@aaronrobertshaw Is this ready for review now that WordPress/gutenberg#77141 has merged? |
|
@peterwilsoncc not quite, there is a closely related PR that has changes that might be best backported in this single PR: WordPress/gutenberg#77142. That Gutenberg PR has a few more changes in the works that might need backporting too. So I'll update as I can and flag this ready once it has the full set of updates. |
1295d58 to
6d8ee2a
Compare
6d8ee2a to
4ec37c1
Compare
8ed54ed to
f0dbb85
Compare
|
Both WordPress/gutenberg#77141 and WordPress/gutenberg#77142 have now landed in Gutenberg. This backport has been updated to cover the latest from both PRs and should be ready for an initial review. |
tellthemachines
left a comment
There was a problem hiding this comment.
Other than the style engine class changes this LGTM as it's accurate in comparison with the two source PRs.
Not sure about the warnings on the theme.json class though (might be more helpful if these warnings were consistent between the two repos 😅)
Either changing the visibility of the methods to |
|
Sorry for the delay on this one. I have addressed the feedback and believe this should be good for another review 🙏 |
Adds a background.backgroundClip block support, so a block can set which box its background is painted into: border-box, padding-box, content-box, or the text itself. Clipping to the text is what gives blocks a gradient text fill. Registers the property in the style engine and theme.json, allows the declarations through KSES, and skips the has-background class when the background is clipped to the text. Props aaronrobertshaw. See #66094.
Backports the PHP from Gutenberg PR 77142. A breakpoint or pseudo state layered over a text clip now unsets the inherited gradient when it sets a box clip, and restores the text fill when it only sets a text color. See #66094.
…radient Backports the PHP from Gutenberg PR 77142. A breakpoint or hover text color on a block that supports the background clip now fills the letters again even when the text gradient comes from global styles. See #66094.
Backports the PHP from Gutenberg PR 77142. A background color on a block that clips its background to the text is clipped to the letters too, so it no longer adds has-background and the padding that comes with it. See #66094.
…lter_attr(). The 7.2.0 line for background-clip sat between the 7.1.0 line and its continuation, so the 7.1.0 transform and clip-path notes read as 7.2.0 changes. It now continues the existing 7.2.0 entry. See #66094.
…orts and theme.json.
f095d62 to
210bd28
Compare
There was a problem hiding this comment.
🟡 Changes recommended
State handling misses applicable clip styles and feature selectors, while invalid clip values can make text invisible.
5 open issues
Validate clip values before clearing images or restoring fills · New Resolve global clip styles before layering instance styles · New Include default pseudo-state when resolving breakpoint clip styles · New Include default pseudo-state in responsive cascade layers · New Apply fill escapes to feature-selector declarations · New
What changed in this PR
Backports background clipping support into WordPress’s server-side styling pipeline, enabling text gradients and box clipping.
Changes:
- Adds clip parsing, theme.json mappings, and allowed CSS properties.
- Adjusts background classes and state-specific text-fill resets.
- Adds rendering and stylesheet regression tests.
| File | Description |
|---|---|
| tests/phpunit/tests/theme/wpThemeJson.php | Tests responsive and pseudo-state clip handling. |
| tests/phpunit/tests/style-engine/styleEngine.php | Tests clip declarations and invalid values. |
| tests/phpunit/tests/block-supports/wpRenderBackgroundSupport.php | Tests clipping output and background classes. |
| tests/phpunit/tests/block-supports/states.php | Tests state escapes and fill resets. |
| tests/phpunit/tests/block-supports/colors.php | Tests background classes with clipping. |
| src/wp-includes/style-engine/class-wp-style-engine.php | Adds clip validation and CSS generation. |
| src/wp-includes/kses.php | Allows clipping and text-fill properties. |
| src/wp-includes/class-wp-theme-json.php | Generates clip styles and state escapes. |
| src/wp-includes/block-supports/states.php | Adds state layering and reset helpers. |
| src/wp-includes/block-supports/colors.php | Suppresses background classes for clipped colors. |
| src/wp-includes/block-supports/background.php | Renders clipping and adjusts background classes. |
Review effort: Balanced
| $base_clip = $base_style['background']['backgroundClip'] ?? ''; | ||
| $declarations = array_merge( | ||
| $declarations, | ||
| wp_get_state_text_clip_escape( $style, is_string( $base_clip ) ? $base_clip : '' ), |
There was a problem hiding this comment.
This is rare and the editor matches it today, so I'll address it in a follow-up.
| wp_merge_state_style_objects( | ||
| $default_root_style, | ||
| $root_state_style | ||
| ) |
There was a problem hiding this comment.
This is another rare combination, so I'll fix it in a follow-up with a test.
| unset( $base_path[ $index ] ); | ||
| $layer = _wp_array_get( $tree, array_values( $base_path ) ); |
There was a problem hiding this comment.
Same gap as the block instance case. I'll fix both in the same follow-up.
| * so those properties are not output twice. | ||
| */ | ||
| $declarations = static::compute_style_properties( $node, $settings, null, $this->theme_json, $selector, $use_root_padding ); | ||
| $declarations = self::get_state_declarations_with_text_clip_escapes( $declarations, $node, $base_styles ); |
There was a problem hiding this comment.
No core block can hit this today: only Heading and Paragraph support background clip, and neither uses a color feature selector. I'll include it in the follow-ups.

Backport of Gutenberg PRs WordPress/gutenberg#77141 and WordPress/gutenberg#77142
Trac ticket: https://core.trac.wordpress.org/ticket/66094
Adds a
background.backgroundClipblock support. A block can paint its background intoborder-box,padding-box,content-box, or the text itself, which gives a gradient text fill.This PR backports:
backgroundClipdefinition and value parser inWP_Style_Engine, with aVALID_BACKGROUND_CLIP_VALUESconstant,WP_Theme_JSON, with the vendor prefixed declarations,background-clipand its vendor prefixed companions in the KSES allowlist,has-backgroundclass when the background is clipped to the text,WP_Theme_JSONand the block states support,Box values only reset the fill color. Resetting
-webkit-background-clipwould discard the clip in Chromium.Without the escapes, a state over a text clip keeps the gradient in its letters.
The editor controls and the Heading and Paragraph opt-ins arrive with the next Gutenberg package update. Until then, the Paragraph breakpoint tests keep their current expectations, and a test block covers the text fill reset.
Testing instructions
theme.json:Use of AI
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5
Used for: the mechanical port