WordPress / gutenberg

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

Block Specific CSS adds block selector to only first CSS element #48989

Open alanef opened 1 year ago

alanef commented 1 year ago

Description

Bl;ock specific CSS add the bl;ock selector class only to the first CSS element in the additional CSS - this creates specificity issues with later CSS e.g. media queries.

e.g.

.wp-block-post-date{ float:right; margin-top: -40px; } .wp-block-post-date:before { content: "Last Updated: "; } .wp-block-post-date:after { clear: both; } @media screen and (max-width: 800px) { .wp-block-post-date{ margin-top: inherit; } }

creates

.placen {}.wp-block-post-template.wp-block-post-date{ float:right; margin-top: -40px; } .wp-block-post-date:before { content: "Last Updated: "; } .wp-block-post-date:after { clear: both; } @media screen and (max-width: 800px) { .wp-block-post-date{ margin-top: inherit; } }

I would expect either the .wp-block-post-template. to be added to all elements or none - but not such a mix and match where you would need 'advanced skills' to unravel

Step-by-step reproduction instructions

Go to Sites Styles - block - Post Template - Custom CSS Add example CSS Inspect why media query fails to work.

Not sure if it applies just to this block or all?

Screenshots, screen recording, code snippet

No response

Environment info

Current version: WP 6.2-RC1-55503 using embedded Gutenberg and using Gutenberg Version 15.3.1 Twenty Twenty Three Firefox dev edition ( but not browser specific )

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

carolinan commented 1 year ago

Does it work better if you use the & selector ? (I did not test run it) The & selector is documented, but it is not something one can expect users to know about. https://make.wordpress.org/core/2023/03/06/custom-css-for-global-styles-and-per-block/

If I remember correctly, displaying information about the selector, dfirectly in the panel, was considered too confusing for users.

alanef commented 1 year ago

I haven't even seen the & selector

The work around I used was to just put a dummy first element

.this-does-nothing{}

But as an experienced developer I would have never have guessed to try some SASS syntax in a CSS box without some immediate prompt - so you are right too confusing for the less experienced and pointless for the more experienced.

What I was hoping is it would apply the & concept to everything in the box - which really should be the intent IMO

alanef commented 1 year ago

adding & does actually work - although bizarrely generates an empty element first but far from intuitive first I tried nested format

( also the link lean more about CSS doesn't mention the & format )

Given the existence of the & - the the auto &ing for the first element only is a bug but from a user expectation custom CSS for a block SHOULD apply only to that block so from a usability perspective ALL elements should auto &

e.g. & { .my-stuff { color: red;} } But that doesn't work

But

& .wp-block-post-date{ float:right; margin-top: -40px; } & .wp-block-post-date:before { content: "Last Updated: "; } & .wp-block-post-date:after { clear: both; } @media screen and (max-width: 800px) { & .wp-block-post-date{ margin-top: inherit; } } }

Does

**.wp-block-post-template{}.** wp-block-post-template .wp-block-post-date{ float:right; margin-top: -40px; }.wp-block-post-template .wp-block-post-date:before { content: "Last Updated: "; }.wp-block-post-template .wp-block-post-date:after { clear: both; } @media screen and (max-width: 800px) {.wp-block-post-template .wp-block-post-date{ margin-top: inherit; } } }

aristath commented 1 year ago

Some notes regarding the use of the & symbol, to avoid confusion: When we were building the per-block custom-CSS implementation, we needed a way to allow users to target child elements and pseudo-selectors. We went over a lot of options, and decided that the most future-proof implementation would be to follow the official CSS spec for nesting. Currently, browsers don't support CSS-nesting, but they will in the future. The & symbol has nothing to do with SASS, and it doesn't behave the same way (for example if you put it at the end of a selector, it doesn't get prepended to its parent). The use-case for the & symbol is very specific, and allows users to add CSS like this in the Custom-CSS field of a block:

font-size: 1em;
color: red;
&:after {
  display: block;
  width: 1em;
  height: 1em;
  background: pink;
}
& > .foo {
  color: purple;
}

Notice that there is no "root" selector in the above CSS... That's because it was designed for the per-block custom-CSS, where the root selector is the selector of the block itself.

Internally we transform/polyfill the & selector, replacing it with the selector of the block where this CSS was entered. So the end-result of the above CSS would looks like this (assuming the CSS was added in the group block for the sake of this example):

.wp-block-group {
  font-size: 1em;
  color: red;
}
.wp-block-group:after {
  display: block;
  width: 1em;
  height: 1em;
  background: pink;
}
.wp-block-group > .foo {
  color: purple;
}

At some point in the future, when browsers natively support CSS-nesting and follow the new CSS spec for nesting, the PHP implementation that polyfills that behavior will be removed. The code for that PHP polyfill can be seen here: https://github.com/WordPress/gutenberg/blob/c9b83b5e08f0d9763914f9894777a3e170b62849/lib/class-wp-theme-json-gutenberg.php#L1098-L1109

alanef commented 1 year ago

Notice that there is no "root" selector in the above CSS... That's because it was designed for the per-block custom-CSS, where the root selector is the selector of the block itself.

The assumption that the custom CSS ONLY applies to the block selector and developers will guess (by some magic) that they can apply a style element without the block selector to the block and if they want to select a class of a sub element they are to use the & structure.

That REALLY is counter intuitive to anyone that has been using additional CSS type structures

At least you should start the doc with some sort of indicator of structure then at least people will be able to make some sort of guess at how to use the box

2023-03-13-14-02
alanef commented 1 year ago

But if the concept is the custom CSS box is to have the top level selector then it should not be valid to 'break out' of the CSS by mistakenly applying a selector without an & that the CSS then applies globally.

So add this to a block CSS and you will hide all buttons site wide

.archive { } .wp-block-button { display: none!important; }

Whereas

.wp-block-button { display: none!important; } .archive { }

Will hide buttons ONLY in the block but apply whatever in the .archive sitewide

aristath commented 1 year ago

I don't think we ever accommodated media queries... And that does look like a bug. I know that when I was doing the code for the '&' thing, media queries never even crossed my mind... But that's because block-specific custom css should not support media queries, I don't think there is a way to accomplish that without breaking the way css works in general. Media-queries should be supported in the global custom-CSS field, and if they don't work there, then it's probably a sanitization issue.

cawa-93 commented 1 year ago

It's a bit dirty, but it allow use media queries in custom css 😅 Please use at your own risk

"core/navigation": {
    "css": "& {} @media (max-width: 600px) { & .wp-block-navigation__responsive-container { /* ... */ } }"
},
aristath commented 1 year ago

It's a bit dirty, but it allow use media queries in custom css 😅 Please use at your own risk

Note: Please don't. This works now, but there's no guarantee that it will work tomorrow. This is a hack and not a feature - which means that if people start building sites using that hack, we'll be locked-in in a bad pattern. The per-block custom-CSS field was not designed to handle media-queries, so you should not use them yet. Not until we figure out a proper way to do that for everyone. Media-queries can be added in the global custom-CSS field, which is a lot more permissive.

alanef commented 1 year ago

Of course though, presented with a box that say 'add your own CSS' then people will be tempted to 'add their own CSS' and right now it works because if you miss the & ( which is un guessable) out and you 'break out' of what is intended.

alanef commented 1 year ago

To be honest, as my first 'go' at using the FSE for something meaninful - I had ( and still don't have ) any idea where the 'global custom-CSS field' is actually.

ndiego commented 1 year ago

Hi @alanef, this issue was reviewed in today's Editor Bug Scrub. You can access the 'global custom-CSS field' but following the steps in the screenshot below. It is a bit hidden.

I also wanted to share a few great articles on how to manage pre-block CSS in block themes.

Let me know if you have any questions.

image