Skip to content

Global styles: render element styles set only inside a breakpoint - #81265

Merged
ramonjd merged 3 commits into
trunkfrom
fix/theme-json-responsive-element-styles
Aug 7, 2026
Merged

Global styles: render element styles set only inside a breakpoint#81265
ramonjd merged 3 commits into
trunkfrom
fix/theme-json-responsive-element-styles

Conversation

@ramonjd

@ramonjd ramonjd commented Aug 6, 2026

Copy link
Copy Markdown
Member

What?

Blocks #81253. Raised by review on that PR.

Element styles written inside @mobile or @tablet now produce CSS whether or not the same element is also styled outside the breakpoint.

Why?

get_block_nodes() looks for a block's elements under styles.blocks.<block>.elements and emits the breakpoint nodes from inside that loop (lib/class-wp-theme-json-gutenberg.php:3706-3733). An element styled only inside a breakpoint is never looped over, so no node is created and no CSS is output. Add a link colour outside the breakpoint and the same theme.json starts working, which makes it look theme-dependent rather than like a missing loop.

Sanitization already keeps these styles (:1320), and the element pseudo handling just below already accounts for a state that exists only in a breakpoint, so this reads as an oversight. docs/how-to-guides/themes/global-settings-and-styles.md already promises the unconditional behaviour: "Any style property that is valid at the block or element level can be nested under one of these keys."

How?

Collect element names from the block node and from each breakpoint before looping. Only emit the default node when the element is styled outside a breakpoint.

Docs gain an example of the breakpoint-only case, and the existing CSS sample is corrected to the selector WordPress actually outputs (.wp-block-group a:where(:not(.wp-element-button)), not .wp-block-group a).

Testing Instructions

npm run test:unit:php

Three new cases in phpunit/class-wp-theme-json-test.php. All three fail on trunk and pass here.

Or in a theme's theme.json:

{
	"version": 3,
	"styles": {
		"blocks": {
			"core/group": {
				"@mobile": {
					"elements": {
						"link": { "color": { "text": "red" } }
					}
				}
			}
		}
	}
}

Before: no CSS at all. After:

@media (width <= 480px){:root :where(.wp-block-group a:where(:not(.wp-element-button))){color: red;}}

Add "elements": { "link": { "color": { "text": "blue" } } } next to @mobile and both rules appear, on trunk and here, which is the behaviour that masked this.

Not included

Three other paths accept styles that never render, all unrelated to breakpoints or fixed here: styles.blocks.<block>.elements.<el>["@mobile"], styles.elements.<el>["@mobile"], and styles.blocks.<block>.variations.<v>.elements / .blocks. Worth separate issues.

`get_block_nodes()` looked for a block's elements under
`styles.blocks.<block>.elements` and emitted the breakpoint nodes from
inside that loop. An element styled only inside `@mobile` or `@tablet` was
never looped over, so no node was created and no CSS came out. The same
element styled outside the breakpoint as well worked fine, which made the
behaviour look like it depended on the theme rather than on a missing
loop.

Sanitization already keeps these styles
(`class-wp-theme-json-gutenberg.php:1320`), and the element pseudo
handling a few lines below already accounts for a state that only exists
in a breakpoint, so this was an oversight rather than a decision.

Collect element names from the block node and from each breakpoint before
looping, and only emit the default node when the element is styled
outside a breakpoint.

The documented behaviour was already unconditional: "Any style property
that is valid at the block or element level can be nested under one of
these keys." The responsive styles guide gains an example of the
breakpoint-only case, and its CSS sample is corrected to the selector
WordPress actually outputs.
@ramonjd
ramonjd requested a review from talldan August 6, 2026 05:44
@ramonjd ramonjd self-assigned this Aug 6, 2026
@ramonjd ramonjd added [Type] Bug An existing feature does not function as intended Global Styles Anything related to the broader Global Styles efforts, including Styles Engine and theme.json labels Aug 6, 2026
Comment thread docs/how-to-guides/themes/global-settings-and-styles.md
@media (width <= 480px) { :root :where(.wp-block-group a) { color: red; } }
:root :where(.wp-block-group a:hover) { color: navy; }
@media (width <= 480px) { :root :where(.wp-block-group a:hover) { color: darkred; } }
:root :where(.wp-block-group a:where(:not(.wp-element-button))) { color: blue; }

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This reflects the actual output.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Ensures breakpoint-only block element styles generate responsive CSS.

Changes:

  • Collects element names across default and responsive block styles.
  • Adds PHPUnit coverage for breakpoint-only elements and pseudo-states.
  • Documents breakpoint-only styling and correct selectors.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
lib/class-wp-theme-json-gutenberg.php Emits nodes for elements styled only within breakpoints.
phpunit/class-wp-theme-json-test.php Tests responsive element and pseudo-style output.
docs/how-to-guides/themes/global-settings-and-styles.md Adds examples and corrects generated selectors.

@talldan talldan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good.

I've made a PR #81291, which is quite closely related to this one (and based on your branch, as I think I needed the changes from it to avoid a conflict). I'm not sure if we want to role them into one fix.

I'll make the backports for that PR, but if you want to take it over and use it for this too, then feel free. I'll be AFK until next Tuesday so won't be able to continue with it tomorrow or Monday.

edit: actually, I'll just go ahead and make a backport for both branches.

@talldan

talldan commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Yeah, sorry, I could've probably done this more cleanly. Maybe I made more work. I made a core backport PR for this PR and my PR (#81291) here - WordPress/wordpress-develop#12918.

If we want the changes in 7.1, then I think we also need a PR for the 7.1 branch.

@ramonjd
ramonjd marked this pull request as ready for review August 7, 2026 00:17
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

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 props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: ramonjd <ramonopoly@git.wordpress.org>
Co-authored-by: talldan <talldanwp@git.wordpress.org>
Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@tellthemachines

tellthemachines commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

If we want the changes in 7.1, then I think we also need a PR for the 7.1 branch.

I believe the release branch hasn't been created yet, but better double check

Edit: it's going to be created next week as per https://make.wordpress.org/core/2026/08/05/wordpress-7-1-release-candidate-phase/

@ramonjd

ramonjd commented Aug 7, 2026

Copy link
Copy Markdown
Member Author

Maybe I made more work. I made a core backport PR for this PR and my PR (#81291) here - WordPress/wordpress-develop#12918.

Oh, let's go with your PR. I created one (part of a local automation) but easy to close.

Core PR 12918 already covers this change, so use that number instead of
opening a second one.
@ramonjd ramonjd added the Backport to WP 7.1 Beta/RC Pull request that needs to be backported to the WordPress major release that's currently in beta label Aug 7, 2026

@tellthemachines tellthemachines left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is working well and changes LGTM!

@ramonjd
ramonjd merged commit 007f062 into trunk Aug 7, 2026
51 of 52 checks passed
@ramonjd
ramonjd deleted the fix/theme-json-responsive-element-styles branch August 7, 2026 02:17
@github-actions github-actions Bot added this to the Gutenberg 23.8 milestone Aug 7, 2026
@github-actions github-actions Bot removed the Backport to WP 7.1 Beta/RC Pull request that needs to be backported to the WordPress major release that's currently in beta label Aug 7, 2026
gutenbergplugin pushed a commit that referenced this pull request Aug 7, 2026
…1265)

Co-authored-by: ramonjd <ramonopoly@git.wordpress.org>
Co-authored-by: talldan <talldanwp@git.wordpress.org>
Co-authored-by: tellthemachines <isabel_brison@git.wordpress.org>
@github-actions github-actions Bot added the Backported to WP Core Pull request that has been successfully merged into WP Core label Aug 7, 2026
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

I just cherry-picked this PR to the wp/7.1 branch to get it included in the next release: d261fb3

@tellthemachines

tellthemachines commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Just noticed we need equivalent editor changes, putting up a PR for that now

Edit: #81307

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Backported to WP Core Pull request that has been successfully merged into WP Core Global Styles Anything related to the broader Global Styles efforts, including Styles Engine and theme.json [Type] Bug An existing feature does not function as intended

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants