Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New WP 6.3 CSS is overriding theme styles and styles from other plugins #53468

Open
kubiqsk opened this issue Aug 9, 2023 · 39 comments
Open
Labels
Backwards Compatibility Issues or PRs that impact backwards compatability CSS Styling Related to editor and front end styles, CSS-specific issues. [Feature] Layout Layout block support, its UI controls, and style output. [Type] Bug An existing feature does not function as intended

Comments

@kubiqsk
Copy link

kubiqsk commented Aug 9, 2023

Description

There are some new CSS rules and they break layouts, eg.:

:where(body .is-layout-flow) > :last-child:last-child {
	margin-block-end: 0;
}

or similar one with duplicated :first-child.

When I remove this duplicated selector with inspect element and leave only 1 occurrence, then everything works again

Step-by-step reproduction instructions

It's hard to write step-by-step for this, as you will need to use some specific themes and plugins and setup some blocks, but it's happening on more websites with a different setup, but the point is, that this is a newly added CSS, so it was working fine until now.

Screenshots, screen recording, code snippet

No response

Environment info

No response

Please confirm that you have searched existing issues in the repo.

Yes

Please confirm that you have tested with all plugins deactivated except Gutenberg.

No

@annezazu annezazu added Needs Testing Needs further testing to be confirmed. CSS Styling Related to editor and front end styles, CSS-specific issues. labels Aug 9, 2023
@annezazu
Copy link
Contributor

annezazu commented Aug 9, 2023

It's hard to write step-by-step for this, as you will need to use some specific themes and plugins and setup some blocks, but it's happening on more websites with a different setup, but the point is, that this is a newly added CSS, so it was working fine until now.

Hey there! Thanks for opening this issue and for using the latest in WordPress. Can you provide more information around how you can replicate this? For example, what plugins and themes are you using? Without replication steps, this makes it very difficult for us to address your feedback, either with more context or a fix.

@kubiqsk
Copy link
Author

kubiqsk commented Aug 9, 2023

Well, there are many plugins allowing you to add some margin for blocks, because the default Gutenberg one is not very useful as you never want to have the same spacings on desktop and on mobile.
Eg. Ghostkit, Block Editor Bootstrap Blocks or many others...
You could add margin top for the first block and margin bottom for the last block and it worked until version WP 6.3, but now you need to use !important switch/checkbox to make it works, so many websites have missing these margins now.

But let's say we will not use any plugin, but ofc I need a bigger margin on the desktop and smaller on the mobile, so I can not use either Gutenberg controls, but I need to manually add class to the first block to have some top margin and also one class for the last block to have some bottom margin.
Here is the demo: https://demo.kubiq.sk/margin-problem/
You can inspect first or last paragraph - they should have 100px margin on desktop, 80px on tablet and 60px on mobile and this worked until WP 6.3 - now it is 0px and that means I need to visit every website and every page, post and CPT in it and fix this.

I'm maintaining hundreds of websites, but thanks god only a few tens of them are based on theme.json

I can add_theme_support('disable-layout-styles') and then write some custom CSS to fix missing rules, or I can add !important everywhere but it means hours and hours of work, just because of this new CSS rules

You should never add that crazy specific CSS rules like :where(body .is-layout-flow) > :last-child:last-child because you can be 100% sure it will break a lot of websites.

And there are more problems in theme.json themes... Broken shortcodes from version 6+ (https://demo.kubiq.sk/sample-page/) also taken hours of my life...

I really like Gutenberg and the FSE but I don't understand some decisions in the development and if this will keep happening, then I will be forced to use some other builder for development and that would be a pitty, because I already have so many custom blocks and patterns and also plugins for block editor.

Thank you for your time.

@carolinan
Copy link
Contributor

For the sites with theme.json, you can achieve responsive spacing by making sure that the spacing presets are responsive.

@kubiqsk
Copy link
Author

kubiqsk commented Aug 10, 2023

@carolinan, sure in the ideal world where you will have perfectly designed everything and all the spaces will be consistent you can rely on this, but unfortunately that's mostly not the real world scenario.
And we are still talking just about some conservative design, but imagine something more fancy and then you need even more control over this...
Just a simple example: you may want to have eg. 100px on desktop for 2 different sections, but then on mobile you want to have 60px for first one and 80px for last one for some reason and you're done... it's not possible.

But the point is, that many people use 3rd party plugins to create more advanced grids, offsets, etc... or just custom classes to write their own CSS rules and updates like this in WP 6.3 will break many things.

You have a margin controls in the editor, so just let the user to decide if he wants to set it for 0 or not... why to write that highly specific default CSS rule that will override existing rules on millions of existing websites?
I mean, IMHO in general if you need to write some default layout rules like :where(body .is-layout-flow) > :last-child:last-child, then you should feel that something is wrong, because this is literarily what you will do if you want to override some themes or plugins CSS.

@cbirdsong
Copy link

I imagine a selector like :last-child:last-child would only be used to address some other specificity problem (though that doesn't mean it was a good idea). The core issue is that the editor needs a coherent CSS authoring strategy that isn't just "don't write CSS, add everything to theme.json". A selector this broad should not be shipped, and something like this happens in every release:

@ndiego ndiego added Backwards Compatibility Issues or PRs that impact backwards compatability and removed Needs Testing Needs further testing to be confirmed. labels Aug 15, 2023
@spencerfinnell
Copy link

spencerfinnell commented Aug 17, 2023

Also related to the new selector style:

@andrewserong andrewserong added the [Feature] Layout Layout block support, its UI controls, and style output. label Aug 21, 2023
@jordesign jordesign added the [Type] Bug An existing feature does not function as intended label Aug 30, 2023
@Romiride
Copy link

Romiride commented Sep 4, 2023

missing dashboard, missing pemerlink in the list

@heyflo
Copy link

heyflo commented Oct 4, 2023

There are so many css rules that have a selector's depth way too aggressive, like :

.editor-styles-wrapper .block-editor-block-list__layout.is-root-container > :where(:not(.alignleft):not(.alignright):not(.alignfull)) {}

html :where(.editor-styles-wrapper) ol,
html :where(.editor-styles-wrapper) ul {}

html :where(.editor-styles-wrapper) ol li, 
html :where(.editor-styles-wrapper) ul li {}

html :where(.editor-styles-wrapper) ol ul, 
html :where(.editor-styles-wrapper) ul ul {}

html :where(.editor-styles-wrapper) h1, 
html :where(.editor-styles-wrapper) h2, 
html :where(.editor-styles-wrapper) h3, 
html :where(.editor-styles-wrapper) h4, 
html :where(.editor-styles-wrapper) h5, 
html :where(.editor-styles-wrapper) h6 {}

.editor-styles-wrapper a:where(:not(.wp-element-button)) {)

.wp-core-ui .button-group > .button {}

.editor-styles-wrapper :where(body .is-layout-flow) > * {}
.editor-styles-wrapper :where(body .is-layout-flow) > :first-child:first-child {}

.editor-styles-wrapper :where(body .is-layout-flow) > * {}

.block-editor-block-list__layout .block-editor-block-list__block {}

And there are some other cases. Maybe the ideal solution would be to move the editor inside an iframe and be able to unload most of the styles. It's supposed to be simple but some of these styles are breaking things inside the editor and thus we can't have the same front-end & back-end styles for both. You cannot have these loose selectors where you're targetting tags or generic classes.
Most of them are too specifics and I understand why but you have to find a way to keep the wp-core-ui styles separated from the editor and provide simple "overridable" css with it. To deal with it on the front-end we removed the block styles completely and are doing it on our own but I feel like it's not great as we still have to deal with it in the editor.

@markhowellsmead
Copy link

markhowellsmead commented Feb 27, 2024

a:where(:not(.wp-element-button)) (from the list above) is also applied in the frontend of the website. Because this rule is inline, it always takes precedence over CSS stylesheets. The errors which are occurring because of this specificity were reported in 2022 as #40159 but there has been no response since then.

@markhowellsmead
Copy link

Same problem, different code in WordPress 6.6. Also, *why" is text-decoration being set at all?!

/* Inline core CSS */ 
:root :where(a:where(:not(.wp-element-button))) {
    color: var(--wp--preset--color--primary);
    text-decoration: underline;
}

Ref. #40159.

@aaronrobertshaw
Copy link
Contributor

Also, *why" is text-decoration being set at all?!

I believe the text-decoration: underline style is coming from the core lib/theme.json file if your theme doesn't define a styles.elements.link.typography.textDecoration value in theme.json.

Regarding the :root :where() wrapping the top-level link selector, a fix is available in Gutenberg 18.8 which was released today and will be included in the WP 6.6.1 point release.

@markhowellsmead
Copy link

markhowellsmead commented Jul 17, 2024

Also, *why" is text-decoration being set at all?!

I believe the text-decoration: underline style is coming from the core lib/theme.json file if your theme doesn't define a styles.elements.link.typography.textDecoration value in theme.json.

Thanks for clarifying that. This seems to be an enforcement which I believe shouldn't be imposed. If there is nothing defined in the settings or CSS, would it not be better to allow the default browser behaviour to be respected? As it is now, the user's browser setting (default or accessibility-based) is overridden and this requires another override to set things back to the default behaviour. New ref. #63647

@aaronrobertshaw
Copy link
Contributor

This seems to be an enforcement which I believe shouldn't be imposed

I don't have the full history and context around this default but it was introduced back in 2022 via #41786. As it has been around for a long while now, I'm not sure it can be easily removed completely, as some themes and sites might actually rely on it.

If your theme is using theme.json it can set this to initial or whatever you prefer. If you want to omit all of core's default theme.json styles, you might be able to achieve that via a filter.

A nuclear option (which I wouldn't really recommend) might be to dequeue all global styles if your theme isn't using them:

add_action(
    'wp_enqueue_scripts',
    function () {
        wp_dequeue_style( 'global-styles' );
    }
);

@kubiqsk
Copy link
Author

kubiqsk commented Jul 17, 2024

Well, I love the idea of the Gutenberg / Block Editor, but i need to do some crazy things to prevent it breaking my websites after each update... so if anyone wants to try it, here is my "cleaning" code ( only for new projects ! ):

add_action( 'after_setup_theme', function(){
	// remove gutenberg duotone
	remove_action( 'wp_body_open', 'wp_global_styles_render_svg_filters' );
	remove_action( 'in_admin_header', 'wp_global_styles_render_svg_filters' );
	remove_filter( 'render_block', 'wp_render_duotone_support' );
});

add_action( 'wp_head', function(){
	// remove all default styles
	global $wp_styles;

	wp_dequeue_style('global-styles');
	wp_dequeue_style('core-block-supports');
	
	foreach( $wp_styles->queue as $handle ){
		if( strpos( $handle, 'wp-block-' ) === 0 ){
			wp_dequeue_style( $handle );
		}
	}
}, 2 );

add_action( 'enqueue_block_editor_assets', function(){
	// remove crazy selectors rules eg. :first-child:first-child or :root :where
	wp_enqueue_script( 'gutenberg-fixes', get_stylesheet_directory_uri() . '/gutenberg-fixes.js', [], 1, 1 );
	wp_add_inline_script( 'gutenberg-fixes', 'const gutenbergFixedCss="' . addslashes( wp_get_CLEAN_global_stylesheet() ) . '"', 'before' );
});

add_action( 'wp_enqueue_scripts', function(){
	$global_stylesheet = wp_get_CLEAN_global_stylesheet();
	if( ! empty( $global_stylesheet ) ){
		wp_register_style( 'clean-global-styles', false );
		wp_add_inline_style( 'clean-global-styles', $global_stylesheet );
		wp_enqueue_style( 'clean-global-styles' );
	}
});

function wp_get_CLEAN_global_stylesheet(){
	$can_use_cached = ! wp_is_development_mode('theme');
	$cache_group = 'theme_json';
	$cache_key = 'wp_get_CLEAN_global_stylesheet';
	if( $can_use_cached ){
		$cached = wp_cache_get( $cache_key, $cache_group );
		if( $cached ){
			return $cached;
		}
	}

	$tree = WP_Theme_JSON_Resolver::get_merged_data();

	$styles_variables = $tree->get_stylesheet( [ 'variables' ], [ 'theme', 'custom' ] );
	$styles_rest = $tree->get_stylesheet( [ 'presets' ], [ 'theme', 'custom' ] );

	$stylesheet = $styles_variables . $styles_rest;
	if( $can_use_cached ){
		wp_cache_set( $cache_key, $stylesheet, $cache_group );
	}

	return $stylesheet;
}

gutenberg-fixes.js

// Block editor is loading default layout styles causing weird margins and other problems

wp.hooks.addFilter( 'blocks.getBlockDefaultClassName', 'theme/gutenber-fix', function( string, className, blockName ){
	let styles;
	const bad_selectors = [ ':first-child:first-child', ':root :where', '.is-layout-constrained' ];
	const iframe = document.querySelector('iframe[name="editor-canvas"]');
	const currentEditor = iframe ? iframe.src : 'div';
	if( ! document.editorFixed || document.prevEditor != currentEditor ){
		if( iframe ){
			styles = iframe.contentDocument.querySelectorAll('style');
		}else{
			styles = document.querySelectorAll('style');
		}
		for( let i = 0; i < styles.length; i++ ){
			if( bad_selectors.some( selector => styles[ i ].innerText.includes( selector ) ) ){
				styles[ i ].innerHTML = gutenbergFixedCss + '.acf-innerblocks-container{width:100%}.editor-visual-editor [data-block] a{pointer-events:none}';
				document.editorFixed = true;
				document.prevEditor = currentEditor;
				console.log('Bad selector style removed');
				break;
			}
		}
	}
	return string;
});

// remove empty block on Backspace

document.body.addEventListener( 'keydown', e => {
	if( e.key == 'Backspace' ){
		const selectionStart = wp.data.select('core/block-editor').getSelectionStart();
		if( 'offset' in selectionStart && selectionStart.offset === 0 ){
			const selectedBlock = wp.data.select('core/block-editor').getSelectedBlock();
			if( selectedBlock.attributes.content.length === 0 ){
				wp.data.dispatch('core/block-editor').removeBlock( selectedBlock.clientId );
			}
		}
	}
}, true );

and then I have my own styles for blocks ofc...

so then it is loading only what I need and I can easily get 100% on pagespeed and I don't need to worry about some weird changes after each update...

I know... it's crazy... but it works for my workflow...
I'm maintaining hundreds of websites and if I should do some fixes after each WP update... eg. just some margins or some underlines... it would take hours...

@mikecollet
Copy link

What is the point of WordPress calling these overly aggressive CSS rules in the website every time. We manage WordPress websites for over 300 clients and surely you can't suddenly use CSS selectors like :root :where(a:where(:not(.wp-element-button))) which changes front-end styling. I understand that you can now enable and disable some settings through the theme.json but this was not at all possible or discussed when this website was developed at the time. Now WordPress uses new settings and we are expected to retroactively update 300 themes. Downright ridiculous.

@markhowellsmead
Copy link

markhowellsmead commented Jul 17, 2024

I agree that it's problematic to introduce rules like this; we currently have nearly 100 sites which now have to be repaired. (Automatic updates are on, based on Core team advice, so I now have to drop everything and fix this issue across dozens of sites.)

@kubiqsk
Copy link
Author

kubiqsk commented Jul 17, 2024

You can also add this to your functions.php to make all the new rules not that much specific, so it will not break your websites now...
But next update will bring again some stupid rules... previously it was :first-child:first-child now it is :root :where... let's see how they decide to break our websites in 6.7... ⏳

add_action( 'wp_head', function(){
	global $wp_styles;
	if( ! empty( $wp_styles->registered['global-styles']->extra['after'][0] ) ){
		$wp_styles->registered['global-styles']->extra['after'][0] = str_replace( ':root :where', ':where', $wp_styles->registered['global-styles']->extra['after'][0] );
	}
}, 1 );

@wolffe
Copy link

wolffe commented Jul 17, 2024

What about keeping the block styles, but not the specific ones with :root, :where and so on?

For example, if I use buttons, or columns, or a cover on my page, I only want those styles to load. Not the global ones. Is that possible?

Will the below do the job?

wp_dequeue_style( 'global-styles' );

@talldan
Copy link
Contributor

talldan commented Jul 18, 2024

@kubiqsk It'd be great if you could report any styles you see breaking. You shouldn't need to implement an action like that since the intention in 6.6 is to reduce core's css specificity.

@wolffe
Copy link

wolffe commented Jul 18, 2024

@talldan And yet, the specificity is now higher, breaking thousands of websites...

I will implement the same code today for my websites, and I'll report my findings here.

@talldan
Copy link
Contributor

talldan commented Jul 18, 2024

Do let us know which particular rules if you can find them, it's really helpful.

For example, the bug you reported in #63345 was an unintentional increase in specificity, it was an important one to fix, and it's one of the reasons a 6.6.1 release for WordPress will be rolled out in the next few days.

@wolffe
Copy link

wolffe commented Jul 18, 2024

So, those dequeue filters remove everything, and I still need my block styles.

The filter below removes all highly -specific :root and :where from the injected global styles. They also fix the forced underlined links. Thanks @kubiqsk for the original filter.

add_action(
    'wp_head',
    function () {
    	global $wp_styles;

        if ( ! empty( $wp_styles->registered['global-styles']->extra['after'][0] ) ){
    		$wp_styles->registered['global-styles']->extra['after'][0] = str_replace(
                [
                    ':root :where',
                    ':root',
                    ':where',
                ],
                '',
                $wp_styles->registered['global-styles']->extra['after'][0]
            );
        }
    },
    1
);

@talldan
Copy link
Contributor

talldan commented Jul 18, 2024

The filter below removes all highly -specific :root and :where from the injected global styles.

:where has zero specificity, so doing that might actually cause the opposite.

@wolffe
Copy link

wolffe commented Jul 18, 2024

@talldan This is the first iteration, I might refine the strings to be replaced. But right now I'll keep it as it solves so many issues ;)

@talldan
Copy link
Contributor

talldan commented Jul 19, 2024

Just to keep you all up to date, another issue was reported that we're looking to include a fix for in 6.6.1 - #63712.

Hopefully that's it, but if there's anything else you spot that seems higher specificity than 6.5, keep the issues coming in and we'll do our best to fix them.

@apmeyer
Copy link

apmeyer commented Jul 20, 2024

Maybe this is known, but if not....

In 6.6, in hybrid themes, within the editor, margins specified in theme.json at the block level (paragraph, for example), or in an editor stylesheet, are overridden by this new css output:

.editor-styles-wrapper .is-layout-flow > * {
    margin-block-start: 2.375rem;
    margin-block-end: 0;
}

This is applying the blockGap spacing (specified in theme.json) to everything at the root level or within a most containers – including non-flexbox groups (not a row or stack) or columns where typography styles should take precedence.

This also happens with a constrained layout element, such as a group.

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

For example, this is Ignored in the editor:

    "$schema": "https://schemas.wp.org/trunk/theme.json",
    "version": 3,
    "styles": {
        "blocks": {
            "core/paragraph": {
                "spacing": {
                    "margin": {
                        "top": "1rem",
                        "bottom": "1rem"
                    }
                }
            }
        }
    }

This is very frustrating. If this specificity could be reverted to how it was previously that would be ideal.

At the root level, or within non flex groups or columns (etc), I'd expect typography styles (paragraph margins, heading margins, list margins, etc) to take precedence. As they do within the media & text block, for example. And as they did previously.

On the frontend, the theme.json styles are being honored properly (but not in the editor):

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

@talldan
Copy link
Contributor

talldan commented Jul 22, 2024

In 6.6, in hybrid themes, within the editor, margins specified in theme.json at the block level (paragraph, for example), or in an editor stylesheet, are overridden by this new css output

Thanks for reporting. I can reproduce it. For anyone else looking to reproduce this, it seems to only be an issue when the editor isn't iframed, which can happen when custom fields is active, or there are older blocks installed. There might also be some other cases that trigger it.

I expect there's extra specificity being added to the selector to override some other styles that bleed into the editor canvas, which wouldn't normally when the iframe is being used.

edit: Here's what I see in 6.5:
Screenshot 2024-07-22 at 3 52 05 PM

vs 6.6:
Screenshot 2024-07-22 at 3 53 29 PM

@apmeyer
Copy link

apmeyer commented Jul 22, 2024

Is there a way to force the block editor to use the iframe when developing hybrid themes?

@markhowellsmead
Copy link

@apmeyer Yes: ensure that all blocks are compatible with theme.json schema version 3.

@munyagu
Copy link

munyagu commented Aug 5, 2024

Is this an editor-only issue?
I get this on the front end as well.

6.5

:where(body .is-layout-constrained) > * {
    margin-block-start: 1.5rem;
    margin-block-end: 0;
}

6.6.1

.is-layout-constrained > * {
    margin-block-start: 1.5rem;
    margin-block-end: 0;
}

@talldan
Copy link
Contributor

talldan commented Aug 6, 2024

@munyagu Are you seeing any problems on the front end?

I believe that one's an editor only issue when the editor is non-iframed. It happens because of the way the .editor-styles-wrapper is appended on to the selector. When that extra class is added to the selector it bumps the specificity from 0,1,0 to 0,2,0.

In all other use cases though (iframed editor, front end) that extra class name isn't added, so the specificity is the same as before.

@talldan
Copy link
Contributor

talldan commented Aug 6, 2024

Just a heads up by the way, I've created a tracking issue for the specificity issue reported - #64243.

@munyagu
Copy link

munyagu commented Aug 6, 2024

@talldan
I am having the same problem with the front end as the following ticket.
https://core.trac.wordpress.org/ticket/61750

If this is an editor-only issue, it seems that the problem I and the ticket are having is not yet included in the tracking issue.

@munyagu
Copy link

munyagu commented Aug 6, 2024

I am using the same hybrid theme as the ticket reporter.
Maybe it is a problem with the hybrid theme.

@hellofromtonya
Copy link
Contributor

Hello @munyagu and @apmeyer 👋

As these changes are being committed into WordPress Core, each contributor will get a credit (prop). Getting WP contributor credit requires a personal (not company) WordPress.org profile / username.

Do you have a personal (not company) WordPress.org profile and username?

  • If yes, share here to ensure.
  • If no and you're interested in getting credited, please create a profile/username and share it here.

Thank you for your contributions!

@apmeyer
Copy link

apmeyer commented Aug 13, 2024

@hellofromtonya I am at https://profiles.wordpress.org/apmeyer/

Thanks.

@hellofromtonya
Copy link
Contributor

Thank you @apmeyer. I manually added you to the Core Props.

@munyagu
Copy link

munyagu commented Aug 15, 2024

@hellofromtonya
Copy link
Contributor

Thank you @munyagu. I manually added you to the Core Props.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Backwards Compatibility Issues or PRs that impact backwards compatability CSS Styling Related to editor and front end styles, CSS-specific issues. [Feature] Layout Layout block support, its UI controls, and style output. [Type] Bug An existing feature does not function as intended
Projects
No open projects
Development

No branches or pull requests