Make WordPress Core

Opened 2 months ago

Last modified 3 days ago

#64389 accepted defect (bug)

Breaking change in 6.9 -> WP Core CSS now forces all links to underline.

Reported by: mmorris8's profile mmorris8 Owned by: westonruter's profile westonruter
Milestone: 6.9.2 Priority: normal
Severity: normal Version: 6.9
Component: Themes Keywords: reporter-feedback has-patch has-unit-tests
Focuses: css Cc:

Description (last modified by sabernhardt)

The offending line:

a:where(:not(.wp-element-button)) {
    text-decoration: underline;
}

My theme is uses a straightforward button class, but does so on a CSS layer. Five years after CSS @layer was widely available and WordPress still doesn't respect it. That wouldn't be a problem except y'all are inserting global rules like this that break people's themes and create work for them.

Simply remove this. Or fix the larger problem of WordPress putting all it's global inline styles on the root layer. It's a 1-line code change in wp-includes/global-styles-and-settings.php

Specifically change line 238 from

<?php
$stylesheet = $styles_variables . $styles_rest;

to

<?php
$stylesheet = "@layer wp { $styles_variables $styles_rest }";

This will allow themes that want to organize their CSS using @layer to declare wp as one of their layers - further they can declare the priority of the wordpress sheets in relation to their own. If the theme does not do this the wp layer will be put on the end of the chain of layers causing it to preempt the other layered styles (which it already does because it is currently "unlayered")

I realize this isn't a long term fix. It isn't intended to be. I've read the discussions on CSS Layer adoption and they get bogged down in with complex implementation details I frankly don't see the point of. For now, if it comes out of WordPress put it on the wp layer. The CSS Layers spec allows for sub layers, so working out what those are and allowing blocks to declare layers and priorities can be sussed out at a later time.

Or, third option, give us a hook here so we can modify the CSS about to be cached so we can wrap it as desired.

Change History (23)

#1 @sabernhardt
2 months ago

  • Description modified (diff)

#2 @westonruter
2 months ago

  • Keywords reporter-feedback added

I don't see this CSS being generated, at least with Twenty Twenty-Five active. The closest thing I see is in STYLE#global-styles-inline-css:

a:where(:not(.wp-element-button)){color: currentColor;text-decoration: underline;}

I see the same in v6.8.3.

Is your theme a block theme or classic theme? If you could provide a sample theme to reproduce the issue that would be helpful.

#3 @mmorris8
2 months ago

  • Resolution set to wontfix
  • Status changed from new to closed

I inherited a botched theme setup that I'm slowly nursing to health. I'm pretty sure it's a block theme - that at least is how the code I'm writing is organized. I'm using postcss to scan the block directories for styles and merge them to a master file independent of WordPress' scan. After some further research I found a way to kill the global inline styles insertion entirely.

The point about wrapping the global inline styles in a layer still has some merit IMO, but that's a feature request and not a bug fix. This one I'll mark as closed as I have found a resolution that doesn't require a change in WordPress itself - which given the thousands of other sites using it is doubtless the safer approach. Thank you for your time.

#4 @westonruter
2 months ago

  • Keywords reporter-feedback removed
  • Milestone Awaiting Review deleted

#5 @george9
2 months ago

  • Resolution wontfix deleted
  • Severity changed from major to critical
  • Status changed from closed to reopened

The underline rule itself already existed, but the end result has changed: themes that previously relied on normal cascade rules can no longer override it without increasing specificity (for example :root a).

So while there may not be a documented Core change explaining why this happens, the behavioral difference is real and reproducible, and it affects sites using Global Styles. This is functionally the same problem that occurred in 6.6 before it was adjusted.

Regardless of intent, this is a regression in behavior and needs to be fixed, as Core should not force presentational defaults that themes previously controlled via normal CSS cascade rules.

#6 @westonruter
2 months ago

  • Keywords reporter-feedback added
  • Milestone set to Awaiting Review
  • Severity changed from critical to normal

@george9 Please provide the steps we can use to reproduce the issue. How is a site configured in 6.8 in a way that a style breakage is observed in 6.9?

#7 follow-up: @joezappie
8 weeks ago

On my Tailpress sites, this is a breaking change from 6.8.3 to 6.9 with no other changes.

Previously, the global styles were added before all the theme CSS was enqueued. Just by upgrading to 6.9, all my links are now underlined and looking at the source, the global styles now come after the themes styles. To fix it, I did increase the specificity from a {} to :root a {}.

That said, this rule in general has been a nuisance. I do not think that WordPress should be enforcing all links (except their own button) to have underlines by default and that it should be up to the theme to decide. The majority of clickable links on the internet probably do not have underlines, unless its in some large content block such as an article. I prefer additive not subtractive CSS, and when using more modern features like @layer, things like this require !important to override.

#8 in reply to: ↑ 7 ; follow-up: @westonruter
8 weeks ago

Replying to joezappie:

On my Tailpress sites, this is a breaking change from 6.8.3 to 6.9 with no other changes.

@joezappie You may be experiencing the issue in #64354. There is a pull request in review that may fix the issue. Can you test?

#9 in reply to: ↑ 8 @vanonsopensource
11 days ago

Replying to westonruter:

Replying to joezappie:

On my Tailpress sites, this is a breaking change from 6.8.3 to 6.9 with no other changes.

@joezappie You may be experiencing the issue in #64354. There is a pull request in review that may fix the issue. Can you test?

Tested this, but the underline styles are still loaded. So the problem still persists!

#10 @westonruter
11 days ago

  • Milestone changed from Awaiting Review to 6.9.2
  • Owner set to westonruter
  • Status changed from reopened to assigned
Last edited 11 days ago by westonruter (previous) (diff)

#11 follow-up: @westonruter
11 days ago

Is anyone (everyone) using Elementor?

@vanonsopensource (and others), please provide steps that I can use to reproduce the issue on a fresh install of WordPress. Without knowing how to reproduce the issue it is very difficult to fix.

#12 @jorbin
11 days ago

Please also confirm that this issue is still present in the recently released 6.9.1.

#13 in reply to: ↑ 11 @vanonsopensource
10 days ago

Replying to westonruter:

Is anyone (everyone) using Elementor?

@vanonsopensource (and others), please provide steps that I can use to reproduce the issue on a fresh install of WordPress. Without knowing how to reproduce the issue it is very difficult to fix.

As long as you have a theme.json global inline styles will be loaded, these include this css line:

a:where(:not(.wp-element-button)) {
    text-decoration: underline;
}

The problem still persists in 6.9.1 (and in the 6.9.2 alpha)

#14 @westonruter
10 days ago

@vanonsopensource Please provide more details, specific testing steps. This will be useful for me but also for future testers who validate any fix. For example, which theme is installed? How is it configured?

#15 @xwolf
9 days ago

I can confirm the issue too. We waitet for 6.9.1 for the fix in #64354, but it still occurs and we had to reactivate the plugin.

In our case we used a classic theme with block-editor. We are running wordpress on a multisite. The problem occurs in blocks, that was inserted by plugins. The needed inline-style for these blocks were missing. On another dev multisite-installation with the same theme and the same plugin, the block would print out this HTML

<div class="rrze-elements columns-grid" style="grid-template-columns: 2fr 1fr;">

but on the installation with the error, it removed the style=""

<div class="rrze-elements columns-grid">

I habe no clue, why the the dev multisite installation works, while the other fails.
Could there be a connection with the size of styles_inline_size_limit? Ours is set to 40k.

#16 follow-up: @westonruter
9 days ago

@xwolf Can you please provide steps to reproduce the issue on a fresh install of WordPress?

I don't see how the core change in 6.9 would affect inline style attributes, as it was only about inlining external stylesheets in STYLE elements.

#17 in reply to: ↑ 16 @xwolf
9 days ago

Replying to westonruter:

@xwolf Can you please provide steps to reproduce the issue on a fresh install of WordPress?
I don't see how the core change in 6.9 would affect inline style attributes, as it was only about inlining external stylesheets in STYLE elements.

Damn, I cannot reproduce it yet on a new fresh install ;(

Our multisite hosts about 800 websites, and its initial installation was a few years ago. However, it has always been updated to the latest WordPress version, and we didn't have any issues with missing CSS until version 6.9.0. Do you have any tips or suggestions on where I could look more closely?

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


8 days ago
#18

  • Keywords has-patch has-unit-tests added

#19 @westonruter
8 days ago

  • Status changed from assigned to accepted

@vanonsopensource OK, you mention theme.json. I've been able to reproduce the issue with the Hello Elementor theme in which case no block styles get enqueued (including the classic-theme-styles which gets enqueued when there is no theme.json). So in the Elementor case, the logic in wp_hoist_late_printed_styles() is falling back to appending the global-styles to the very end of the HEAD, which is the wrong place as the global-styles should be getting printed where styles are printed normally.

It would be helpful if users experiencing this issue could share the URL for a page on their site where the issue can be observed, and then also have the Load Combined Core Block Assets plugin active. This plugin has a query parameter that allows for the hotfix to be bypassed, which will then allow me to compare with and without should_load_separate_core_block_assets enabled.

@westonruter commented on PR #10875:


8 days ago
#20

How I tested:

  1. Install and activate the Elementor plugin.
  2. Install and activate the Hello Elementor theme.
  3. Override the Elementor hotfix logic by adding plugin that does: add_filter( 'wp_should_output_buffer_template_for_enhancement', '__return_true' );
  4. Create a blank post with Elementor.
  5. View the post on the frontend.
❌ Before (links are underlined) ✅ After (links are not underlined)
https://github.com/user-attachments/assets/0097091f-5d47-4d28-8540-a7a58b84fd90 https://github.com/user-attachments/assets/10f6dbcf-09a2-4cf3-9228-a0b1e0260186
STYLE#global-styles-inline-css is printed at the end of HEAD, far after LINK#hello-elementor-css STYLE#global-styles-inline-css element is printed after STYLE#wp-emoji-styles-inline-css and before LINK#hello-elementor-css.

#21 @westonruter
8 days ago

  • Keywords needs-testing added

I have a pull request which is available for testing. It fixes the issue with global-styles not being printed in the spot in the cascade. See testing instructions.

Note that this is the only scenario that I've been able to reproduce the issue. If there are other scenarios, please share the precise testing steps.

@westonruter commented on PR #10875:


8 days ago
#22

This new placeholder approach may be relevant the hoisted placement of other styles. But I'd really love to get more reproduction steps for any issues people are experiencing.

#23 @sajib1223
3 days ago

  • Keywords needs-testing removed

Patch Testing Report

Patch tested: https://patch-diff.githubusercontent.com/raw/WordPress/wordpress-develop/pull/10875.diff

Environment

  • WordPress: 7.0-alpha-61215-src
  • PHP: 8.2.29
  • Server: nginx/1.27.5
  • Database: mysqli (Server: 8.4.7 / Client: mysqlnd 8.2.29)
  • Browser: Firefox 147.0
  • OS: Windows 10/11
  • Theme: Hello Elementor 3.4.6
  • MU Plugins: None activated
  • Plugins:
    • Elementor 3.35.4
    • Test Reports 1.2.1
    • Ticket 64389 1.0.0

Steps taken

  1. Installed and activated the Elementor plugin.
  2. Installed and activated the Hello Elementor theme.
  3. Added hotfix in a custom plugin and activated.
    <?php
    /**
     * Plugin Name: Ticket #64389
     * Plugin URI: https://buffercode.com/plugin/frontend-dashboard
     * Description: WP Core CSS now forces all links to underline.
     * Version: 1.0.0
     * Author: Shazzad
     * Author URI: https://shazzad.me
     */
    if (! defined('ABSPATH')) {
            die();
    }
    
    add_filter('wp_should_output_buffer_template_for_enhancement', '__return_true');
    
    
  1. Created a blank post with Elementor.
  2. Frontend of the post does not show underline for site title.
  3. ✅ Issue resolved with patch.

Expected outcome

  • Frontend link should not be hyperlinked from WP Core CSS.

Supplemental Artifacts

✅ Links are not underlined after patch
https://files.catbox.moe/1m24ld.png

Note: See TracTickets for help on using tickets.