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

General CSS Concepts: Declaring style vs. describing state #38694

Open
Luehrsen opened this issue Feb 10, 2022 · 16 comments
Open

General CSS Concepts: Declaring style vs. describing state #38694

Luehrsen opened this issue Feb 10, 2022 · 16 comments
Labels
CSS Styling Related to editor and front end styles, CSS-specific issues. Developer Experience Ideas about improving block and theme developer experience [Feature] Themes Questions or issues with incorporating or styling blocks in a theme. Global Styles Anything related to the broader Global Styles efforts, including Styles Engine and theme.json [Type] Discussion For issues that are high-level and not yet ready to implement.

Comments

@Luehrsen
Copy link
Contributor

Luehrsen commented Feb 10, 2022

I feel we have a conflict of concepts in the project at the moment. I am not sure in which direction we are going (in terms of this specific concept) and I think a clear definition of what we want to achieve would be beneficial in understanding the rest of the components and set clear(er) expectations.

Definitions

Before we talk about the conflict of concepts themselves I want to quickly describe (my understanding of) the meaning of the concepts in conflict.

Describing State: Following this concept we want to describe the current state a component, or block, is currently in. A state would describe if an element has a background with the has-background class, or which font size it has with has-font-size-regular. We use these states all over the project and we can easily spot those descriptor-classes with the has- or is- prefixes.

Declaring Style: Sometimes we add some specific style declarations to elements to reflect a state. One example would be the width of columns in the core/columns block. If we set a column to 12% width, a flex-basis: 12% style declaration is added explicitly, as a general description of state (e.g. with has-width-12percent) would lead to a lot of redundancy and duplication. (I'm looking at you, Tailwind!)

Why this matters

As theme developers we sometimes like or need some leeway in terms of how to interpret a certain state of a block or element. For example has-font-size-regular imposes no opinionated value of what regular means. We have some default settings set by the block editor, but as a theme we are free to interpret what regular means and overwrite the defaults.

On the other hand, setting a width on a column declares a very strict flex-basis: 12%, which locks us as theme developers in a corner. We have to use flex for columns, even it we wanted to use something else (like css grid).

My proposal

For us as themers interpreting a state gives us a lot more freedoms to interpret the assumptions compared to working with declared styles. So I would love the project to explore where a style declaration could also be a state description.

One important aspect of modern CSS is the fact, that we do not only have classes to describe state, but also CSS variables. So for example setting --wp--has--width: 12% on a core/column block would still allow the project to have explicitly set defaults, but at the same time allow themers some more freedoms of choice with how we interpret the state.

The ticket #38677 is another example of where a descriptive state would be helpful and a declarative style is applied.

So I would love to add "Describing state over declaring style" to the set of values for this project. I think it has value to encourage contributors to use state instate of styles when refactoring or newly implementing (frontend) elements.

Thank you!

@annezazu annezazu added [Feature] Themes Questions or issues with incorporating or styling blocks in a theme. [Type] Discussion For issues that are high-level and not yet ready to implement. Developer Experience Ideas about improving block and theme developer experience Global Styles Anything related to the broader Global Styles efforts, including Styles Engine and theme.json labels Feb 10, 2022
@annezazu
Copy link
Contributor

Thanks for kicking off this discussion. I've added some labels to ensure folks can find it more readily. I might also bring this to the next Core Editor meeting (you can see agendas here). To cross connect what feels related too, here's an issue on standardizing a way to modify hover/focus/active states #27075

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

Thank you @annezazu for triaging this issue. #27075 is more about "that it should be done", this is more about "how it should be done". So similar goal, different perspective.

@annezazu
Copy link
Contributor

Correct! I believe they influence each other so wanted to be sure there was some cross connection.

@chthonic-ds
Copy link
Contributor

#36525 is another related ticket, where the Navigation block saw the removal of a descriptive is-vertical class. The class has thankfully appeared again, though it's unclear if this is temporary: the issue has been closed but not explicitly resolved.

@scruffian
Copy link
Contributor

I find the has- and is- classes difficult because it complicates the contract between things Gutenberg control and things the theme controls. In general it should be up to Gutenberg to add CSS for these things, not the theme. In my opinion, in most cases there should be no need for themes to implement CSS to target components using state selectors, as Gutenberg should be taking care of all that stuff. Instead the theme should be modifying the CSS variables so the block can simply declare: font-size: var(--wp--preset--font-size--medium). The theme can control the value of that variable using theme.json.

There are exceptions to this though, for example some block attributes don't map cleanly to one CSS rule. In these cases a. state class may be necessary to allow a combination of CSS rules to apply to the block. It would be best for themes to avoid targeting these rules if the theme is expected to be easily switchable otherwise users might have some unexpected changes when they switch.

@Luehrsen
Copy link
Contributor Author

In general it should be up to Gutenberg to add CSS for these things, not the theme. In my opinion, in most cases there should be no need for themes to implement CSS to target components using state selectors, as Gutenberg should be taking care of all that stuff.

That is a nice thing to want, but it simply does not reflect the reality how WordPress is currently used and what users (end users and developers) expect.

As I said in #38719: 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.

@chthonic-ds
Copy link
Contributor

chthonic-ds commented Feb 11, 2022

I find the has- and is- classes difficult because it complicates the contract between things Gutenberg control and things the theme controls

The problem is this contract is not clear and far from complete as we enter the 6th year of Gutenberg development. Gutenberg does not yet enable precise and predictable content layout for even quite simple designs, and themes conveniently continue to do the heavy lifting in many regards.

In my opinion, in most cases there should be no need for themes to implement CSS to target components using state selectors, as Gutenberg should be taking care of all that stuff

This may be fine when a theme has originated in the editor and is naturally contained by the UI exposed by Gutenberg, not so much when bringing a 3rd-party design to Gutenberg. Unless designers embrace designing with Gutenberg—unlikely for the majority considering the far more expressive visual layout tools that are currently available—there will always be exceptions that Gutenberg cannot reasonably anticipate but needs to accommodate. With Gutenberg assuming responsibility for the shape of component markup it becomes especially important to bake in attributes that can help theme developers target anything Gutenberg hasn't anticipated.

@mrwweb
Copy link

mrwweb commented Feb 12, 2022

I'm working on a blog post to hopefully provide greater detail, but I want to weigh in now to hopefully keep this conversation moving. I'm hitting publish a little sooner than I normally would. I'm happy to clarify futher

It appears that the vision of Gutenberg involves no theme-authored CSS and I don't think that's possible

For a long time, I have not had a clear understanding of the final vision for how WordPress styling will be done. Both on this issue and others, it sounds like core developers envision no theme-provided CSS at all.

"In general it should be up to Gutenberg to add CSS for these things"

"we aim to absorb all the theme CSS via theme.json"

If that were possible, then the direction of using inline and autogenerated styles makes lots of sense. However, I just do not see how that is possible. I can't see how theme.json could ever replicate every possible CSS function covering pseudo classes, pseudo elements, media queries (and container queries!), user preference queries, sibling/descendent selectors, and every combination of those things. I can say from lived experience (not just hypotheticals) that I've built themes where I want to write rules that:

  • Change the spacing between blocks depending on the consecutive alignment of those blocks
  • Reinterpret vertical alignment in Media & Text or Column blocks
  • Apply text shadows to blocks depending on their background or font colors or whether they are on a gradient
  • Set font colors based on background colors
  • Choose a different CSS mask shape depending on which of many "random" nth-child formulas a Cover block matches

I can also envision lots of other scenarios where themes need access to block's state on the front-end that I can't imagine theme.json supporting. For example, creating a set of scroll-triggered animations of the Media & Text block that are dependent on the position of the media and the vertical alignment of the content.

The changes in 5.9 have already broken sites for me by removing some of these classes like the ones on the social icons block.

Update (14 Feb 2022): I was directed to @mtias's comment on #35469 by @luisherranz today which implies that the intended CSS responsibility is intended to be more like 80/20. Not only does that feel right, but it makes it extra clear that themes and plugins need consistent markup and style expectations to customize core markup and styles. Big picture: @luisherranz was super smart to ask the question on that thread the way they did and it answered a huge question I know I and many other theme builders have had for a long time. The answer also seems counter to a lot of other comments and decisions I see happening right now when it comes to markup and CSS. It feels like a period of broad community discussion and feedback is needed to make sure that the direction of markup and styles in core is lean, fast, accessible, portable between themes, and customizable outside of the UI.

Theme Lockin vs. Theme Flexibility

If the plan is that WordPress outputs all CSS as inline styles and style blocks, then it would become very hard to move content to a new theme because so much of the styling is tied to specific block style values. I don't agree with the comment above:

It would be best for themes to avoid targeting these rules if the theme is expected to be easily switchable otherwise users might have some unexpected changes when they switch

The beauty of switching themes is that the content stays the same but the design (aka "theme"!) is different. People specifically switch themes so that their sites look different.

If there are standardized classes and design tokens (more on that in a moment), then themes can faithfully reinterpret user choices, letting them shift their content cohesively from one design system to another.

With recent talk of creating an interoperable block standard across platforms, it's even more critical that the state of blocks is represented in the markup and not the styles.

What A Better Future Could Look Like

Here's a rough outline of a better path forward. Happily, this builds a ton on the groundwork already by WordPress!

Design Tokens: I think theme.json needs to be viewed as a design token system. It is for saving design-related values (including what parts of the design are user editable) that the WordPress backend, WordPress frontend, and theme can all share. There is a huge opportunity to further standardize these token names (font sizes and colors, obviously, but also gap sizing and widths and responsive breakpoints!) so that themes become more interoperable. @richtabor had some popular posts with proposals around font sizes and colors that lay out why this would be so valuable.

Compontent Framework: Blocks are already components, and yet they don't feel much like they're treated as standardized HTML front-end components. A while ago, I tried to document all possible selectors for blocks so that themes could have a set starting point for theming. I know now that many of these selectors are incorrect and out-dated. These classes are GREAT. They should be carefully considered, document, and standardized.

What this OP is asking for—and what I thoroughly believe the future of the block editor and FSE should be—is for a set of front-end components with consistent markup and CSS classes that are given baseline values by the design tokens in theme.json.

Inline Styles for one-off values: There will still be moments where user-customized values need to be inlined. Column width percentages are a great example. It's fine for these to be inline styles. They are one-off decisions made by editors that should be treated as one-off styles, which is exactly the purpose of the style attribute or style element.

When put together, you get something that is close to what currently exists but is significantly more standardized, documented, and leaner due to better shared styles. I'd love to see BEM-style classes for each block with utility classes tied to theme.json styles, much as is described in the CSS-Tricks post: "Building a Scalable CSS Architecture With BEM and Utility Classes"

The Advantages of a Front-end Framework + theme.json standardized design tokens

This system allows:

  1. theme authors to create interoperable baseline definitions for standard design needs (colors, font sizes, spacing)
  2. third-party blocks to take advantage of standardized design tokens AND CSS classes to provide more theme-friendly styles (and CSS custom property fallbacks mean it's still possible to provide a baseline for classic themes)
  3. theme authors to remain creative with their designs will still faithfully respecting and interpreting user block settings

Happily, I don't think that these goals are at odds with the concepts behind FSE or what developers are trying to accomplish. There is a huge world where smart people have thought a lot about creating front-end design systems of design tokens and standardized markup that can then be consumed and safely modified by others. I feel pretty strongly that WordPress would be very smart to embrace this component-driven frontend framework approach in order to both streamline consistent internal development AND allow themes and plugins to safely and 🌟 creatively 🎨 build beautiful, unique websites.

@aurooba
Copy link
Member

aurooba commented Feb 12, 2022

Design Tokens: I think theme.json needs to be viewed as a design token system. It is for saving design-related values (including what parts of the design are user editable) that the WordPress backend, WordPress frontend, and theme can all share. There is a huge opportunity to further standardize these token names (font sizes and colors, obviously, but also gap sizing and widths and responsive breakpoints!) so that themes become more interoperable. @richtabor had some popular posts with proposals around font sizes and colors that lay out why this would be so valuable.

This exactly what I thought theme.json would be. I haven't been working themes as much recently, but theme authoring is very much a part of my work in general, and seeing the kinds of bugs and issues that are coming up as more active theme authors are reporting them is greatly concerning to me. @mrwweb has done a great job expressing concepts that many people will agree with.

@patric-boehner
Copy link
Contributor

I don't have much to add but I'm in agreement with @Luehrsen and @mrwweb. The lack of a consistent and easy-to-understand baseline for the classes and naming makes working with and writing CSS for the block editor a frustrating experience.

@luisherranz
Copy link
Member

I don't have much to add either at this moment, but I started a couple of related discussions a few months ago to try to understand what are the new theme and block responsibilities and what does the block-theme contract look like:

@fwazeter
Copy link
Member

fwazeter commented Feb 15, 2022

I posted this over on #35376 but figured this would be good to repost on - since I discovered it from that issue.

I've been tinkering with this quite a lot and it certainly gets pretty complex fast. (Note, none of this is meant as critical, just observation and trials-and-tribulations from the trenches...Gutenberg definitely is like it was once described as "trying to replace a jet engine while the plane is in flight."

Part of the issue is that while most plugin or theme developers won't care as deeply to what's happening under the hood with backend processes (except to adapt to how things are done or hook into something, etc), CSS ends up being a whole different ballpark because of the impact on the visual front end - and as someone who runs an agency, CSS is almost always the area where the most time is spent/lost. Worse, it's also by far the most opinionated (or at least vocally opinionated) because it's the area someone's most likely to notice.

For example - FSE radically sped up our dev process (been building them in production since 5.8) for the average small business site in terms of setup, migrating features from one to the next and so on.

That said it's a chronic fight with CSS on a scale not seen before in WP - a strength of a classic theme is that, well, you can just dequeue everything and load up whatever you want.

That simply isn't possible with blocks - or more specifically - with theme.json (which is something that's great ), since that has to be a dynamically generated stylesheet. This means that opinionated styling is the default, because, well, it has to be in this iteration.

The Problem

Let's evaluate a seemingly simple problem. CSS works best when it's leveraged to it's full inheritance properties - setting smart, global defaults that are only overridden for specific, actual, exceptions to the global standard.

Simple Problem 1: On mobile, a paragraph or heading block on it's own within a container without a background by default ends up flush against the side of the device screen.

Easy Solution: Make the the global default box-sizing: border-box & direct child of the main content box section default to content-box model.


/* because everything in CSS is a box, just make border-box the global default */
* {
box-sizing: border-box;
}

/* main, or entry-content or whatever hook you want to use for the_content */
main > * {
box-sizing: content-box;
padding-right: var(--wp--style--block-gap);
padding-left: var(--wp--style--block-gap);
}

Now, the content will align perfectly on a screen size larger than contentSize or wideSize and on fullwidth, as originally intended, but on smaller screen sizes won't be flush against the size of the device.

Here's the problem: wp-block-group, column, etc all explicitly state to be border-box...so now I've got to override those styles by either dequeuing them and loading my own styles or overriding their CSS, and anything else that explicitly says border-box, when it wasn't necessary with a global default like box-sizing: border-box.

But hey, that's easy enough to override - we can override the block styles, so we'll just dequeue them and enqueue what we want after reading through every style and eliminating what we don't need and re-enqueuing a new style. It's a PITA the first time, but once we got it, we got it mostly, and then have to keep up with more internal changes with core...or we could completely forego core blocks.

But then, it very quickly gets more and more complex.

But, let's go to the next problem - okay, my page load speeds are pretty awesome with FSE, so I don't really need to worry too much about dynamic .wp-container-uuid, even though it's a pain to read through to diagnose CSS, it's functional. But, now I want to make it so my theme doesn't have to account for different reading modes by writing new CSS - which is solved with single line logical properties instead of margin-right / left etc, we can use margin-inline-start / margin-inline-end etc and the layout will automatically change based on the user's reading mode preference. Awesome! I can keep the integrity of my design, be internationalized by default, and not write anymore code.

Now we have to rewrite the Layout Support part of Block Support API to fix that...

Except now I can't because Layout Support ties me to being margin-right / margin-left...and to overwrite it, I have to rewrite the whole Layout Support section of the Block Support API. Now I've got to maintain a fix that core could override or change at any time, or I'll have to adjust to account for new features.

Then, there's the whole tied into global core colors and such, which is livable, but annoying to read through during development and well, would be great if it could just be opt-out gone - the reason it's global and not overridable is for block patterns, but it feels like a relatively simple version of an if loop could just be attached to the render_block hook to pull the global style into the common global CSS style sheet if the property is used.

Plus, then that brings the thought - so great, we made global colors and gradients non-opt out for custom props, so, why not make a custom prop for contentSize and wideSize and simply change that value on a one off tag (or call via an id property) when a user input is put in place?

Then, on top of that, half of the Block Support API registers values from theme.json one way (e.g. apply) and the other half uses render - presumably because a custom contentSize / wideSize can't be inherited using the owl selector if it's an inline style.

Effectively, four different sources of truth for how the CSS is generated and where it comes from.

So we've now got four different ways CSS is rendered without getting into anything super complicated - there's the core styles that get output inevitably through script-loader, inline styles via Layout Support and Duotone support, the individual blocks themselves, and whatever other CSS is left-over from older enqueues (e.g. wp-emoji - although, being dequeueable that's not such a big deal).

This isn't even including something like - colors - in the block editor which all default to HEX overrides - and not in a way that enables opacity (e.g. via 8 digit hex). But because there's no singular area where CSS is resolved, the easy solution of simply having a JS or PHP script that powers the color wheel and converts the values to whatever the custom property set it as or let the end user set whatever color code they want to use and have them render that way - which would enable things like opacity to work out of the box (e.g. avoiding the cover block opacity thing that has to use a filter to override the color) - and be easy enough to say, hey, RGB to RGBA, Hex to 8 digit hex, HSL to HSLA, etc.

If I remember right, I think the customizer even has something like that for it's color wheel!

CSS is complex - what's needed is a CSS API.

A centralized CSS API that parses CSS from various sources and generates it in one spot would simplify the development process of further features, streamline how the CSS is created and where it's output, and enable a singular area for hooks to be generated so developers could hook into what they want and manipulate values or replace them as they need to without messing with the core interface.

Here's the solution I've been building independently for my agency within a plugin for our internal use so far.

  1. a CSS parsing class takes data from different sources (e.g. block attr's, theme.json, from custom post type)

  2. The parser output is universalized into a single data standard dividing it into declaration blocks and declaration prop-values

  3. A CSS generator class compiles the values into the appropriate stylesheet(s) wanted. A copy of this is saved as a CPT.

  4. The output is registered as an inline stylesheet as the default.

  5. The Block Support mechanism (mostly just Layout Support) assigns the class if no block attr for layout/content size is set.

  6. If a custom value is saved by the user, it saves the new value in a CPT and adds it to render when that property is used - if a second block uses the same value, it doesn't create a new class, and uses the already generated class. Using custom props for things like contentSize and wideSize means we don't have to alter the original - we just change the value of the custom prop for that specific new css class.

We save different copies of the parsed data in a custom post type - so that if a user wanted to change what the default output is, say change a property from margin-right to margin-inline-end, they could simply change one value and it goes out - though this probably isn't something core would really need to care about - but I think giving a plugin or theme author the ability to hook into this mechanism would be widely applauded. In our case we're just using the CPT as a data store that can be easily edited / referenced once the CSS is already parsed.

CSS is complex enough that I feel that a class / API that powers parsing and creating declaration blocks and assigning them to stylesheets would radically simplify the development of the block editor - and even provide a framework for blocks themselves to radically simplify the amount of CSS they have to render for options, while giving plugin & theme authors a way to change those values if they so desired, without taking away the power of choice from the user.

The bottom line is - no theme or plugin author should have to completely overwrite a core API to change how a couple of lines of CSS are generated.

@ramonjd
Copy link
Member

ramonjd commented Feb 15, 2022

So many excellent ideas in this thread 👍

But, now I want to make it so my theme doesn't have to account for different reading modes by writing new CSS - which is solved with single line logical properties instead of margin-right / left etc, we can use margin-inline-start / margin-inline-end etc and the layout will automatically change based on the user's reading mode preference. Awesome!

This is something we could and probably should look at to ensure margins and padding behave across writing modes. I've started looking at alternate writing modes. If it gets any traction switching to logical properties might have to happen anyway.

Anyhoo, here's a draft PR that experiments with switching the layout margins to CSS logical properties:

#38816

😄

A centralized CSS API that parses CSS from various sources and generates it in one spot would simplify the development process of further features, streamline how the CSS is created

It'd be fab to capture some of these ideas over at Tracking: Add a Style Engine to manage rendering block styles.

The scope is fairly narrow so far, but it's still early days, but ideas, feedback and discussion at this point would be highly valuable. Particularly the experiences surrounding the CSS API implementation outlined above.

🍺 Cheers!

@fwazeter
Copy link
Member

fwazeter commented Feb 15, 2022

@ramonjd Even if it never "catches" on, it's a smart, sensible default, we've been using it without issue for almost a year now - for one, the semantics follow flex & grid semantics, which you pretty much have to be accustomed with in modern CSS anyway, two if a user / author really doesn't like it explicit margin-right / left overrides it (although, that also might be faulty memory of mine in a messed up inheritance tree) tested this again, like all css whichever is declared later overrides (it was indeed a messed up inheritance tree that made me recall that!), three the caniuse for inline-start/inline-end is basically everything except IE 11, (shorthand props at ~90%, just missing some opera mobile support mostly), and well, four who wouldn't want to eliminate an entire need for a new stylesheet to have internationalization by default? Months ago I submitted a trac issue to add the logical properties to safe-style attr's, but forgot to check if it was ever put in, since I get lost on trac.

RE: CSS API

I could probably convert the API I have right now to a more WordPress coding standard style if that'll help move the needle in a PR, since I've already got the bulk of the work hammered out in a scenario that works on top of Gutenberg / WP Core. I just tend to write smaller classes that use interfaces for dependencies and are a bit more component-sized to be easier to hot swap in my own coding.

A more finely tuned core-integrated version would de-couple the CSS logic from WP_Theme_JSON and related classes (which I haven't gone to that length, since overall the Theme JSON API is great, and decoupling it altogether in a 3rd party plugin requires a massive amount of re-write of a lot of related classes.

But, under the hood, I rewrote the old PEAR PHP package for parsing CSS from a file / html / etc and paired it with a 'fromAPI' version that took the data from wp_get_global_stylesheet() etc.

There might be a cleaner solution than using a CPT as a data store, but I figured to follow the pattern from similar use cases (like block templates, navigation block, etc).

@cbirdsong
Copy link

cbirdsong commented Feb 21, 2022

Major agreement with @mrwweb and @Luehrsen. I also want to chime in on this bit, which gets at a pain point for me:

The beauty of switching themes is that the content stays the same but the design (aka "theme"!) is different. People specifically switch themes so that their sites look different.

If there are standardized classes and design tokens (more than that in a moment), then themes can faithfully reinterpret user choices, letting them shift their content cohesively from one design system to another.

If this is the goal it is massively undermined anytime the editor outputs inline style values, especially when it's the only option to adjust something. To avoid de facto lock-in, there needs to be a level of abstraction between what the user can edit and what comes out on the front end, and Gutenberg already found a decent solution: presets.

Themes registering a range of font sizes and color/gradient values has already proven to be a reasonably1 successful balance, providing a structure for a theme to use to ensure design consistency while reducing cognitive overhead for content editors.

Three existing problems that could be solved by presets:

Spacing, Margins and Padding

Theme designs inherently have different default spacing values, and consequently, any custom spacing value that looks good on one theme could be cramped on another. A user might increase the padding on a column block or decrease the spacing on a buttons block based on the default in their theme, but once those choices are moved into the next theme they're likely no longer going to fit. Similarly, block patterns might include a hard-coded padding size that doesn't fit in with the theme for the same reason.

Additionally, fully custom values are fixed and can't change for different screen sizes. The user almost certainly doesn't want a block's padding to be 75px on a 375px wide phone display, but they probably won't think about that when typing "75px" and seeing it look pretty good on their desktop display.

A standardized set of presets ("small", "medium", "large", etc) would allow a user to tweak these values while sidestepping all of these issues. I previously proposed this solution for spacing in an issue last year:

Font Weights

5.9 added the "Appearance" (font weight) setting, which has options for every weight going from 100 to 900 and outputs that value as an inline font-weight: whatever. On every theme I've implemented most of the options in this control straight up don't work, as the theme only includes the 2-3 font weights required by the design and loading all the weights would be a huge site performance problem.

Even discounting that, the lack of abstraction inherently poses a problem since one theme's "bold" weight might be font-weight: 600, while another's is 800 (or even a random value like 527, in the case of using variable fonts). A user that set a secondary heading to a weight of 600 might find it is now heavier than their content's primary headings after switching to a theme with a lighter heading font. This also poses a problem for block patterns, which might include a hard-coded font weight far out of step with the theme they're being dropped into.

A standard abstracted set of font weights like "light", "normal", "semibold", "bold", etc. would allow content to smoothly transition between themes and typefaces, as well as allowing theme authors to add more options without filling the user's content with hard-coded font-weight values.

Column Sizing

One important aspect of modern CSS is the fact, that we do not only have classes to describe state, but also CSS variables. So for example setting --wp--has--width: 12% on a core/column block would still allow the project to have explicitly set defaults, but at the same time allow themers some more freedoms of choice with how we interpret the state.

I have been using block filters to accomplish this on my recent themes, and it makes it much easier to manage the layout of columns/media & text blocks in various contexts while still allowing users to set a custom width.

However, presets would be greatly preferable to requiring users to enter arbitrary percentages. A grid system-style set of width presets (50%, 33%, 25%, 20%, 16%) would cover most use cases and could also include intrinsic options like "max-content" or "auto", which is a much better way to think about layout on the web than fixed percentages.


In my opinion, any option that results in an inline style value being injected into the page should have a set of presets presented to the user before allowing them to set a custom value, just like font sizes and colors. Themes should also be able to easily opt out of using any custom values even if they already exist in the content, which is not currently possible with custom font sizes and colors.

I would love to know why the Gutenberg team has gone the opposite direction and moved away from using presets in favor of asking users to enter arbitrary values using units they might not understand and requiring theme developers to deal with the resulting inline styles, especially considering the many issues complaining about it:

Footnotes

  1. Though not entirely. Colors could really use a standardized abstraction layer.

@mrwweb
Copy link

mrwweb commented Feb 22, 2022

I just published a more detailed proposal for trying to address this issue while meeting some other related needs. #38998 is the corresponding issue for the blog post.

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. Developer Experience Ideas about improving block and theme developer experience [Feature] Themes Questions or issues with incorporating or styling blocks in a theme. Global Styles Anything related to the broader Global Styles efforts, including Styles Engine and theme.json [Type] Discussion For issues that are high-level and not yet ready to implement.
Projects
None yet
Development

No branches or pull requests