WordPress / gutenberg

The Block Editor project for WordPress and beyond. Plugin is available from the official repository.
https://wordpress.org/gutenberg/
Other
10.25k stars 4.09k forks source link

External stylesheets can't override inline core styles #40159

Open markhowellsmead opened 2 years ago

markhowellsmead commented 2 years ago

Description

I'm trying to override inline rules, e.g. .wp-container-1 > *, using rules in a stylesheet referenced through an enqueued stylesheet. The specificity of this selector is 0,1,0.

Using the selector .wp-block-group in the theme CSS is also 0,1,0 and so it should be able to override the inline rule.

However, it cannot because inline styles take precedence over any linked stylesheets.

See also https://github.com/WordPress/gutenberg/issues/36135 in particular, as well as https://github.com/WordPress/gutenberg/issues/35840, https://github.com/WordPress/gutenberg/issues/34047, https://github.com/WordPress/gutenberg/issues/29705, https://github.com/WordPress/gutenberg/issues/17511 and https://github.com/WordPress/gutenberg/issues/39971.

Step-by-step reproduction instructions

Enqueue a stylesheet containing the following CSS. The max-width doesn't override the inline core CSS unless !important is used.

(In practice, the rule is being applied to a custom block with a custom class name, which must always be full-width and whose max-width - or alignment - may not be adjusted in the editor. The example class name .wp-block-group is only being used here for example purposes.)

(The use of !important introduces a large number of subsequent priority rule problems and a large number of experts have been advising against it for a very long time. e.g. [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity#the!importantexception).)

Screenshots, screen recording, code snippet

.wp-block-group {
    max-width: 1000px;
}

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

Yes

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

Yes

markhowellsmead commented 2 years ago

See also https://github.com/WordPress/gutenberg/issues/41230.

ramonjd commented 2 years ago

Speaking to .wp-container-1 > *, I've encountered other areas where style rendered by layout override other styles that should take precedence.

I'm referring specifically to blockGap, whereby an attempt to apply a block gap to all group blocks (for example) using theme.json is futile since the layout styles are too specific.

There are a couple of PRs trying to address this bug, namely https://github.com/WordPress/gutenberg/pull/40875 and https://github.com/WordPress/gutenberg/pull/39870.

As you've noted it highlights a broader challenge regarding the specificity of all CSS properties defined by layout.

In the spirit of the issue about standardizing CSS classnames/tokens, an exploratory PR is out there that generates

class names based on values used in constructing the styles instead of using a random class name. E.g. wp-container-1 becomes wp-layout-default wp-layout-default-content-size-650px wp-layout-default-wide-size-1000px wp-layout-default-global-gap

What are your thoughts about an approach like that?

The layout implementation affects a number of block and site layouts so it's all a bit like tip-toeing on thin ice above a sea of radioactive sharks, but I'm of the view it needs to be refactored, and it will have to before we add further layout options to Gutenberg.

markhowellsmead commented 2 years ago

Thanks for looking into it, @ramonjd, I appreciate it. Some colleagues and I discussed the problematic descendant selector in #36135 last year and we came to a similar solution: using semantic class names makes a lot more sense.

I would suggest:

markhowellsmead commented 2 years ago

I would also note that !important is still being referenced in code examples in that PR, which are themselves contributing to specificity problems. There are several issues open on this subject: https://github.com/WordPress/gutenberg/search?q=%21important&type=issues

markhowellsmead commented 2 years ago

…and your comment about justification class names also hits home: see #41230 and #38719.

cbirdsong commented 2 years ago

I generally like the idea of abstracting layout out into predictable classes like .wp-layout-<whatever>, but I think it would be best if the layouts were conceptualized more cleanly and holistically instead of merely retrofitting what exists into the style engine.

.wp-layout-default and .wp-layout-flex do not describe what the layout is intended to manage, especially since apparently the flex one might be wrap or nowrap, which leads to very different results. Every .wp-layout- should have a clear and defined responsibility in the way that the different layouts on Every Layout do, and options and variations on these layouts should do nothing but supply what is needed to make those adjustments, ideally via custom properties.

I'd also agree with the use of !important – it should not be there.

tedw commented 2 years ago

Related https://github.com/WordPress/gutenberg/issues/38126

markhowellsmead commented 2 years ago

Related #41431.

markhowellsmead commented 1 year ago

Still a problem.

markhowellsmead commented 6 months ago

Still a problem.

EmSixTeen commented 3 months ago

I loathe this.

SCR-20240506-lpny

My enqueued stylesheet is the style.min.css here, but WordPress is The colour should be --btn-tc, but the inline style kills this.

An error on my part. This is a theme issue, not a WordPress issue.

markhowellsmead commented 3 months ago

@EmSixTeen Going by the custom property names, that specific implementation is most likely coming from a third-party solution. --btn-bgc etc. aren't from WordPress itself. Which tech. is loading the style.min.css file?

(Bumping this through @WordPress/outreach to get some visibility.)

EmSixTeen commented 3 months ago

I'm afraid I need to hold up my hands and say I've made an error here in thinking the cause is WordPress/Gutenberg. The style.min.css is my enqueued stylesheet, and I believed that the inline style was WP/Gutenberg.

markhowellsmead commented 1 month ago

This problem is still occurring and is more prevalent with WordPress 6.6. Specifically:

/* Linked stylesheet */ 
h2 a {
    text-decoration: none;
}

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

The inline core CSS overrides my linked styles because it comes later in the cascade.

aaronrobertshaw commented 1 month ago

The inline core CSS overrides my linked styles because it comes later in the cascade.

Regarding this specific element issue noted in the comment above, a fix is available in Gutenberg and was released today in v18.8.

For WP6.6, there is an open ticket with a custom plugin build that can be used to evaluate the fix in the context of WP6.6. The fix will be included in the 6.6.1 point release but I unfortunately don't have a specific time yet for when that point release might happen. I'd recommend keeping an eye on https://core.trac.wordpress.org/ticket/61660 for further updates.