Block Supports: Add background gradient support that can combine with background images#75859
Block Supports: Add background gradient support that can combine with background images#75859aaronrobertshaw wants to merge 13 commits intotrunkfrom
Conversation
|
Size Change: +1.25 kB (+0.02%) Total Size: 7.69 MB
ℹ️ View Unchanged
|
|
Flaky tests detected in 0567753. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/23574013872
|
6c9ca1f to
5208c81
Compare
5208c81 to
272f719
Compare
|
Just noting that their might be additional unexpected use cases to drive the need for this improvement for background support. To implement text gradients we can't be modifying the shorthand Leveraging this |
- 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
|
Just a quick update here to note that this proposed |
|
Thanks for the discussion everyone 🙇
@jasmussen there's a good chance that paragraph blocks will not only have a single item inside for long. With #76171 and planned follow-ups, the paragraph block would also get the background image and optional clip control. So it will fill out more rather than appear as an afterthought. Additionally, perhaps it would be better then for #76171 if the "text gradient" selection were its own control rather than a gradient tab within the text color popover and "Foreground" panel.
The renaming of the Background Image panel to Background was proposed here. I initially didn't include it here mostly in that all the current background controls were all still background images (including gradient) I intended to seek design feedback there to settle on a course of action for the Color panel. Reworking the Color panel's background to the Background panel and renaming the panels themeselves might be best as an immediate follow-up to this. |
This PR is slightly related, though it might be outdated: |
|
Thanks for sharing that link @ramonjd, I missed adding it 👍 I'm starting to wonder if we should also give the background color the same treatment as the background gradient here. I mean, in this PR we are creating a new block support so that we can assign the resulting style to a new CSS property free of backward compatibility concerns. If we did the same, creating a If we complete the process to shift away from the shorthand |
Nice. That said, as a tools-panel I'd default those controls to not show by default for paragraphs. The fact that we show background by default is already slightly a stretch since it's a much better user experience to set a background on a container.
I actually still think that a tab inside the popover is the best path forward for this, and one that organically matches the term "foreground" very well. It's a separation of concerns, and it follows design precedence: items in the background panel already have gradient tab, now items in the foregrond panel do as well. It even makes it potentially simpler to add background images to foreground items; we'd need a redesign of the tabs to fit it (perhaps towards icons), but it's a good place to put them. I think the strongest reason for having these separate panels for foreground and background is actually the parallel layering conversation. If we are embracing that for backgrounds you can layer solids, gradients, and images, and eventually reorder them, then potentially we can do the same for foregrounds. It's a stretch, but layering a solid and a gradient for text feels reasonable to me.
Let me know if there's any nuance I'm missing. |
|
I greatly appreciate the feedback and thoughts @jasmussen 👍
I'm a little confused here. This PR adds a Gradient control within the Background panel, but it isn't a tab within a popover; it's a standalone control. Clicking it opens a gradient picker within a popover. The tab-in-popover pattern is specific to the Color panel's Text control, where solid and gradient are presented as tabs. So I'm not sure there's symmetry yet between the Color and Background panels. Your mockup also appears to show color and gradient as separate controls within the Color panel, which is closer to what I was proposing Could you clarify your preferred path forward? |
|
Oh that's right, that conflicts. Apologies for that confusion, let me clarify. The background tab works well if you want to add background-clip + gradient support to text in a small PR, soon. The separation of panels feels like a larger endeavour, and if the foreground proposal resonates with @WordPress/gutenberg-design, it would give us this:
We could still use the ToolsPanel defaults to reduce it to this by default:
The above path would negate the ned for tabs inside the flyouts. I think it might be more discoverable and strike a good balance, but I'd love design validation. @jameskoster @fcoveram do you have instincts? The inverse path is interesting, though, and deserves exploration. What if we maintained a single "Color" panel, that included text and background items? It would be something like this:
It's more compact in the inspector, and notably the above precludes us from allowing layer reordering as proposed here. If I had to choose between these, I would go with the separate panels, and these defaults:
Because the vision for this could be like so:
That is, several layers, even multiple stacked gradients, to match what is possible in CSS. What do you think? |
I personally prefer the separate panels. The ability to scale with the forward compatibility is a big win. The discoverability will be great for new or less advanced users. And finally, the Image tab within a Color panel popover doesn't fit as neatly, but maybe it's just my particular blend of OCD though 🤷 I've already started playing with an additional PR that will separate the panels as proposed here. I'll link it as soon as there is something tangible for people to play with and see how it feels. |
|
It's only been quickly thrown together but there's a proof of concept over in #76474 that introduces a new That new block support follows the same general approach as the This has all been wrapped up in a refactor of the panels to the proposed Here's a rough demo, but I think we can continue discussion on that broader panel refactor to #76474 and keep this PR discussion back on the background gradient UI in particular. Screen.Recording.2026-03-13.at.12.59.40.am.mp4It seems like we have buy in for the general direction all of this is taking. So in the next week or so, I'll look to start getting these base PRs and explorations in shape to merge. Starting with this one. |
|
At a glance, I like that a lot. But I would also love validation at this point. @WordPress/gutenberg-design, notably @jameskoster @fcoveram perhaps. 🙏 |
|
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'll take a look this week. Do you think it's worth getting a draft iteration issue up for 7.1, something like #73772? No action required - just asking if it's worth it 😄 |
|
Just tested again and I think the approach here makes sense. Moving gradient into the background property group seems like the right call to unblock the gradient + image combo. |
|
A new tracking issue for design tools and block supports was created over in: #76525. This covers adoption of some recent block support additions such as width and height as well as these new features around text gradients, background gradients, clipping etc.
I'll get a backport for this PR up soon and polished this up ready for a proper review. |
|
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 If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
|
Thanks for the continued testing @ramonjd I'm thinking part of what we are seeing is that the style engine still processes whatever styles are thrown at it. We need that for backward compatibility though so perhaps we need to tweak the color block supports to filter out the old styles if the block supports the new I'll explore this angle a bit and update accordingly. |
|
I think I might have an approach that avoids the need for block deprecations for blocks adopting the new background.gradient support. Blocks with The On the PHP side, |






What?
Adds
background.gradientas a new block support, enabling blocks to have a gradient picker in the Background panel. This is separate from the existingcolor.gradientin the Color panel and allows blocks to combine a background gradient with a background image via comma-separatedbackground-imageCSS values.Why?
Currently, the only way to apply a gradient to a block is through the Color panel's
color.gradientsupport. This stores the gradient atstyle.color.gradientand renders it as abackgroundCSS shorthand, which conflicts with and overrides background image properties.By introducing
background.gradient(stored atstyle.background.gradient), gradients become part of the background style group. The style engine can then combine gradient and image values into a singlebackground-imagedeclaration (e.g.,background-image: linear-gradient(...), url(...)), enabling layered backgrounds without conflict.This also lays the groundwork for eventually migrating
color.gradienttobackground.gradientacross all blocks, providing a more consistent and capable background styling system.How?
The implementation is organized into commits representing distinct layers of the system, which may help when reviewing:
1. Schema & constants (
e5aebaf)Adds
background.gradienttoblock.jsonandtheme.jsonschemas,STYLE_PROPERTYconstants, and the theme JSON class (VALID_SETTINGS,VALID_STYLES,PROPERTIES_METADATA,INDIRECT_PROPERTIES_METADATA,APPEARANCE_TOOLS_OPT_INS).2. Style engine & global styles output (
9259102)Updates the JS style engine to combine gradient and
backgroundImageinto a comma-separatedbackground-imageCSS value, adds the gradient definition to the PHP style engine, and updatescompute_style_propertiesto pass both values to the engine.3. Block support rendering & safe CSS (
63faf64)Updates
background.phpto handle gradient values on the frontend (including combined gradient + image), and adds asafecss_filter_attr_allow_cssfilter inkses.phpto allow combinedgradient+url()values that core'ssafecss_filter_attr()strips.4. Editor UI (
522b740)Adds the gradient picker to the Background panel using
ColorPanelDropdown, suppresses the Color panel's gradient tab whenbackground.gradientis enabled, gates gradient settings per block inuseSettingsForBlockElement, and adds panel styles.5. Block opt-in (
45fd7b2)Opts the Group block into
background.gradientas the first adopter, with documentation updates.6. Tests (
0c13dba)PHP tests for block support rendering, theme JSON (
compute_style_properties,remove_insecure_properties, appearance tools), and style engine. JS tests for gradient and combined gradient+image output.Testing Instructions
linear-gradient(135deg, #000 0%, #fff 100%))Global styles
Testing Instructions for Keyboard
Screenshots or screencast