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

feature-request: Add Custom CSS at block instance level. Not globally. #48331

Open
tresorama opened this issue Feb 22, 2023 · 6 comments
Open
Labels
[Feature] Block settings menu The block settings screen [Feature] Design Tools Tools that impact the appearance of blocks both to expand the number of tools and improve the experi [Type] Enhancement A suggestion for improvement.

Comments

@tresorama
Copy link

tresorama commented Feb 22, 2023

What problem does this address?

Currently is not possible to add custom CSS to a block instance.
By instance i mean that if you apply custom CSS to a specific core/cover block instance, no other core/cover block instance are affected by that custom CSS.

There are various custom CSS solution already discussed and merged.
#46571
#44412

These are related to custom CSS applied globally to every block of that kind.
This issue is about custom CSS per block INSTANCE instead.

Which are potential benefits of this feature ?

Gutenberg is designed that, instead of exposing the entire CSS properties set for a block (like Elementor, WebFlow) we only expose a limited amount of block settings/attributes, only necessary ones.
This is the killer feature of the Gutenberg design, because the consumer is the "Content Creator" and not the "Web Designer/Developer".

The "Web Designer/Developer"** is also a consumer of Gutenberg but his/her works is preparing the daily routine to the final "Content Creator".

Sometimes, the exposed block properties in the UI doesn't let the developer achieve his/her goal.
These are rare scenarios, but they exists.

Scenario where this feature adds value

Imagine that you know how to use CSS and, while creating your content , you feel to be 95% close to your goal, but you can’t add that missing piece because “block” you are using doesn't expose necessary CSS properties, not yet.
BUT YOU KNOW THAT WITH 2 LINES OF CSS YOU CAN ACHIEVE YOUR GOAL

Now you have these choices:

    1. Create a CSS stylesheet with a style definition and enqueue that stylesheet, (via PHP, or with a plugin that inject CSS in all pages) and link that block to that CSS via Block > Sidebar > Advanced > Custom CSS Classes.
    1. Create a custom Gutenberg Block and load it as plugin and use that block instead of original one
    1. Install a “Page Builder” Plugin that add a block with feature you are looking for.
    1. Install a plugin that enable "custom CSS per block instance".

Examine these solution:

    1. Css definition in one place (PHP or Plugin Settings) and usage in other place (Block Editor). Feels wrong (to me) and no easy to guess that some custom CSS is used.
    1. Time consuming and feels unnecessary complex, and also it requires that every block that need custom CSS should be created separatly. Feels wrong (to me).
    1. Time consuming for searcing > installing > testing plugins .
      Also, why load all blocks that the plugin has just for 1 block?
      Also, why load all PHP code for one block ??
      Feels ok only if you are using that plugin anyway.
    1. In my opinion the right choice at the moment.
      Example plugin that does it well: Otter

What is your proposed solution?

Copy what Otter plugin does with Custom CSS and integrate in all blocks. It’s perfect.
A demo is visible in the video below.

Otter:

  • Generate a unique string and append to block wrapper as css class (ticss-131a035e)
  • let you write a <style> declaration in the editor UI
  • inject provided custom CSS scoped to that selector
<style type="text/css" media="all">
.ticss-131a035e .wp-block-cover__inner-container{
  width:100% !important
}
</style>

Otter supports full css:

  • media query
  • pseudo element and selector
  • ...

Otter does also one other UX key thing:

  • When you use custom CSS at block level, you should enable the "Custom CSS" tool from a dropdown (similar to when you need to enable "Line Height" or "Letter Spacing" tools from "Typography" dropdown). Doing this ensure that only block where Custom CSS is really used has that section in the Block Inspector (sidebar). This facilitate understanding which block use custom CSS and which not.

Example of UX of this feature (using Otter)

In the following video this marketing hero is created.

Schermata 2023-02-22 alle 20 25 19

The process:

Kapture.2023-02-22.at.19.47.50.mp4

Final consideration

Adding this feature is good for these reasons:

Let user add custom CSS right where it’s used. When that CSS code is not necessary anymore it can be removed safely.
If, instead, that CSS was loaded with an external stylesheet solution , how do you know if you can remove it in the future ??? How can you know which block are using that CSS ??
Orphan css is not good.

If later on, the block receives an updates that add a new feature, and this feature can replace custom CSS , the developer can remove previously added custom CSS and replace with block attributes, all in the same place.

Could be interesting, for Gutenberg dev community, to “observe” which CSS users add, in order to understand what they want to achieve and they can not at the moment.
Thanks to this we can prioritize, and add missing features to core blocks, that are really useful and required.
Obviously, user should be asked to accept that CSS will be observed, similar to a cookie policy.

It’s always good to have a last resort for developer.

@tomdevisser
Copy link
Member

Thanks for the suggestion @tresorama, but to be honest, I'm not a fan of this idea.

  1. This will really uglify your markup and make it a mess to work in when writing CSS. There's already an option to add custom CSS classes uniquely for that block, that would solve the issue if you already know CSS (which is the audience for this feature).

  2. This means the argument This is the killer feature of the Gutenberg design, because the consumer is the "Content Creator" and not the "Web Designer/Developer". is true, but not relevant in this case, cause custom CSS is something for the designer/developer, not something we should clutter the interface for end users with.

@tomdevisser tomdevisser added [Feature] Design Tools Tools that impact the appearance of blocks both to expand the number of tools and improve the experi [Feature] Block settings menu The block settings screen labels Feb 23, 2023
@tresorama
Copy link
Author

Alternative solution, available right now without plugins:

  • Add a additional css class to desired block (Block > Sidebar > Advanced > Custom CSS Classes)
  • Write a stylesheet inside Custom HTML directly in page
Kapture.2023-02-23.at.15.46.39.mp4

Cosideration

The process is the same that Otter does, but done manually.

Downsides

  1. The custom CSS is applied only in frontend but not in the block editor.
  2. The Custom HTML affect layout of other block in the editor

Maybe these two things could be enhanced...

@tresorama
Copy link
Author

tresorama commented Feb 23, 2023

Thanks for the suggestion @tresorama, but to be honest, I'm not a fan of this idea.

  1. This will really uglify your markup and make it a mess to work in when writing CSS. There's already an option to add custom CSS classes uniquely for that block, that would solve the issue if you already know CSS (which is the audience for this feature).
  2. This means the argument This is the killer feature of the Gutenberg design, because the consumer is the "Content Creator" and not the "Web Designer/Developer". is true, but not relevant in this case, cause custom CSS is something for the designer/developer, not something we should clutter the interface for end users with.

You re right on point 2.
I expressed myself poorly, my bad.

Opinionated Workflow

My ideal world in the long run is that Gutenberg is "who" injects CSS in pages.
Theme developer don't need to have a css file in the theme folder for these scenarios (of this issue).

Theme developer interact with theme.json to:

  • define tokens, used by editor
  • define core block extension/overrides
  • define global styles

Theme developer create block patterns ready to be filled with real content.
Final user (Content Creator) then uses block pattern as primary way of adding content.
Final user (Content Creator) can create content with block directly, if he feels comfortable with.

So because, main "user" usage is via block pattern, it will be good if developer, while creating these block patterns can add custom css scoped to the pattern itself.

Maybe i'm used to Tailwind approach where CSS is right where it's used, so that portability is easy and no mental context switch between where you define css and where you use it.


Edited: better explanation of the workflow

@kathrynwp kathrynwp added the [Type] Enhancement A suggestion for improvement. label Feb 23, 2023
@mrfoxtalbot
Copy link

Hi @tresorama . I would be curious to hear your thoughts on the new per-block CSS feature.

This new feature adds CSS to all blocks of that type, so I do not think it cover the need you explain in this issue but I would like to know how you think we could bridge this gap.

Related #49415

@tresorama
Copy link
Author

tresorama commented Apr 2, 2023

Without testing, but by reading the #49415 and https://wordpress.org/documentation/article/styles-overview/#per-block-css I can confirm that this issue and the "per-block CSS feature" handle CSS overrides at different levels.

I think it will be good the have both global and local-per-instance override of block CSS, because they address two different "moment / motivation" due to where they take place.

Put simply, global override (feature already available as "per-block CSS feature", A in this comment) is when a site creator want to override a block visual across all site independent of render context.
And, local-per-instance override (feature requested in this issue, B in this comment) is used when in a particular page a block should be rendered with additional CSS because of the page context (parent and siblings blocks layout decision likely).


When a user need a website, and choose Wordpress as the platform to achieve it he/she starts by choosing theme first and then create pages with contents.
So he/she:

  • choose a theme
  • customizes globally block-type that he/she does not like totally (A)
  • create pages with content
  • if required by the context (the page he/she is working on) he/she adds custom CSS per block instance (B)

Not every content creator is a web designer, so a more widespread usage is

  • choose a theme
  • create pages with content using block patterns and core blocks

These two paths are different but also similar, because a block pattern can act as a incapsulated box that provide complex CSS override hidden from the Content Creator perspective, and the block pattern can be created via GUI entirely by theme developer if a per-block-instance features is available.

For completeness, i also add that:

  • Wordpress core provides core blocks, that can be seen as a default set of component with a predefined theme definition
  • Then the theme, via "theme.json" can put a layer of overrides over core blocks of the step above. This is the global CSS overrides at code level, instead of GUI level.

Wordpress core can be seen as a default theme.json.


For the implementation side, i think that a unique id string for every block instance is needed, similar to Styled Components /Emotion / CSS Modules approach, and also is how Otter does it.

Maybe adding css style inside html comments JSON (i don't remeber how is called ).

Adding this CSS to a core/paragraph

& { 
  color: red; 
}
&:hover { 
  color: blue;
}
@media (min-aspect-ratio: 2/3) {
  &:hover { 
    color: green;
  }
}
<!-- wp:parapraph { customCSS: "& { color: red; } &:hover { color: blue}" } -->
<p>I like chocolate</p>
<!-- /wp:paragraph -->

Then, when the block is rendered int he PHP server code (inside render_block function), a id is generated (like block-instance-8675654) and used as CSS class to select only this block instance.

and final rendered HTML code will be

<style>
.block-instance-8675654 {
  color: red;
}
.block-instance-8675654:hover {
  color: blue;
}
@media (min-aspect-ratio: 2/3) {
  .block-instance-8675654 { 
    color: green;
  }
}
</style>
<p class="block-instance-8675654">I like chocolate</p>

It will be great to decide first if custom CSS per-block-instance must be linked also to theme, meaning that a theme switch will deactivated css style injection.

If yes, my first idea is to add customCSSThemeSlug attribute to the JSON stringified in the html comment.

<!-- wp:parapraph { 
  customCSSThemeSlug: "thwenty-twenty-three", 
  customCSS: "& { color: red; } &:hover { color: blue}" 
} -->
<p>I like chocolate</p>
<!-- /wp:paragraph -->

Sorry for my english, i'm not a native speaker.

@Louis7777
Copy link

Hi @tresorama . I would be curious to hear your thoughts on the new per-block CSS feature.

This new feature adds CSS to all blocks of that type, so I do not think it cover the need you explain in this issue but I would like to know how you think we could bridge this gap.

Related #49415

Hello, I'll leave here some of my own thoughts on this matter.

What I am personally curious about, is why it is that WordPress devs clearly think that custom CSS is an important aspect of customization and creativity plus they've given a considerable amount of care on SEO and performance while baking Gutenberg and many other features into WordPress, but at the same time in most discussions they prioritize site-wide custom CSS over per-block CSS, and per-post or per-page CSS seem to not be considered at all. If there's one obvious way to eliminate unused CSS in favor of performance, maintainability and good organization, then that's it, combined with per-block CSS.

The folks at Elementor, WPBakery and behind some other well-known page builders, thought that you should be able to write CSS only for specific pages, rather than having to maintain bloated global styles that contain CSS rules that will be used only by specific pages and/or blocks and remain unused on every other page, or having to write custom code to check for those pages and enqueue their stylesheets.

So I wonder why the focus with custom CSS is not on eliminating unused CSS, be it with per page/post/template styles or with any other better way the community may come up with.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Block settings menu The block settings screen [Feature] Design Tools Tools that impact the appearance of blocks both to expand the number of tools and improve the experi [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

No branches or pull requests

5 participants