Block Supports: Add background clip support and combined UI for text gradient selection#76171
Block Supports: Add background clip support and combined UI for text gradient selection#76171aaronrobertshaw wants to merge 12 commits intotry/background-gradient-supportfrom
Conversation
|
Size Change: +2.99 kB (+0.04%) Total Size: 6.89 MB
ℹ️ View Unchanged
|
|
Quick update, as there's been a lot of exploration here but a perfect solution has been hard to come by. The explorations have mostly focused on how the background panel should behave when text gradients are supported. The complication here is that a text gradient is not a separate setting. It is composed from two background support values:
The color panel's text gradient control sets both of those values. The background panel also exposes controls for gradient and background clip. That means two different panels can manipulate the same underlying data. Because of that overlap, I explored several approaches: Option 1: Fully transparent shared stateBoth panels simply reflect the raw underlying values. If a text gradient is active, the background panel shows whatever those values imply. That means the gradient control may appear with a value and the clip control may show text. Pros Cons Option 2: Hide gradient when a text gradient is activeIf backgroundClip === 'text', the gradient control is hidden from the background panel. Pros Cons Option 3: Smart hasValue handlingTreat the text-gradient combination as “no value” for the background panel controls so they do not auto show. Pros Cons Option 4: Smart hasValue plus smart reset behaviorSame as option 3 but with reset logic that preserves the text gradient when reset is triggered from the background panel. Pros Cons Option 5: Disable background controls when text gradients are supportedAnother possible direction was to disable the background gradient and clip controls entirely when text gradient support is present. Pros Cons Because the background support APIs already allow these combinations, removing the controls would effectively reduce capabilities that currently exist. Option 6: Separate ownership (The chosen option)The approach that seemed to provide the best balance is to separate ownership of the shared values. The key idea is that each panel should primarily manage the state it conceptually owns rather than both panels trying to co own the text gradient configuration. This results in the following behavior. Reset behavior follows the same ownership model. Why the background controls are still presentEven when text gradient support exists, the background gradient and clip controls are still exposed because those features already exist independently of text gradients. The goal was to avoid removing flexibility that theme authors or advanced users might rely on while still keeping the text gradient workflow anchored in the color panel where it is introduced. ResultThis approach avoids controls appearing or disappearing unexpectedly while still preserving the full flexibility of the background support system. It also keeps reset behavior predictable and keeps the text gradient workflow centered in the color panel where users would expect to find it. |
- Add background.gradient to block.json and theme.json schemas - Add STYLE_PROPERTY entry (backgroundGradient) in constants.js - Add gradient to VALID_SETTINGS, VALID_STYLES, PROPERTIES_METADATA, INDIRECT_PROPERTIES_METADATA, and APPEARANCE_TOOLS_OPT_INS in class-wp-theme-json-gutenberg.php - Enable gradient globally in lib/theme.json - Add gradient setting in global-styles-engine get-setting.ts
- Add gradient property to BackgroundStyle type definition - Update JS style engine to combine gradient and backgroundImage into a comma-separated background-image CSS value - Add gradient definition to PHP style engine class - Update compute_style_properties in class-wp-theme-json-gutenberg.php to collect both gradient and backgroundImage before passing to the style engine for combined background-image CSS output
- Update background.php render support to handle gradient values, including combined gradient + background image - Add safecss_filter_attr_allow_css filter in kses.php to allow combined gradient+url() background-image values that WordPress core safecss_filter_attr() strips
- Add gradient picker to background-panel.js using ColorPanelDropdown with preset slug encoding/decoding - Suppress color panel gradient tab when background.gradient is enabled to avoid duplicate gradient UIs (color-panel.js) - Update hooks.js to preserve gradient presets for blocks with background.gradient support and disable gradient settings for blocks without support - Add gradient detection in background.js and useBlockSettings in utils.js - Add background panel SCSS styles with hasInnerWrapper pattern - Add slot className for inner wrapper in styles-tab.js and block-inspector/index.js
- Opt Group block into background.gradient in block.json - Update core-blocks.md and theme-json-living.md documentation
- PHP: background block support tests for gradient rendering - PHP: theme-json tests for gradient in compute_style_properties, remove_insecure_properties, and appearance tools opt-in - PHP: style engine tests for gradient CSS generation - JS: style engine tests for gradient and combined gradient+image
The gradient pattern in gutenberg_allow_background_image_combined only matched rgb()/rgba() inside gradient functions. Gradients using hsl(), oklch(), lab(), or other color functions with parentheses were stripped when combined with a url() background image. Broaden the nested parenthesis pattern to allow any single-level nested parens, covering all CSS color functions. Add KSES tests to the background block support test suite verifying combined gradient and url() values survive safecss_filter_attr() across color formats.
…class Replace the gradient control's per-item border workaround and the image control's inline border with a reusable `.block-editor-background-panel__item` class that handles grouped border and radius styling for all panel items.
272f719 to
895fab7
Compare
80cdd52 to
7c6702f
Compare
|
There's still a long way to go but I ironed out a few kinks here over the weekend. I'm not suggesting the UX is perfect only that this PR now provides something tangible that people can play with and see how it truly feels. Hopefully, this will spark some further ideas or help us coalesce around an ideal path forward. Here's a quick glimpse at the latest state (also added to PR description) TextGradient.mp4Regarding all the test failures, I'll get to those early next week. For now, I just wanted to be able to move the UX discussion forward. |
7c6702f to
cd7e90b
Compare
|
Flaky tests detected in 5de5cb0. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/22833658675
|
|
I just want to validate, from a glance, that this direction looks good to me, thanks for working on it! |
|
For anyone else following along, the work in the following PRs, including this one, likely need a general direction to be settled on before we can progress them much further:
Depending on general confidence in the UI, we could look to land the first two PRs above with the view to iterate on them quickly. |
I've just found time to digest this. The separate ownership option (6) makes sense to me:
Reset behavior follows the same separation, right? Sounds clean and predictable. Just to confirm what happens when a user changes the clip dropdown in the background panel from text to border-box (or any other value) while a text gradient is active. Is that even possible? I'm understanding that the gradient value carries over to the background fill? Anyway, I think you've made the right trade offs. |
I appreciate yet again the patience, the exploratory work. The value of these gradients is extremely real, and worth landing in some shape or form as soon as we can. So we need both a near term and a long term plan for this. It all relates to what I oultined here as well, we have built up a complex IA of dependencies, where a mix of color-adjacent things live as Items in an ItemGroup, based on the limitation that background is one thing and color is another. In fact we may decide that to remain the correct path forward, separating concerns, and lessening the focus we've had on layering where a "solid" can be a part of a But it is worth mapping out, so we reach all the corners, including the one where you might want an animated gradient on link-hover. We either plan for that to become a possibility to grow into, through the right IA from the start, or we cauterize that opportunity from the start. Both are valid, and I will connect with some designer folks for a chat this week so we can plot this out. Ideally we also end up with an answer to this:
|
0567753 to
92d1b99
Compare

What?
This PR builds on top of two in-progress PRs:
color.gradientwrites abackgroundCSS shorthand that conflicts withbackground-clip; having the gradient onbackground.gradientkeeps both in the same property groupIt reworks the UI and UX of background clip in the following ways.
Why?
The original background clip PR scoped the control to Global Styles only and left open questions about how clip interacts with gradient text (a common use case), how the control should look, and where it should live. This PR answers those questions.
How?
Text gradient integration in the Color panel
A gradient picker is added to the Color panel's Text section, allowing users to apply gradient text without leaving the color-focused context. This stores its value at
background.gradientwithbackgroundClip: 'text', the same properties used by the Background panel.Because both panels write to the same location, they must coordinate:
text. This lets users switch clip mode directly from the Background panel. Changing away fromtext(e.g. toborder-box) reveals the gradient control with the existing value, creating a natural "convert text gradient to background gradient" flowbackground.gradientandbackground.backgroundClipwhen the text gradient is setbackgroundClipwhen it is'text', preventing invisible text if reset is triggered while a text gradient is activehas-backgroundblock class is suppressed when the gradient is being used as a text fill, since the gradient is not painting the block's background in that caseBackground panel styling
The background panel mixes two kinds of items:
ColorPanelDropdownitems (which usestyle.scss's shared border/radius system via the__itemclass) and plainToolsPanelItemelements (background image, clip). This required targeted CSS overrides in a newbackground.scssto:Testing Instructions
Textas the active value).Screenshot
TextGradient.mp4