Make WordPress Core

Opened 2 months ago

Closed 6 weeks ago

Last modified 6 weeks ago

#61829 closed defect (bug) (fixed)

Some layout styles have increased specificity in WordPress 6.6 within the non-iframed editor

Reported by: talldanwp's profile talldanwp Owned by: hellofromtonya's profile hellofromTonya
Milestone: 6.6.2 Priority: normal
Severity: normal Version: 6.6
Component: Editor Keywords: has-patch has-unit-tests has-testing-info gutenberg-merge commit fixed-major dev-reviewed
Focuses: Cc:

Description (last modified by hellofromTonya)

Ticket for merging the changes in https://github.com/WordPress/gutenberg/pull/64076.

Description

When the block editor is not iframed (which can happen when Custom Fields are active, or blocks that use and older apiVersion are present), style rules are processed using post css to append the .editor-styles-wrapper class name. This has the effect of scoping the the style rules to ensure they don't affect the editor chrome or admin.

In WordPress 6.6, one of the rules was changed to .is-layout-flow > *. In a iframed editor, the specificity of this rule is ok (0,1,0), but in a non-iframed editor it becomes .editor-styles-wrapper .is-layout-flow > *, a specificity of (0,2,0). Comparing this to 6.5, the same rule was .editor-styles-wrapper :where(body .is-layout-flow) > * (specificity 0,1,0). So this is a regression in specificity that has caused some issues. Notably themes can no longer properly override the spacing for blocks using theme.json and have the results correctly shown in the non-iframed editor.

Testing Instructions

  1. Add some very obvious margin rules to your theme.json like this for paragraphs (under styles.blocks):
"core/paragraph": {
	"spacing": {
		"margin": {
			"top": "4rem",
			"bottom": "4rem"
		}
	}
},
  1. Create a new post. Ensure you don't have custom fields active.
  2. Insert 3 paragraphs with text, check that the margin looks right. The first paragraph should have no top margin, the last no bottom margin, but in all other cases there should be 4rem top/bottom margin.
  3. Activate Custom Fields in the editor preferences to 'un-iframe' the editor
  4. Observe that the block spacing is now incorrect

Screenshots or screencast

Actual

https://github.com/user-attachments/assets/1e053fe1-d942-4f71-8a53-ea478b26c0b4

Expected

https://github.com/user-attachments/assets/ffb33f68-cf8f-42eb-916c-af4d189d428e

Change History (20)

This ticket was mentioned in PR #7145 on WordPress/wordpress-develop by @talldanwp.


2 months ago
#1

Trac ticket: https://core.trac.wordpress.org/ticket/61829
Github PR: https://github.com/WordPress/gutenberg/pull/64076

Backports the changes from https://github.com/WordPress/gutenberg/pull/64076

## What?
Fixes the issue mentioned in https://github.com/WordPress/gutenberg/issues/53468#issuecomment-2241279024 to restore theme.json spacing rules taking precedence over the implicit spacing rules in a non-iframed editor.

## How?
In trunk the code generates a selector like .is-layout-flow > * (specificity 0,1,0) which is fine normally. When in a non-iframed editor, the transformStyles function prefixes selectors with .editor-styles-wrapper to scope them to the editor canvas, so it becomes .editor-styles-wrapper .is-layout-flow > * (specificity 0,2,0), a bump in specificity that causes the precedence of styles to change.

In this PR I've changed the selector to :root :where(.is-layout-flow) > * (still specificity 0,1,0). transformStyles handles 'root' selectors a little differently, it'll instead replace the :root part so it becomes .editor-styles-wrapper where(.is-layout-flow) > * (keeping the specificity at 0,1,0).

The other layout selector that this affects is the :first-child :last-child selectors that are responsible for resetting margin at the start and end of a block list. They traditionally have a 0,2,0 specificity so that they can override both the above rule and any rules in the theme.json. Those selectors are also maintained at 0,2,0 with this change, they become something like :root :where(.is-layout-flow) > :first-child.

<details><summary>Here's a list of selectors that will be updated (according to our php tests)</summary>

-.is-layout-flow  > :first-child {
+:root :where(.is-layout-flow) > :first-child {

-.is-layout-flow  > :last-child {
+:root :where(.is-layout-flow) > :last-child {

-.is-layout-flow  > * {
+:root :where(.is-layout-flow) > * {

-.is-layout-constrained  > :first-child {
+:root :where(.is-layout-constrained) > :first-child {

-.is-layout-constrained  > :last-child {
+:root :where(.is-layout-constrained) > :last-child {

-.is-layout-constrained  > * {
+:root :where(.is-layout-constrained) > * {

-.is-layout-flex  {
+:root :where(.is-layout-flex) {

-.is-layout-grid  {
+:root :where(.is-layout-grid) {

-.wp-block-social-links-is-layout-flow  > :first-child {
+:root :where(.wp-block-social-links-is-layout-flow) > :first-child {

-.wp-block-social-links-is-layout-flow  > :last-child {
+:root :where(.wp-block-social-links-is-layout-flow) > :last-child {

-.wp-block-social-links-is-layout-flow  > * {
+:root :where(.wp-block-social-links-is-layout-flow) > * {

-.wp-block-social-links-is-layout-constrained  > :first-child {
+:root :where(.wp-block-social-links-is-layout-constrained) > :first-child {

-.wp-block-social-links-is-layout-constrained  > :last-child {
+:root :where(.wp-block-social-links-is-layout-constrained) > :last-child {

-.wp-block-social-links-is-layout-constrained  > * {
+:root :where(.wp-block-social-links-is-layout-constrained) > * {

-.wp-block-social-links-is-layout-flex  {
+:root :where(.wp-block-social-links-is-layout-flex) {

-.wp-block-social-links-is-layout-grid  {
+:root :where(.wp-block-social-links-is-layout-grid) {

-.wp-block-buttons-is-layout-flow  > :first-child {
+:root :where(.wp-block-buttons-is-layout-flow) > :first-child {

-.wp-block-buttons-is-layout-flow  > :last-child {
+:root :where(.wp-block-buttons-is-layout-flow) > :last-child {

-.wp-block-buttons-is-layout-flow  > * {
+:root :where(.wp-block-buttons-is-layout-flow) > * {

-.wp-block-buttons-is-layout-constrained  > :first-child {
+:root :where(.wp-block-buttons-is-layout-constrained) > :first-child {

-.wp-block-buttons-is-layout-constrained  > :last-child {
+:root :where(.wp-block-buttons-is-layout-constrained) > :last-child {

-.wp-block-buttons-is-layout-constrained  > * {
+:root :where(.wp-block-buttons-is-layout-constrained) > * {

-.wp-block-buttons-is-layout-flex  {
+:root :where(.wp-block-buttons-is-layout-flex) {

-.wp-block-buttons-is-layout-grid  {
+:root :where(.wp-block-buttons-is-layout-grid) {

</details>

## Testing Instructions

  1. Add some very obvious margin rules to your theme.json like this for paragraphs (under styles.blocks):
    "core/paragraph": {
            "spacing": {
                    "margin": {
                            "top": "4rem",
                            "bottom": "4rem"
                    }
            }
    },
    
  1. Create a new post. Ensure you don't have custom fields active.
  2. Insert 3 paragraphs with text, check that the margin looks right. The first paragraph should have no top margin, the last no bottom margin, but in all other cases there should be 4rem top/bottom margin.
  3. Activate Custom Fields in the editor preferences to 'un-iframe' the editor
  4. Check that the styles are the same without the iframe

Also worth checking out trunk and comparing the styles. You should see that in trunk the iframed editor looks correct, but when you activate custom fields the non-iframed editor styles are broken.

## Screenshots or screencast
#### Before
https://github.com/user-attachments/assets/1e053fe1-d942-4f71-8a53-ea478b26c0b4

#### After
https://github.com/user-attachments/assets/ffb33f68-cf8f-42eb-916c-af4d189d428e

#2 @hellofromTonya
2 months ago

  • Owner set to hellofromTonya
  • Status changed from new to reviewing

Self-assigning this CSS specificity bugfix for commit review.

#3 @hellofromTonya
2 months ago

  • Keywords has-testing-info added

Test Report

Patch tested: https://github.com/WordPress/wordpress-develop/pull/7145

Steps to Reproduce or Test

See test instructions in ticket's description.

Environment

OS: macOS
Localhost: Core's Docker env
Browser: Firefox
Plugins: none
Theme: TT4

Actual Results

When reproducing a bug/defect (before applying the patch):

  • ✅ margin is correct before activating the custom field preference.
  • ❌ margin is not correct when activating the custom field preference.

When testing the bugfix patch (after applying the patch):

  • ✅ margin is correct before activating the custom field preference.
  • ✅ margin is correct after activating the custom field preference.

✅ There are no impacts before and after to the margins in the frontend.

#4 @hellofromTonya
2 months ago

Patch: https://github.com/WordPress/wordpress-develop/pull/7145

✅ The patch generates the expected CSS (see the How section in the patch).

Generated CSS Test Results

Here are my testing results from my previous test report:

On the first child

  • With the custom field preference turned off:
    :root :where(.is-layout-constrained) > :first-child {
      margin-block-start: 0;
    }
    
    :root :where(p) {
      margin-top: 4rem;
      margin-bottom: 4rem;
    }
    
  • With the custom field preference turned on:
.editor-styles-wrapper :where(.is-layout-constrained) > :first-child {
  margin-block-start: 0;
}

.editor-styles-wrapper :where(p) {
  margin-top: 4rem;
  margin-bottom: 4rem;
}

On the middle children

  • With the custom field preference turned off:
:root :where(p) {
  margin-top: 4rem;
  margin-bottom: 4rem;
}

:root :where(.is-layout-constrained) > * {
  margin-block-start: 1.2rem;
  margin-block-end: 0;
}
  • With the custom field preference turned on:
.editor-styles-wrapper :where(p) {
  margin-top: 4rem;
  margin-bottom: 4rem;
}

.editor-styles-wrapper :where(.is-layout-constrained) > * {
  margin-block-start: 1.2rem;
  margin-block-end: 0;
}

On the last child

  • With the custom field preference turned off:
:root :where(.is-layout-constrained) > :last-child {
  margin-block-end: 0;
}

:root :where(p) {
  margin-top: 4rem;
  margin-bottom: 4rem;
}

:root :where(.is-layout-constrained) > * {
  margin-block-start: 1.2rem;
}
  • With the custom field preference turned on:
.editor-styles-wrapper :where(.is-layout-constrained) > :last-child {
  margin-block-end: 0;
}

.editor-styles-wrapper :where(p) {
  margin-top: 4rem;
  margin-bottom: 4rem;
}

.editor-styles-wrapper :where(.is-layout-constrained) > * {
  margin-block-start: 1.2rem;
}

#5 @hellofromTonya
2 months ago

  • Keywords commit added

Patch: https://github.com/WordPress/wordpress-develop/pull/7145

LGTM and ready for commit.

#6 @hellofromTonya
2 months ago

  • Resolution set to fixed
  • Status changed from reviewing to closed

In 58890:

Editor: Fix bumped specificity for layout styles in non-iframed editor.

Fixes a regression introduced in [58241] which inadvertently bumped the specificity in a non-iframed editor for .editor-styles-wrapper .is-layout-flow > * from (0,1,0) to (0,2,0). This fix restores theme.json spacing rules taking precedence over the implicit spacing rules in a non-iframed editor.

The What

When the block editor is not iframed (which can happen when Custom Fields are active, or blocks that use and older apiVersion are present), style rules are processed using post css to append the .editor-styles-wrapper class name. This has the effect of scoping the the style rules to ensure they don't affect the editor chrome or admin.

With [58241], one of the rules was changed to .is-layout-flow > *. In a iframed editor, the specificity of this rule is okay (0,1,0), but in a non-iframed editor it becomes .editor-styles-wrapper .is-layout-flow > *, a specificity of (0,2,0). Comparing this to before [58241], the same rule was .editor-styles-wrapper :where(body .is-layout-flow) > * (specificity 0,1,0). This is a regression in specificity that has caused some issues. Notably themes can no longer properly override the spacing for blocks using theme.json and have the results correctly shown in the non-iframed editor.

The How

This changeset modifies the selector to :root :where(.is-layout-flow) > * (still specificity 0,1,0). transformStyles handles 'root' selectors a little differently, it'll instead replace the :root part so it becomes .editor-styles-wrapper where(.is-layout-flow) > * (keeping the specificity at 0,1,0).

The other layout selector that this affects is the :first-child :last-child selectors that are responsible for resetting margin at the start and end of a block list. They traditionally have a 0,2,0 specificity so that they can override both the above rule and any rules in the theme.json. Those selectors are also maintained at 0,2,0 with this change, they become something like :root :where(.is-layout-flow) > :first-child.

References:

Follow-up to [58241], [58228], [55956], [54162].

Props talldanwp, aaronrobertshaw, andrewserong, markhowellsmead, ramonopoly, hellofromTonya.
Fixes #61829.

#8 @hellofromTonya
2 months ago

  • Keywords fixed-major dev-feedback added
  • Resolution fixed deleted
  • Status changed from closed to reopened

Reopening for 2nd committer sign-off to backport [58890] to the 6.6 branch for 6.6.2 release.

#9 @hellofromTonya
2 months ago

Committer note:

2 contributors were not included in the changeset props as could not find their .org profiles. Asked each of them to create and share if they wish to be credited.

I'll be monitoring and, if either follow-up, I'll manually add them to the changesets in Core's Props.

Version 0, edited 2 months ago by hellofromTonya (next)

This ticket was mentioned in Slack in #core by hellofromtonya. View the logs.


8 weeks ago

This ticket was mentioned in Slack in #core by hellofromtonya. View the logs.


7 weeks ago

This ticket was mentioned in Slack in #core by hellofromtonya. View the logs.


6 weeks ago

#13 @hellofromTonya
6 weeks ago

  • Keywords gutenberg-merge added

Adding the gutenberg-merge keyword to denote [58890] is merging PHP changes from Gutenberg.

#14 @hellofromTonya
6 weeks ago

  • Description modified (diff)

Pinging committers involved in this change for a 2nd committer sign-off to backport it to the 6.6. branch for 6.6.2 RC1 on Sep 4th.

@aaronrobertshaw @andrewserong @talldanwp

This ticket was mentioned in Slack in #core-editor by hellofromtonya. View the logs.


6 weeks ago

#16 @andrewserong
6 weeks ago

  • Keywords dev-reviewed added; dev-feedback removed

I've tested https://github.com/WordPress/wordpress-develop/pull/7145 applied on the 6.6 branch and it's all working correctly, with margins displaying correctly in both the iframed and non-iframed editors. Adding the dev-reviewed keyword, marking this as ready for backporting to the 6.6 branch.

This ticket was mentioned in Slack in #core-editor by andrewserong. View the logs.


6 weeks ago

#18 @hellofromTonya
6 weeks ago

  • Resolution set to fixed
  • Status changed from reopened to closed

In 58986:

Editor: Fix bumped specificity for layout styles in non-iframed editor.

Fixes a regression introduced in [58241] which inadvertently bumped the specificity in a non-iframed editor for .editor-styles-wrapper .is-layout-flow > * from (0,1,0) to (0,2,0). This fix restores theme.json spacing rules taking precedence over the implicit spacing rules in a non-iframed editor.

The What

When the block editor is not iframed (which can happen when Custom Fields are active, or blocks that use and older apiVersion are present), style rules are processed using post css to append the .editor-styles-wrapper class name. This has the effect of scoping the the style rules to ensure they don't affect the editor chrome or admin.

With [58241], one of the rules was changed to .is-layout-flow > *. In a iframed editor, the specificity of this rule is okay (0,1,0), but in a non-iframed editor it becomes .editor-styles-wrapper .is-layout-flow > *, a specificity of (0,2,0). Comparing this to before [58241], the same rule was .editor-styles-wrapper :where(body .is-layout-flow) > * (specificity 0,1,0). This is a regression in specificity that has caused some issues. Notably themes can no longer properly override the spacing for blocks using theme.json and have the results correctly shown in the non-iframed editor.

The How

This changeset modifies the selector to :root :where(.is-layout-flow) > * (still specificity 0,1,0). transformStyles handles 'root' selectors a little differently, it'll instead replace the :root part so it becomes .editor-styles-wrapper where(.is-layout-flow) > * (keeping the specificity at 0,1,0).

The other layout selector that this affects is the :first-child :last-child selectors that are responsible for resetting margin at the start and end of a block list. They traditionally have a 0,2,0 specificity so that they can override both the above rule and any rules in the theme.json. Those selectors are also maintained at 0,2,0 with this change, they become something like :root :where(.is-layout-flow) > :first-child.

References:

Reviewed by andrewserong.
Merges [58890] to the 6.6 branch.

Follow-up to [58241], [58228], [55956], [54162].

Props talldanwp, aaronrobertshaw, andrewserong, markhowellsmead, ramonopoly, hellofromTonya, munyagu, apmeyer.
Fixes #61829.

Note: See TracTickets for help on using tickets.