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

Explore options to add back semantic classnames to block wrappers #38719

Open
glendaviesnz opened this issue Feb 10, 2022 · 33 comments
Open

Explore options to add back semantic classnames to block wrappers #38719

glendaviesnz opened this issue Feb 10, 2022 · 33 comments
Labels
CSS Styling Related to editor and front end styles, CSS-specific issues. [Feature] Themes Questions or issues with incorporating or styling blocks in a theme. [Type] Enhancement A suggestion for improvement.

Comments

@glendaviesnz
Copy link
Contributor

glendaviesnz commented Feb 10, 2022

Description

As noted here, and here the move to random class names for applying layout styling in the likes of the Buttons block has removed the ability of themes/plugins to easily target elements based on layout.

For instance, in WP 5.8 a button block that was centrer aligned would have a class assigned to indicate this:

<div class="wp-block-buttons is-content-justification-center"></div>

but in 5.9, a button block that is center aligned just has a random classname assigned to apply these styles:

<div class="wp-container-620589d3d9565 wp-block-buttons"></div>

Ideally this should be done in a way that does not involve serialising these classnames in the saved block content, so the Style engine seems like the best place to explore adding these back as this can enable it to be done at runtime from the current block semantics in both the editor and frontend.

Additional discussion has taken place here and here, in relation to the value of semantic classnames to allow themes to override styles.

This needs to be balanced out with a desire to not expose too many classnames that may not be intended as a permanent API, but which theme authors may assume they can depend on.

@glendaviesnz glendaviesnz added the CSS Styling Related to editor and front end styles, CSS-specific issues. label Feb 10, 2022
@coreyworrell
Copy link
Contributor

Another instance this happens is for link colors.

<p class="has-text-color has-primary-color has-link-color">
  This contains a <a href="#">link</a>
</p>

A class could be applied of which color was selected. Then you could do something like:

.has-primary-color.has-primary-link-color a,
.has-danger-color.has-danger-link-color a {
  text-decoration: underline;
}

@Luehrsen
Copy link
Contributor

Yes, this is a real issue.

I've written about this in a more abstract way in issue #38694.

@gziolo
Copy link
Member

gziolo commented Feb 11, 2022

The work on the Style Engine has started recently. I think it would be great to include this use case in the roadmap so we could come up with a good solution. I commented about this issue in #38167 (comment):

It looks like the automatically generated class names to move granular class names and styles outside of the block's HTML to the style tag introduce some challenges. See #38719 and #38694. It would be great to keep that on the radar while working on the Style Engine implementation.

There are vast benefits of the single automatically generated class name for a given block:

  • no excessive pollution of the HTML for the block that simplifies validation and deprecation handling
  • the ability to target inner HTML tags through CSS syntax generated on the server with style tag instead of complex handling through __experimentalSkipSerialization flag in block support.

However, it would be great to keep the flexibility of the current blocks that use several discrete class names to indicate selected block customizations like colors, fonts, etc.

Do you have some ideas on how the same goal could be achieved if you were able to access the state with all applied style modifications to the block? Would it be possible to leverage WordPress hooks in any way?

@Luehrsen
Copy link
Contributor

Do you have some ideas on how the same goal could be achieved if you were able to access the state with all applied style modifications to the block? Would it be possible to leverage WordPress hooks in any way?

Having access styles though hooks/filters would be great, but it still does not solve the underlying problem: The loss of syntax that describe the intrinsic state of the frontend component the user wants it to have. So if having access to the styles means losing the class names, that would be a hard no from us.

The practical reasons behind that are quite straightforward: You cannot target explicit styles hidden behind a selector with a random name. In a lot of larger systems you need these styles to bridge the gap between systems and to give external systems the ability to understand the state the block/component wants to be in.

The most basic example of 'external systems' would be an external stylesheet. But the possibilities are limitless. From JavaScript applications that act upon having certain classes present in the DOM, towards complex DOM tree manipulation with workers in Cloudflare.

To be perfectly clear here: Removing explicit classnames that describe state in favor of implicit, random classnames that describe style would effectively make any Gutenberg frontend a walled garden, which is the antithesis to openness. At least from our point of view this has to be avoided at all costs.

@fabiankaegy
Copy link
Member

Having access styles though hooks/filters would be great, but it still does not solve the underlying problem: The loss of syntax that describe the intrinsic state of the frontend component the user wants it to have. So if having access to the styles means losing the class names, that would be a hard no from us.

I'd have to agree with that statement. Custom theme development is not jet and may not ever come to the state where we can purely rely on theme.json and therefore relies on these state describing classnames. And that is not just for styling purposes but also in order to gain insight into the state of a component via JS.

I can sympathize with the the issues that are trying to be addressed here. But the move away from state describing classnames would make it very very hard if not impossible to work with the generated markup.

@xwolfde
Copy link

xwolfde commented Feb 11, 2022

Do you have some ideas on how the same goal could be achieved if you were able to access the state with all applied style modifications to the block? Would it be possible to leverage WordPress hooks in any way?

I had a similar issue with post-id in a page, where more as one blogroll is display and therfor the same id is used twice - which results in an validation error...

Therfor I would suggest to use random-numbers in the id like this and leave the styling attributes in the class:

<div id="wp-container-620589d3d9565" class="wp-block-buttons is-content-justification-center"></div>

Important note on the randon number in the id: If the same block with the same content might be used more as one time in the same page. take care, that is getting a new number every-time its insertet in the page.

@ZebulanStanphill ZebulanStanphill added the [Feature] Themes Questions or issues with incorporating or styling blocks in a theme. label Mar 1, 2022
@glendaviesnz glendaviesnz changed the title Move to random class names for layout removes ability for themes to target blocks based on layout Explore options to add back semantic classnames to block wrappers Mar 10, 2022
@cbirdsong
Copy link

cbirdsong commented Mar 10, 2022

Have CSS custom properties been considered as a solution? They could work with just regular CSS, no convoluted server rendering trickery or messy-looking unique IDs required. The defaults would appear in the global styles block, and elements with custom widths could have them inline.

Example going off the conversation in #38974:

.is-align-content{
   max-width: var(--wp--content-width);
}
.is-align-wide {
   max-width: var(--wp--wide-width);
}
.is-align-full {
   max-width: var(--wp--full-width);
}
<div class="wp-container wp-block-group is-align-full has-custom-layout-width" style="--wp--content-width: 50rem; --wp--wide-width: 80rem;">
   <div class="wp-container wp-block-group is-align-content">
      <!-- stuff -->
   </div>
   <div class="wp-container wp-block-group is-align-full">
      <!-- stuff -->
   </div>
</div>

These class/variable names are just approximations since I’m not super familiar with the FSE/theme.json layout system yet. Relatedly, apologies if I’ve missed something about the architecture that makes this impractical!


Fleshed this out further in:

@benplum
Copy link

benplum commented Mar 30, 2022

The classes should return, they make the most sense for custom theme developers. The button block alignment is completely useless when the 'wp_render_layout_support_flag' filter is removed.

This type of update is incredibly disruptive for clients who have no technical knowledge. Their page is simply 'broken' and the developer they can email is always to blame.

@fabiankaegy
Copy link
Member

I'd love to get a sense of whether we can expect the class names to return at least till the style engine is further along in the next WordPress 6.0 release. :)

@badlydrawnben
Copy link

+1 for this.

The semantic class names for the block wrappers seem like a much more DRY approach and use much less code.

To me, this:

<div class="wp-block-buttons is-content-justification-center">
...
</div>

seems much better than having a whole bunch of these on my pages wherever I alter a block wrapper

<div class="wp-container-62472b7e7f354 wp-block-buttons">
...
</div>
<style>.wp-container-62472b7e7f354 {display: flex;gap: 0.5em;flex-wrap: wrap;align-items: center;align-items: center;justify-content: center;}.wp-container-62472b7e7f354 > * { margin: 0; }</style>

If I look at all the internal .wp-container-xxxxxxxxx style tags at the bottom of a typical page then they look almost identical. There could be 5-10 of them in there to center items that were happily being centred previously with the .is-content-justification-center classname and one CSS rule in my external stylesheet.

This is with a Theme that doesn't have a theme.json file. Whenever I save a page that was created pre5.9 it replaces the semantic classes with the newer multiple-internal-CSS-tags one. I was happy with the way things were but I can't see a way to disable all these internal CSS tags whilst retaining the semantic classes which are no longer used by 5.9+

@Luehrsen
Copy link
Contributor

Luehrsen commented Apr 2, 2022

I'd love to get a sense of whether we can expect the class names to return at least till the style engine is further along in the next WordPress 6.0 release. :)

I was under the impression, that the missing (removed) classes would be classified as a regression bug and therefore obviously be part of the next major release. Is that not the case?

@tellthemachines
Copy link
Contributor

Having read the excellent discussion taking place here and in #38998, I'd like to jump in with a couple of thoughts.

This needs to be balanced out with a desire to not expose too many classnames that may not be intended as a permanent API, but which theme authors may assume they can depend on.

As far as I understand it (please correct me where needed), classnames-as-API are undesirable because:

  • Plugins can output the same classnames using a different logic to core, with potentially unpredictable results if themes style those classnames directly;
  • We want to encourage theme authors to use the theme.json API where possible, so that the hierarchy of base > theme > user defined styles can be resolved correctly.

Classnames are currently an implementation detail of the wider style-processing mechanisms we are working on, meaning they aren't stable or consistent enough to work well as a public API. But theme authors are using them, and holding them to the standards of a public API (which is why new features keep falling short of these standards). This may reflect a communication problem, but it also reflects an insufficiency of the current API, because theme authors are having to reach around and find non-standard solutions to their problems.

Should we obfuscate some of those generated classnames to avoid them being used in non-standard ways? As mentioned in #38998 and its accompanying blog post, there are many situations where themes may want to hook styles to a certain block state, and going down the obfuscation path will remove the possibility entirely. I believe we should avoid such brute force methods, if for no other reason than no-one stands to gain from them.

It's not just theme authors that will become frustrated with not being able to implement their designs with the amount of lovingly crafted detail we have become used to in WP themes. It's also website developers building throwaway marketing campaigns, students or hackathon participants putting together quick prototypes, newbies just learning how to code. An inflexible system that's designed to be used in only one way won't serve any of those folks.

We can and should educate everyone on the best way to build themes: docs and tutorials about what can be done with theme.json, and how to do it. Docs discouraging use of classnames where there's a better way to accomplish the goal.

But sometimes there isn't a better way to accomplish the goal, and the best we can do in that case is provide a good safety net of consistent and meaningful classnames.

@Luehrsen
Copy link
Contributor

Luehrsen commented Apr 4, 2022

But theme authors are using them, and holding them to the standards of a public API (which is why new features keep falling short of these standards).

But that is exactly what they are. By definition. That is what CSS classes have been built for and that is what their reason of existence is. For an obfuscated approach where theme.json is the only and singular source of truth, we could completely abandon css classes and just use IDs.

But we already know that this approach does not scale. I am aware, that a lot of JS first developers love the obfuscated approach for its control and lockdown, but that would mean abandoning best practices defined by the last 25 years of HTML/CSS and essentially forcing a whole industry to adapt a standard workflow to a custom, untested, unscaled approach - at the scale of 43% of the web. Some would call that bold, I would use a different term.

It's also website developers building throwaway marketing campaigns, students or hackathon participants putting together quick prototypes, newbies just learning how to code. An inflexible system that's designed to be used in only one way won't serve any of those folks.

This is the exact reason why we need well defined and dependable CSS classes, that describe the current state of a DOM element. Could not have written that better myself.

We can and should educate everyone on the best way to build themes: docs and tutorials about what can be done with theme.json, and how to do it. Docs discouraging use of classnames where there's a better way to accomplish the goal.

This makes an assumption of two things that are highly unlikely:

  1. The fact that docs will be written and maintained in a meaningful, easy to understand and approachable way. I think the WordPress docs team can sing a song about how much wishful thinking this is.
  2. Making developers aware that a fundamental concept of the web has changed in a software powering 43% of the web in case they hit a roadblock, directing them to those docs. At this scale that will lead to A LOT of frustrated developers and WordPress will be hit by a massive loss of trust.

Plugins can output the same classnames using a different logic to core, with potentially unpredictable results if themes style those classnames directly;

While this is true, this is not an argument for theme.json, as plugins can also influence the rendering of the styles. This is one of the core strengths and weaknesses of WordPress: A plugin can fundamentally change any aspect of the system. And until the Gutenberg team decides to abandon plugins, there is nothing that can be done about that.


To quote myself from #38694:

Removing explicit classnames that describe state in favor of implicit, random classnames that describe style would effectively make any Gutenberg frontend a walled garden, which is the antithesis to openness. At least from our point of view this has to be avoided at all costs.

@cbirdsong
Copy link

cbirdsong commented Apr 8, 2022

Another issue with autogenerated CSS is that Wordpress and Gutenberg can no longer be used with a strict content security policy. This issue was previously raised in #9534 (comment) by @Adrian-Fischer, but CSPs are not otherwise mentioned anywhere in this repo outside of backend troubleshooting.

It seems reasonable that any autogenerated CSS should be able to be removed from the page and have the target fall back to a standard set of CSS located in traditional stylesheets loaded using <link rel="stylesheet" >, as that will ensure an at least functional experience under a strict CSP.

@pattyok
Copy link

pattyok commented Apr 16, 2022

There doesn't seem to be a fix in 6.0beta. Does that mean a fix is not coming?

I have a certain button style that I want to wrap differently depending on whether it is left or center aligned. There is no way for me to control that so I now have to make button-style-a, and button-style-a-left which is totally redundant and means I have to override the users choices anyway so you haven't really solved any problems with this approach.

@cbirdsong
Copy link

I used a block filter to restore the previous classes.

function block_filter_buttons_add_alignment_class($block_content, $block)
{
	if (empty($block["attrs"]["layout"])) {
		return $block_content;
	}

	$classes = [];

	if (!empty($block["attrs"]["layout"]["orientation"])) {
		$classes[] = "is-" . $block["attrs"]["layout"]["orientation"];
	}

	if (!empty($block["attrs"]["layout"]["justifyContent"])) {
		$classes[] = "is-content-justification-" . $block["attrs"]["layout"]["justifyContent"];
	}

	if (!empty($block["attrs"]["layout"]["flexWrap"]) && ($block["attrs"]["layout"]["flexWrap"] = "nowrap")) {
		$classes[] = "is-nowrap";
	}

	if (!empty($classes)) {
		$classes = implode(" ", $classes);

		$search = 'class="wp-block-buttons';
		$replace = 'class="wp-block-buttons ' . $classes;
		$block_content = str_replace($search, $replace, $block_content);
	}

	return $block_content;
}
add_filter("render_block_core/buttons", "block_filter_buttons_add_alignment_class", 10, 2);

@benplum
Copy link

benplum commented Apr 18, 2022

We're also including more of these custom render functions to deal with the shifting API, but they should be unnecessary. WP has historically stood by backwards compatibility (almost to a fault), making the constant changes on point releases unnerving.

@pattyok
Copy link

pattyok commented Apr 18, 2022

Thank you @cbirdsong for the filtering example!

With the added wp-container-x class, I just had to change the search and replace to use regular expressions.

$search  = '/class="(.*?)wp-block-buttons/';
$replace = 'class="$1wp-block-buttons ' . $classes;
$block_content = preg_replace( $search, $replace, $block_content );

@mtias
Copy link
Member

mtias commented Apr 25, 2022

There's been some roundabout discussions here that I think we need to untangle. It's obvious we need semantic classes and that premise doesn't conflict with the use of theme.json. The presence of obfuscated classes (essentially IDs) should be seen as a temporary state as the style engine is tweaked and its attributes standardized. @cbirdsong I see CSS variables as orthogonal since they will need to be hooked to classes or inline styles anyways.

In terms of tasks, it seems we need to:

  • Add block type classes (some blocks are missing them).
  • Restore previously semantic classes that were removed.
  • Converge into semantic classes and avoid obfuscated classes for other attributes (should be done gradually based on the attribute stability).
    • Consider the current ID-based classes to be of use for custom CSS purposes (i.e. when we allow custom CSS on a group, etc).
    • Allow users to turn custom modifications into reusable style encapsulations (i.e. classes).
  • Do it all without serializing classes.

Am I missing anything?

@cbirdsong
Copy link

cbirdsong commented Apr 25, 2022

I would add:

  • Standardize classes that can be universal.

    For example, flex alignment: on buttons, it was is-content-justification-<direction>, the columns block uses is-vertically-aligned-<direction>, and the cover block uses a more complex .is-position-<vertical direction>-<horizontal direction>. The row/stack group block variations will also need one of these, and there’s no reason for them to all be different. This should be part of the standard CSS toolkit proposed in Proposal: Standardized block markup, theme.json design tokens, and CSS classes to improve interoperability #38998.

  • Add BEM-style child classes or equivalents to any non-innerBlocks child elements that currently lack them.

    Ideally, core styles should not use any descendant selectors, and switching as much of that as possible to classes would help to reduce the level of specificity used in core styles and provide more stable markup to build on moving forward. They would also generally reduce the complexity of writing block CSS since it has to support every version of a block simultaneously.


I should make a separate issue detailing this further, but it’s related:

I see CSS variables as orthogonal since they will need to be hooked to classes or inline styles anyways.

As I mentioned above, the recent heavy reliance on serialized/injected CSS makes stock Wordpress incompatible with a strict content security policy. A robust set of semantic class names would be a good start toward supporting a basic level of functionality with inlined/serialized CSS disabled, and doing that would ultimately lead to more robust and well thought out CSS overall. (again, much of that overlapping with good ol’ #38998)

@eric-michel
Copy link

I would add:
Standardize classes that can be universal.

Two standard class names that I would give my left leg to see implemented are something like .is-dark and .is-light on any element with a background color selected.

I am constantly trying to provide my content editors with sensible defaults that make editing as easy as possible. That includes automatically changing the foreground color from dark to light if the chosen background is dark, without the need to also manually select a foreground color that contrasts well.

I have ways to accomplishing that, but they involve automatic color assessment in SASS, along with some extra CSS.

Gutenberg already has a way to assess lightness or darkness in the editor. I know that because the Cover block is automagically given an .is-light class when the background color is light, and its foreground color is adjusted appropriately. However, no other block currently takes advantage of this feature. In Twenty Twenty-Two I can create a Group block with a black background, and the text stays black by default.

If the editor automatically generated an .is-dark class for all appropriate blocks, my stylesheet for a typical site with a default white background could simply be:

body {
  color: black;
}

.is-dark {
  color: white;
}

All of a sudden, in six lines of CSS, I have sensible defaults for all background colors for my editors no matter what my color palette is, because the editor will handle calculating whether any given color is light or dark. And, just as importantly, this provides ideal accessibility out-of-the-box. Of course, those foreground colors can be manually changed by selecting something different from the color palette if desired.

In a perfect world, I would love for the editor to generate .is-dark or .is-light classes where appropriate for all elements (not just one or the other, as the Cover block currently does). This give the flexibility to have light and dark modes, with the default body color changing as-needed (and avoids the need for :not selectors).

pento pushed a commit to WordPress/wordpress-develop that referenced this issue Jun 23, 2022
…utes specified.

[WordPress/gutenberg#38719 In 5.9 these utility classnames were removed], which removed the ability for theme/plugin authors to assign their own custom CSS related to specific layout selections. This was mostly related to the Button block.

This commit adds these classes dynamically based on attributes, rather than saving them to the serialized content.

Original PR from Gutenberg repository:
* [WordPress/gutenberg#41487 #41487 Add utility classnames back to blocks that have layout attributes specified]

Props glendaviesnz, peterwilsoncc, andrewserong, zieladam, matveb, samikeijonen.
See #56058.

git-svn-id: https://develop.svn.wordpress.org/trunk@53568 602fd350-edb4-49c9-b593-d223f7449a82
markjaquith pushed a commit to markjaquith/WordPress that referenced this issue Jun 23, 2022
…utes specified.

[WordPress/gutenberg#38719 In 5.9 these utility classnames were removed], which removed the ability for theme/plugin authors to assign their own custom CSS related to specific layout selections. This was mostly related to the Button block.

This commit adds these classes dynamically based on attributes, rather than saving them to the serialized content.

Original PR from Gutenberg repository:
* [WordPress/gutenberg#41487 #41487 Add utility classnames back to blocks that have layout attributes specified]

Props glendaviesnz, peterwilsoncc, andrewserong, zieladam, matveb, samikeijonen.
See #56058.
Built from https://develop.svn.wordpress.org/trunk@53568


git-svn-id: http://core.svn.wordpress.org/trunk@53157 1a063a9b-81f0-0310-95a4-ce76da25c4cd
pento pushed a commit to WordPress/wordpress-develop that referenced this issue Jun 23, 2022
…utes specified.

[WordPress/gutenberg#38719 In 5.9 these utility classnames were removed], which removed the ability for theme/plugin authors to assign their own custom CSS related to specific layout selections. This was mostly related to the Button block.

This commit adds these classes dynamically based on attributes, rather than saving them to the serialized content.

Original PR from Gutenberg repository:
* [WordPress/gutenberg#41487 #41487 Add utility classnames back to blocks that have layout attributes specified]

Props glendaviesnz, peterwilsoncc, andrewserong, zieladam, matveb, samikeijonen.
Merges [53568] to the 6.0 branch.
See #56058.

git-svn-id: https://develop.svn.wordpress.org/branches/6.0@53569 602fd350-edb4-49c9-b593-d223f7449a82
markjaquith pushed a commit to markjaquith/WordPress that referenced this issue Jun 23, 2022
…utes specified.

[WordPress/gutenberg#38719 In 5.9 these utility classnames were removed], which removed the ability for theme/plugin authors to assign their own custom CSS related to specific layout selections. This was mostly related to the Button block.

This commit adds these classes dynamically based on attributes, rather than saving them to the serialized content.

Original PR from Gutenberg repository:
* [WordPress/gutenberg#41487 #41487 Add utility classnames back to blocks that have layout attributes specified]

Props glendaviesnz, peterwilsoncc, andrewserong, zieladam, matveb, samikeijonen.
Merges [53568] to the 6.0 branch.
See #56058.
Built from https://develop.svn.wordpress.org/branches/6.0@53569


git-svn-id: http://core.svn.wordpress.org/branches/6.0@53158 1a063a9b-81f0-0310-95a4-ce76da25c4cd
gMagicScott pushed a commit to gMagicScott/core.wordpress-mirror that referenced this issue Jun 23, 2022
…utes specified.

[WordPress/gutenberg#38719 In 5.9 these utility classnames were removed], which removed the ability for theme/plugin authors to assign their own custom CSS related to specific layout selections. This was mostly related to the Button block.

This commit adds these classes dynamically based on attributes, rather than saving them to the serialized content.

Original PR from Gutenberg repository:
* [WordPress/gutenberg#41487 #41487 Add utility classnames back to blocks that have layout attributes specified]

Props glendaviesnz, peterwilsoncc, andrewserong, zieladam, matveb, samikeijonen.
Merges [53568] to the 6.0 branch.
See #56058.
Built from https://develop.svn.wordpress.org/branches/6.0@53569


git-svn-id: https://core.svn.wordpress.org/branches/6.0@53158 1a063a9b-81f0-0310-95a4-ce76da25c4cd
gMagicScott pushed a commit to gMagicScott/core.wordpress-mirror that referenced this issue Jun 23, 2022
…utes specified.

[WordPress/gutenberg#38719 In 5.9 these utility classnames were removed], which removed the ability for theme/plugin authors to assign their own custom CSS related to specific layout selections. This was mostly related to the Button block.

This commit adds these classes dynamically based on attributes, rather than saving them to the serialized content.

Original PR from Gutenberg repository:
* [WordPress/gutenberg#41487 #41487 Add utility classnames back to blocks that have layout attributes specified]

Props glendaviesnz, peterwilsoncc, andrewserong, zieladam, matveb, samikeijonen.
See #56058.
Built from https://develop.svn.wordpress.org/trunk@53568


git-svn-id: https://core.svn.wordpress.org/trunk@53157 1a063a9b-81f0-0310-95a4-ce76da25c4cd
@eric-michel
Copy link

I know there's been general agreement that improvements are needed, but it's been 6 months since this issue was raised and, for the most part, there hasn't been a ton of improvement. Below is the CSS output from WP on a sample page of one of my test sites that simply has 11 columns blocks on it:

Look at this
<style>.wp-container-1 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-1 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-1 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-2 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-2 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-2 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-3 {display: flex;gap: 2em;flex-wrap: nowrap;align-items: center;}.wp-container-3 > * { margin: 0; }</style>
<style>.wp-container-4 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-4 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-4 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-5 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-5 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-5 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-6 {display: flex;gap: 2em;flex-wrap: nowrap;align-items: center;}.wp-container-6 > * { margin: 0; }</style>
<style>.wp-container-7 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-7 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-7 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-8 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-8 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-8 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-9 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-9 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-9 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-10 {display: flex;gap: 2em;flex-wrap: nowrap;align-items: center;}.wp-container-10 > * { margin: 0; }</style>
<style>.wp-container-11 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-11 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-11 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-12 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-12 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-12 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-13 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-13 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-13 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-14 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-14 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-14 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-15 {display: flex;gap: 2em;flex-wrap: nowrap;align-items: center;}.wp-container-15 > * { margin: 0; }</style>
<style>.wp-container-16 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-16 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-16 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-17 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-17 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-17 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-18 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-18 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-18 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-19 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-19 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-19 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-20 {display: flex;gap: 2em;flex-wrap: nowrap;align-items: center;}.wp-container-20 > * { margin: 0; }</style>
<style>.wp-container-21 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-21 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-21 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-22 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-22 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-22 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-23 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-23 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-23 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-24 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-24 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-24 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-25 {display: flex;gap: 2em;flex-wrap: nowrap;align-items: center;}.wp-container-25 > * { margin: 0; }</style>
<style>.wp-container-26 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-26 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-26 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-27 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-27 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-27 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-28 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-28 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-28 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-29 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-29 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-29 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-30 {display: flex;gap: 2em;flex-wrap: nowrap;align-items: center;}.wp-container-30 > * { margin: 0; }</style>
<style>.wp-container-31 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-31 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-31 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-32 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-32 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-32 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-33 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-33 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-33 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-34 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-34 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-34 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-35 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-35 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-35 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-36 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-36 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-36 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-37 {display: flex;gap: 2em;flex-wrap: nowrap;align-items: center;}.wp-container-37 > * { margin: 0; }</style>
<style>.wp-container-38 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-38 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-38 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-39 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-39 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-39 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-40 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-40 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-40 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-41 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-41 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-41 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-42 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-42 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-42 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-43 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-43 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-43 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-44 {display: flex;gap: 2em;flex-wrap: nowrap;align-items: center;}.wp-container-44 > * { margin: 0; }</style>
<style>.wp-container-45 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-45 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-45 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-46 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-46 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-46 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-47 {display: flex;gap: 2em;flex-wrap: nowrap;align-items: center;}.wp-container-47 > * { margin: 0; }</style>
<style>.wp-container-48 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-48 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-48 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-49 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-49 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-49 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-50 > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.wp-container-50 > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.wp-container-50 > .aligncenter { margin-left: auto !important; margin-right: auto !important; }</style>
<style>.wp-container-51 {display: flex;gap: 2em;flex-wrap: nowrap;align-items: center;}.wp-container-51 > * { margin: 0; }</style>

Just to pick a property definition at random, it defines margin-left: auto !important; 40 times. This violates any reasonable CSS development philosophy. Installing the latest version of the Gutenberg plugin does not improve the issue.

I recognize this is all a work in process. But unfortunately, at some point, this was allowed this to reach production in its current form and now it desperately needs to be fixed. It's creating huge headaches for maintaining existing sites because of priority and specificity issues. Those of us trying to maintain sites are already scrambling during release cycles with CSS breaking changes we have to fix, and the way this CSS is applied is a force multiplier to that problem.

I think it's absolutely critical that Gutenberg gets back to proper semantic class names that can be easily overridden in the theme for the 6.1 release. This just isn't a can that can get kicked down the road. Ever since 5.9, I've dreaded even minor releases because of what might break.

@markhowellsmead
Copy link

There are notable improvements already merged in #40875.

@eric-michel
Copy link

Thanks @markhowellsmead! I will definitely take a look and try them out. Will be really glad to see some progress.

@mtias
Copy link
Member

mtias commented Sep 10, 2022

@glendaviesnz what do we have pending here?

@glendaviesnz
Copy link
Contributor Author

@glendaviesnz what do we have pending here?

As far as I am aware the main pain point of Layout supports relying the random container ids was the main focus for 6.1 and this has been resolved. Post 6.1 the aim is to extend the scope of semantic class names and/or design token expressions in the style engine, and encapsulate rules into stable utility classes, as noted here.

@mtias
Copy link
Member

mtias commented Sep 12, 2022

That's great, we should ensure this gets to be communicated properly in dev notes and theme notes.

@andrewserong
Copy link
Contributor

I think the main change was in #40875, so I'm happy to write up a short dev note for that (basically, expanding on the idea that blocks that use Layout no longer have a random container id class when they use default settings, so that the container id is only in use when the block utilises non-default settings / has unique settings set at the block level).

I also have a WIP draft PR (#42619) to start documenting how the Layout support works (and the classnames it outputs). I've held off on pushing forward that PR during this period just before the feature freeze since things are still a little in flux, but plan to dust it off once we know exactly what's made it into the 6.1 Beta.

whereiscodedude pushed a commit to whereiscodedude/wpss that referenced this issue Sep 18, 2022
…utes specified.

[WordPress/gutenberg#38719 In 5.9 these utility classnames were removed], which removed the ability for theme/plugin authors to assign their own custom CSS related to specific layout selections. This was mostly related to the Button block.

This commit adds these classes dynamically based on attributes, rather than saving them to the serialized content.

Original PR from Gutenberg repository:
* [WordPress/gutenberg#41487 #41487 Add utility classnames back to blocks that have layout attributes specified]

Props glendaviesnz, peterwilsoncc, andrewserong, zieladam, matveb, samikeijonen.
Merges [53568] to the 6.0 branch.
See #56058.
Built from https://develop.svn.wordpress.org/branches/6.0@53569
whereiscodedude pushed a commit to whereiscodedude/wpss that referenced this issue Sep 18, 2022
…utes specified.

[WordPress/gutenberg#38719 In 5.9 these utility classnames were removed], which removed the ability for theme/plugin authors to assign their own custom CSS related to specific layout selections. This was mostly related to the Button block.

This commit adds these classes dynamically based on attributes, rather than saving them to the serialized content.

Original PR from Gutenberg repository:
* [WordPress/gutenberg#41487 #41487 Add utility classnames back to blocks that have layout attributes specified]

Props glendaviesnz, peterwilsoncc, andrewserong, zieladam, matveb, samikeijonen.
See #56058.
Built from https://develop.svn.wordpress.org/trunk@53568
@cbirdsong
Copy link

cbirdsong commented Feb 1, 2023

I know there's been general agreement that improvements are needed, but it's been 6 months since this issue was raised and, for the most part, there hasn't been a ton of improvement.

Since this comment was written things have improved, but there are still some very strange choices with the way CSS is being structured and deployed here. For instance:

.wp-block-columns.wp-container-3,.wp-block-columns.wp-container-6,.wp-block-columns.wp-container-9,.wp-block-columns.wp-container-12,.wp-block-columns.wp-container-15,.wp-block-columns.wp-container-18,.wp-block-group.wp-container-25,.wp-block-group.wp-container-26,.wp-block-group.wp-container-27,.wp-block-group.wp-container-28,.wp-block-group.wp-container-29,.wp-block-group.wp-container-30,.wp-block-columns.wp-container-40,.wp-block-columns.wp-container-43,.wp-block-columns.wp-container-46,.wp-block-columns.wp-container-49,.wp-block-columns.wp-container-52,.wp-block-columns.wp-container-55,.wp-block-group.wp-container-62,.wp-block-group.wp-container-63,.wp-block-group.wp-container-64,.wp-block-group.wp-container-65,.wp-block-group.wp-container-66,.wp-block-group.wp-container-67 {
    flex-wrap: nowrap;
}

These blocks already have an is-nowrap class that is not otherwise used, and this entire block of CSS could simply be:

.is-nowrap {
    flex-wrap: nowrap;
}

The stack variation of the group block has the same issue. What currently is generated:

.wp-block-group.wp-container-31,.wp-block-group.wp-container-32,.wp-block-group.wp-container-33,.wp-block-group.wp-container-34,.wp-block-group.wp-container-35,.wp-block-group.wp-container-36,.wp-block-group.wp-container-68,.wp-block-group.wp-container-69,.wp-block-group.wp-container-70,.wp-block-group.wp-container-71,.wp-block-group.wp-container-72,.wp-block-group.wp-container-73 {
    flex-direction: column;
    align-items: flex-start;
}

Again, the is-vertical class already exists on these blocks right now, and could be used like this:

.is-layout-flex.is-vertical {
    flex-direction: column;
    align-items: flex-start;
}

Also, to keep this from being entirely negative – the ability to use add_theme_support( 'disable-layout-styles' ); and get rid of this inefficient CSS is a fantastic option and I'd love to see more ability to opt in/out of certain pieces of core CSS without having to throw the entire thing out.

VenusPR added a commit to VenusPR/Wordpress_Richard that referenced this issue Mar 9, 2023
…utes specified.

[WordPress/gutenberg#38719 In 5.9 these utility classnames were removed], which removed the ability for theme/plugin authors to assign their own custom CSS related to specific layout selections. This was mostly related to the Button block.

This commit adds these classes dynamically based on attributes, rather than saving them to the serialized content.

Original PR from Gutenberg repository:
* [WordPress/gutenberg#41487 #41487 Add utility classnames back to blocks that have layout attributes specified]

Props glendaviesnz, peterwilsoncc, andrewserong, zieladam, matveb, samikeijonen.
Merges [53568] to the 6.0 branch.
See #56058.
Built from https://develop.svn.wordpress.org/branches/6.0@53569


git-svn-id: http://core.svn.wordpress.org/branches/6.0@53158 1a063a9b-81f0-0310-95a4-ce76da25c4cd
@mehne
Copy link

mehne commented Mar 30, 2023

Hi,

I want to add an issue:

Since wordpress 6.2 the default output for .is-layout-flex is

body .is-layout-flex { flex-wrap: wrap; align-items: center; }

But why change the default align-items to center? This destroys many layouts.
And on top of that it is not changeable in the editor, so you have to override it via css.

Possible solution:
remove the align-items: center; from the default class definition

@andrewserong
Copy link
Contributor

Thanks for the feedback @mehne. The align-items: center rule predates WordPress 6.2, so as far as I'm aware there hasn't been a change there in 6.2. There is an open PR from @tellthemachines looking to explore removing that default, though, over in #47099.

And on top of that it is not changeable in the editor, so you have to override it via css.

In WordPress 6.2, vertical alignments are allowed in both horizontal and vertical flex orientations. So, as of #47134, you should be able to adjust the align-items of Row and Stack blocks without having add in additional CSS.

If there's anything not covered there, feel free top open a separate issue, though!

@mehne
Copy link

mehne commented Mar 31, 2023

Thanks for your answer @andrewserong.
I opened a new issue with a more detailed description of the/my)problem here: #49502
It started with 6.2 and wasn't there in 6.1 (I think it was a bug in 6.1) but see my issue for more details.

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] Themes Questions or issues with incorporating or styling blocks in a theme. [Type] Enhancement A suggestion for improvement.
Projects
Status: 📢 Not started
Development

No branches or pull requests