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

Additional Block CSS: Selector impossible if attribute is not on block-level but on element-level (as in BEM) #49415

Open
porg opened this issue Mar 28, 2023 · 16 comments
Labels
CSS Styling Related to editor and front end styles, CSS-specific issues. [Feature] Design Tools Tools that impact the appearance of blocks both to expand the number of tools and improve the experi [Feature] Site Editor Related to the overarching Site Editor (formerly "full site editing") [Type] Enhancement A suggestion for improvement.

Comments

@porg
Copy link

porg commented Mar 28, 2023

User Goal

As a block theme tweaker (advanced user, designer with CSS knowhow, but no developer):

  1. You add a helper class like .has-outline-dashed on a block instance like a Button block.
  2. You add Additional Block CSS, which shall apply not all all instances of that block but only to block instances which have that helper class added via their Additional CSS Class(es).

TL;DR — My User Experience

If the attribute you want to override corresponds not to the block-level (as in BEM) of your block, but on an element level ...

  1. In Additional Block CSS due to automatic prefixing it is impossible for "advanced users" (designers/tweakers) to formulate a proper CSS selector here.
  2. Then the only way for advanced users is via Global Additional CSS, which is not in the "modular spirit" (modular CSS selectors yes, but all in one long text blob (enqueued all time!), instead of separate Additional CSS per each block (enqueued only on demand).
  3. Professional theme.json developers/modders possibly can achieve that by writing a proper block style with inline custom CSS as JSON values.

Followup

  • Is there a solution currently other than 2) Global Additional CSS and 3) proper CSS within theme.json ?
  • Is it possible that "Additional Block CSS" gets "a bit smarter" with what it prefixes?
    • Is there an existing syntax for "if the block has the helper then consider the Additional CSS here to match"? Ampersand maybe?
    • If not could that be implemented?

My full testing

  1. If I wanted to overwrite the default block style, it works easy:

Global Styles → Blocks → Button → Additional block CSS

border-style: dashed;
  • ✅ Works all nice
  • ✅ No selector necessary
  • ✅ No !important necessary
  1. If I wanted to overwrite a particular block style "Outline", working with the same method fails.

Global Styles → Blocks → Button → Style Variation "Outline"

  • No "Additional block CSS" here!
    • Note: I even fell into a usability pitfall. Clicked the "more" menu (3 vertical dots) in the Styles panel in the believe this is the way to get "Additional CSS" for the Style Variation "Outline". No this is the global one (as I later verified by writing "/* This is the Theme CSS Level Additional CSS */" and then accessed this from a totally different block and the same inline comment was still there.)
  1. Select a button block instance → block settings → Advanced → Additional CSS Class(es)
  • I assign my helper class has-border-style-dashed.
  • Problem:
    • This is assigned on the block level .wp-block-button
    • But the relevant border to override is on the element level .wp-block-button__link

a) The only way I managed to select and override it was:

Global Styles → Additional CSS

.has-border-style-dashed .wp-block-button__link {
  border-style: dashed;
}
  • On a pure CSS selector level this is almost true to Modular CSS ("BE + M" instead of "BEM"), but on Block Editor UX / UI it is not modular. Everything in the Global CSS override blob.
  • I tried to use the offered more modular ways, but failed, due to the prefixing/suffixing which happens behind the scenes, not being comprehensible.

b) Cleaner but failed attempt: Global Styles → Blocks → Button → Additional block CSS

  • The basic version worked fine, see 1.
  • But now we want it only if the button block has the helper class has-border-style-dashed.

b1) Additional block CSS:

.has-border-style-dashed {
  border-style: dashed;
}

Outcome in <style id='wp-block-library-inline-css'>

.wp-block-button .wp-block-button__link.has-border-style-dashed {
  border-style: dashed;
}
  • ❌ Okay, so it prefixed it with the element-level .wp-block-button__link.

b2) So I try this now:

.wp-block-button.has-border-style-dashed .wp-block-button__link {
  border-style: dashed;
}

Outcome in wp-block-library-inline-css:

.wp-block-button .wp-block-button__link.wp-block-button.has-border-style-dashed .wp-block-button__link {
    border-style: dashed;
}
  • ❌ No, I'm getting nowhere.

b3) Hence I tried to formulate a selector in the spirit of "has a parent with class .has-border-style-dashed":

.has-border-style-dashed:has(.wp-block-button__link) {
  border-style: dashed;
}

Outcome in wp-block-library-inline-css:

  .wp-block-button .wp-block-button__link.has-border-style-dashed:has(.wp-block-button__link) {
      border-style: dashed;
  }
  • ❌ My last attempt has failed too.
@kathrynwp kathrynwp added Global Styles Anything related to the broader Global Styles efforts, including Styles Engine and theme.json and removed Global Styles Anything related to the broader Global Styles efforts, including Styles Engine and theme.json labels Mar 29, 2023
@mrfoxtalbot mrfoxtalbot added CSS Styling Related to editor and front end styles, CSS-specific issues. [Feature] Site Editor Related to the overarching Site Editor (formerly "full site editing") labels Mar 31, 2023
@mrfoxtalbot
Copy link

Thank you for the report @porg. I am going to add a couple of screenshots with a simple example of what you describe to make sure I understand:

You add a per-block style:
Screen Shot on 2023-03-31 at 17:28:55

But you have some blocks of that type that should be styled different:
Screen Shot on 2023-03-31 at 17:27:59

... hence, your only option is to add a global style.
Screen Shot on 2023-03-31 at 17:28:30

Were you referring to this?

I also see how trying to target different parts of the block can be very challenging in the case of complex blocks. There are a couple of tips in this article: https://wordpress.org/documentation/article/styles-overview/#applying-custom-css but I see how it is very limiting at the moment.

Is it possible that "Additional Block CSS" gets "a bit smarter" with what it prefixes

Do you have any thoughts on how we could iterate on the "Per block CSS" interface to incorporate more flexibility?

@mrfoxtalbot mrfoxtalbot added the [Feature] Design Tools Tools that impact the appearance of blocks both to expand the number of tools and improve the experi label Apr 1, 2023
@porg
Copy link
Author

porg commented Apr 4, 2023

Were you referring to this?

Yes, I was referring to what is depicted on your screenshots.

Identified base problem

  • A WordPress block does not necessarily refer to one HTML element in the output, but in reality often is composed of several HTML elements.
    • There is often are a wrapper element with a block class (B as in BEM) of whom you can style some attributes
    • And then several contained HTML elements, of which all/some (?) have an element-class (E as in BEM).
  • On the other hand the Additional Block CSS UI currently is a single undifferentiated text area.

Do you have any thoughts on how we could iterate on the "Per block CSS" interface to incorporate more flexibility?

Please improve the documentation of this section

https://wordpress.org/documentation/article/styles-overview/#applying-custom-css

  • The whole section mentions NOTHING whatsoever
    • How to properly select the sub-elements within a block
    • What post-processing that input gets:
      • Pure attributes get wrapped into the selector of the block-class
      • But if you use class selectors, these also get suffixes, and how this works is undocumented! Please add info. Maybe that already shows me the way.
  • Mentions "You can also use the ampersand (&) as in SASS/LESS, to target a nested element." but no more info than that!
    • Please add a link to how the relevant SASS/LESS ampersand operator works
    • And show some meaningful examples like how with this you can select the parent block-class or a block__element class
    • And also how the automatic prefixing/postfixing works, and how this may affect your manual written selectors.

I have some ideas how to improve the Additional Block CSS UI.

Though I know the underlying architecture of theme.json and the Style Engine only on the level of a designer / amateur frontend-dev, but not more. So some ideas may need adaptation or discarding.

Existing solutions

Pure attribute names get wrapped into the appropriate selector. That works fine already. And shall be guaranteed to continue to work, also if we the rest gets added functionality.

Idea

  • In the block manifest there quite certainly is a list of the block class and the block__element classes.
  • Possible also with some "Human Friendly" name of each of those. If not, the spec may get extended there.

Approach 1 (short term): Single textarea with available selectors visible as click links above the text area.

  • a) New behavior:
    • Hovering above them gives tooltip "Copy CSS selector to clipboard".
    • Clicking gives toast message "Copyied CSS selector to clipboard".
  • b) Behavioral change to avoid bug that I experienced:
    • If the text area contains only pure attributes without selectors, then it is assumed these belong to the top level block class, and they get the proper selector wrapped around them automatically.
    • If selectors are in the text area, then pure attributes continue to get automatically get the top level block class as their selector, but where selectors were written manually (intentionally!) prefixing/suffixing gets de-activated!

Approach 2 (long term): From the manifest the UI automatically creates different text areas

  • Top level block (as in BEM)
  • Then for each element (as in BEM) another textarea.

I prefer approach 2:

  • x) It is user friendly.
  • y) The idea of a "Modular CSS" is then fully resembled in the Site Editor UI too then.
  • z) Pro users can still enqueue CSS files, and there have all CSS selector freedom they need (also select block and element at the same time and style common attributes)

@mrfoxtalbot
Copy link

Thank you for the detailed outline. I see pros and cons on both solutions 🤔

Once again I need to resort to @annezazu's expertise 🙏

@annezazu
Copy link
Contributor

annezazu commented Apr 5, 2023

👋🏼 Thanks for tagging me in! To take a step back, CSS is intended to be a gap filler with the long term aim for as much as possible to be handled by the site editor itself. I'm sharing that to ensure the wider context is known for how and why custom CSS was added. Ideally, in the future, you won't need to rely on this to create the customizations you want. Of note, there are these follow up items:

Add inline code completion and linting to input box similar to customizer.
Provide list of blocks that have had custom CSS applied at the block level.

Professional theme.json developers/modders possibly can achieve that by writing a proper block style with inline custom CSS as JSON values.

Generally speaking, this is what's currently possible. In the future though, there's work to be done to both expand styling options through things like #40966 and thoughts around having a way to save a custom CSS class as a block variation: #7551 I might comment on that latter issue personally.

@glendaviesnz I want to get your thoughts here, particularly around why there isn't a custom CSS field for block variations. That felt a bit surprising but I imagine there might be some technical limitations here.

@porg
Copy link
Author

porg commented Apr 5, 2023

@annezazu thanks for providing the bigger picture and long term goals.

  1. My approach 1 to make the BEM selector accessible would be aided by Global Styles Custom CSS: Add inline code completion and linting to input box similar to customizer #47945 if it would also complete the block__element classes.
    • Though as said, this is just "more of the same" (like Additional CSS in the Customizer of classic themes) compared to approach 2.
  2. My approach 2 to Reflect the Modular CSS nature also in the UI likely gets more possible with Global Styles: Elements support tracking issue #40966 which can serve as a manifest of Elements (as in BEM) too and as such you could then in the UI particularly style certain Elements of a Block without dealing CSS selectors.
  3. As you seem to have knowhow in that subject domain: Could you please amend the documentation with the status quo on Custom CSS particularly to answer these aspects I inquired ?

@annezazu
Copy link
Contributor

annezazu commented Apr 5, 2023

As you seem to have knowhow in that subject domain: Could you please amend the documentation with the status quo on Custom CSS particularly to answer #49415 (comment) ?

Ironically, I did an initial sweep of that doc right before 6.2 to help out that team: WordPress/Documentation-Issue-Tracker#675 (comment) and then @mrfoxtalbot and co helped flesh it out after the fact. Here's an issue to address this: WordPress/Documentation-Issue-Tracker#747 If I can, I'll loop back personally.

@glendaviesnz
Copy link
Contributor

glendaviesnz commented Apr 5, 2023

@glendaviesnz I want to get your thoughts here, particularly around why there isn't a custom CSS field for block variations. That felt a bit surprising but I imagine there might be some technical limitations here.

I didn't have much involvement in the block-level CSS sorry, I mostly handled the global level, @carolinan may have more of the background on this.

@carolinan
Copy link
Contributor

carolinan commented Apr 5, 2023

The per-block custom CSS field is not intended to target these additional selectors. It is intended to be as simple as possible for end users, not developers.

  1. Use the global CSS field when you are not targeting a block. I read in the issue why you don't want to, but that is its purpose.
  2. Use the interface in the Styles sidebar to update the style variation, not custom CSS.

@carolinan
Copy link
Contributor

About the documentation, the article you linked to is for users, not developers, so I do strongly disagree that it should cover topics like what post-processing is used.

@porg
Copy link
Author

porg commented Apr 5, 2023

So I summarize:

  1. Styling in block themes is primarily done in the Editor UI. Convenient!
  2. Custom CSS is intended as a workaround to achieve some things the Editor UI does not yet support. But beware that this custom CSS is limited to declare attribute: values; only and not targeting particular elements of a block with CSS selectors (the prefixing/suffixing is a blackbox, which one must not know and which will remain undocumented).
  3. Selecting particular elements and styling them should be in block specific CSS files which use wp_enqueue_block_style().

So I will use mostly 1, skip 2 due its very limited nature, and fall back to 3 in the few cases where really needed.

@carolinan
Copy link
Contributor

A user should not be required to know what a prefix is. They should trust that the CSS is added to the block they selected in the menu: and it is.

@porg
Copy link
Author

porg commented Apr 5, 2023

Exactly that expectation was the start of my journey!

  • Put "border-style: dashed;" into a "custom block CSS" and instead of overriding the visible border's style (which was solid) I got nothing, and when using "border: 2px dashed red;" I got another border around the existing visible border.
    • Why: Because the block author had applied the border not on the block level but on the element level (some deeper nested element).
    • Only from this arose the need for an element-level CSS selector.
  • All "attribute: value;" pairs without a selector filled into the custom block CSS UI seems to simply go to the block level (top level). There seems to be no logic which binds particular attributes to particular deeper nested elements.

@mrfoxtalbot
Copy link

mrfoxtalbot commented Apr 5, 2023

I have the impression that we are discussing two things in paralell here:

  • Explain how the current Block-specific CSS system works.
  • Expand this functionality to address the scenario @porg explained in the issue.

Regarding the first item, I opened a separate thread here #49531 If we do not want to make the end-user documentation excessively complicated, we should at the very least include a link to the relevant developer article where this is covered. I discuss the need to cross reference developer and end-user documentation with @juanmaguitar a while back and this is a perfect example.

About the second item, I do not see a clear path to fix this without going a very complex rabbit hole. I would recommend polishing the current interface and gather feedback from users to understand how useful per-block CSS really is.

@annezazu
Copy link
Contributor

annezazu commented Apr 5, 2023

Wanted to cross reference this issue too as it relates to this conversation around "adding a custom CSS field to block style variations":

#49602

@carolinan
Copy link
Contributor

These are two separate issues:

  • Custom CSS does not override style variations because the style variation CSS uses an additional class name and has a higher specificity.
  • Custom CSS is applied to the wrong element.

Put "border-style: dashed;" into a "custom block CSS" and instead of overriding the visible border's style (which was solid) I got nothing, and when using "border: 2px dashed red;" I got another border around the existing visible border.
Why: Because the block author had applied the border not on the block level but on the element level (some deeper nested element).
Only from this arose the need for an element-level CSS selector.

I am not able to reproduce this, the second issue. Can you provide the full details, including which block you are using and wether or not you were trying to override a style variation here?

@carolinan
Copy link
Contributor

If I understand correctly from discussions in related issues, the plan now is to add a CSS input field to the style variation UI.
#49602

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CSS Styling Related to editor and front end styles, CSS-specific issues. [Feature] Design Tools Tools that impact the appearance of blocks both to expand the number of tools and improve the experi [Feature] Site Editor Related to the overarching Site Editor (formerly "full site editing") [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

No branches or pull requests

7 participants