The Case for a Shared CSS Toolkit in WordPress

Earlier today, Mark Root-Wiley published an in-depth proposal around standardized design tokens and CSS for WordPress. The goal is to create a consistent, customizable, and interoperable system around the design tools in core. Essentially, he is proposing a standardized design framework or, as he refers to it, a “shared CSS toolkit” that WordPress, themes, and plugins can rely on.

The blog post clocks in at nearly 4,000 words. He also added a shorter version of the proposal via a Gutenberg GitHub ticket. However, the post expands on the idea, linking to resources that span a few years.

I responded to Root-Wiley via email. This was a subject near and dear to me. It has also been a source of frustration from other theme authors I have had the privilege of talking to over the last few years. These are themers who have been 100% behind the block system since Day 1, not the random guy in the back shouting, “Gutenberg sucks!”

The primary thought I shared was that there has been a bit of fatigue on the topic. There is a push to bring standard presets to core every so often. But, it always feels like the wheels are spinning in the mud until everyone gets out of the car when they realize it’s not moving.

Root-Wiley pointed to my 2019 post, Themes of the Future: A Design Framework and a Master Theme, as a common ancestor to his deep dive into the bowels of this issue. But, others and I have been talking about it even before the launch of the block editor in WordPress 5.0.

In part, this is because we were excited about the potential of more standardization. WordPress could finally correct some of its longstanding issues and usher in a utopian era of theme creation based on well-designed conventions.

WordPress 5.0 rolled out theme-support flags for custom font sizes and a color palette. The features in and of themselves were a welcome first step, but they did not go far enough. WordPress should have leaped ahead and set standards from the outset.

Instead, we got a mish-mash of default font size and color names with no guidelines on what they meant. How huge is the “huge” font size? What if I need to follow that naming scheme and need something larger? What should I name it? (For a potentially educational tangent on size names, see my notes at the end of this post.)

I still cringe every time I see classes like .has-luminous-vivid-orange-background-color.

However, I will not continue bashing the mistakes of the platform’s past. It is time to look forward. Root-Wiley notes in his post:

I would like to propose a path toward standardizing how CSS for WordPress designs and layouts are created so they are more transparent, efficient, and customizable. Not only can this approach simplify core styles, it would address a number of long-term WordPress pain points that predate even the block editor’s release in WordPress 5.0.

I want to see presets for everything users can select via the block design tools. For example, instead of setting absolute units for margins, they can choose predefined sizes from WordPress and/or their theme. However, there should be standards for naming these presets.

Why is this so important? Imagine setting a top margin of 20px on a block in some blog post. It looks good and matches your current theme, and you repeat this process dozens or more times on various elements. Then, you change designs down the road. This could be a full theme switch or a change via the global styles system. This new design implements a different vertical spacing system. 24px might make more sense than the 20px littered throughout the site.

The old setting would be tied to a global value in an ideal world, not the block. This would allow it to match whatever design system is in place.

Margins are just one piece of a much larger puzzle. And, presets for the various design tools do not even cover everything in Root-Wiley’s proposal. That is why I encourage all theme and plugin authors to review it.

There are a few items I disagree with in the proposal. However, those involve the low-level implementation work, not the concept of creating a standardized system. I had planned to discuss those in detail, but doing so would get into what a former team member I worked with called “weed discussions.” They get in the way of the big picture.

If there is one thing Root-Wiley and I agree on, it is that big picture of creating a CSS toolkit to carry WordPress into the future.

A Never-Before-Published List of Sizes

This is a bit of a side tangent, but I did do a ton of research on size names following the WordPress font-size model. And, because I will likely never have a reason to publish my findings elsewhere, I might as well post them here.

If you were ever wondering what specific sizes are bigger or smaller than others (e.g., Colossal vs. Titanic), I present to you a somewhat-educated-but-may-not-be-100%-correct list:

  • Diminutive (2XS)
  • Tiny (XS)
  • Small
  • Normal (Medium, Regular, Base)
  • Large
  • Extra Large (XL)
  • Huge (2XL)
  • Gargantuan (3XL)
  • Colossal (4XL)
  • Titanic (5XL)
  • Olympic (6XL)
  • Planetary (7XL)
  • Galactic (8XL)
  • Universal (9XL)

That is likely not an exhaustive list, but I spent several weeks looking up and comparing definitions and resources. I added a few alternatives in the mix for reference.

I also wanted to post this to show how naming things can break the user experience. The average user should not have to think about which sizes are the biggest or smallest. A naming system like this is a recipe for confusion. Even if the user experience works, the code-based slugs should not confuse developers.

This same rule applies to colors and all other presets. Naming things is hard, but it is even tougher when you have already made a mess and need to fix it later. It starts at the foundation, especially when everything added today will be a part of the legacy code set for years to come.

23 responses to “The Case for a Shared CSS Toolkit in WordPress”

  1. For goodness sake already…can’t we just have a universal framework for CSS like Bootstrap and stop all this fuss? It’s been 16 years already and WordPress continues to go in circles over something that has been proven elsewhere to be solved by using a standard set of CSS as the starting point so everyone isn’pt “reinventing the wheel” and causing collisions with their neighbors.

    • No, Bootstrap is too intrusive with its negative margins and other crap. It’s a pain to override its CSS and make it right.

    • This would be a far lighter touch than Bootstrap. It’s much closer to a shared set of design tokens than a shared CSS framework. Theme/plugin authors would be free to use these if they’re a good fit or ignore them if they need to use something custom.

      • Yes… you had me at “hello”…
        I’ve been shouting from the hills for months now that WP needs to get on board with streamlining a unified framework for many things, not the least of which is CSS ;-)

        I’ve talked about this with Brian Gardner (working now on Frost..as a similar mindset/approach) and he too sees the value in us all getting together (for once) instead of the current approach of everyone doing their own thing.

        Sign me up!
        spence

      • Just want to echo what @cbirdsong says here: This proposal is for the absolute possible light weight system that can provide theme values to Core and 3rd parties without dictating how people choose to build their front ends. It’s more than just design tokens, but it would not provide sufficient CSS/tools to build a totally custom theme.

        Building consensus around a proposal like this is difficult, so it should seek to be as minimal as possible but sufficient to enable us to make content more portable between themes and more interoperable with plugins and themes.

  2. Thank you for supplying the tangent on font sizes. I’ve been just searching for a recommended standard for size naming conventions over the past few days and was happy to see this referenced in this post.

    I can already see that referencing font size names like “Gargantuan,” and “Colossal” let alone “Titanic,” “Olympic,” “Planetary,” etc. with clients will sound fairly amateurish while also still not providing a clear hierarchy of sizes. This will only be increased when building for a non-English-speaking (or English as a primary language) audience.

    In looking through comments like https://github.com/WordPress/gutenberg/issues/29568#issuecomment-913153681, do you see a problem in using an approach like overclokk’s:

    --wp--preset--font-size--base // where m size could be the base font
    --wp--preset--font-size--xxs
    --wp--preset--font-size--xs
    --wp--preset--font-size--s
    --wp--preset--font-size--m
    --wp--preset--font-size--l
    --wp--preset--font-size--xl
    --wp--preset--font-size--xxl
    • I actually use a similar approach for font sizes:

      --wp--preset--font-size--xs
      --wp--preset--font-size--sm
      --wp--preset--font-size--base
      --wp--preset--font-size--lg
      --wp--preset--font-size--xl
      --wp--preset--font-size--2-xl
      --wp--preset--font-size--3-xl
      ...
      

      For things that have a sort of base/middle/medium size, I much prefer this type of sizing system.

      I also prefer 2-xl (note: WP auto-hyphens this) over xxl because multiple x characters become harder to read for developers.

      • That’s awesome. As I was re-reading my comment, I was thinking the exact same thing – to use something like 2-xl, etc. when adding larger text options and something like 2-xs, etc. when adding smaller text options.

        The primary point is that this type of approach allows us to establish a universal base of standard sizes AND provide a semantic & seemingly limitless extension to those sizes as needed.

        For, you know, those clients that want some 8-xs legal copy. ;)

  3. Can we stop using xs, md, xl, 2xl or xxl etc. for sizes already? It’s always hard to remember which of these represent what value so as a developer you always have to go and check, especially if you switch between multiple projects. Why not just use numeric values? We can all count (I guess? :D)

    For example, I would go with “font-size-1”, “font-size-2” etc. where the number represents a multiplier. So if you have a 4px base value, font-size-1 = 4px, font-size-2 = 8px etc. Might be weird to use font-size of 4px for anything on page, but it’s just an example. And you can go to font-size-100 this way if you wish and you still know what each value represents. There is less confusion and no need to name these values things like “Gargantuan” or “Galactic” or 9XL.

    I’ve started using this multiplier based approach for consistent spacing (padding/margin) values instead of using xs, md etc. and I’m never looking back. It has been so refreshing to work with those instead of having to always go check what does “xs/sm/md” represent. Haven’t been using it for font-sizes since I haven’t required it, but I can see it working for this case as well.

    P.S. If using JavaScript objects for some of these definitions (styled-components or whatever other setup you might have) if might be weird to specify property name as “1” because then you have to access it like myObject[1] instead of myObject.1. In that case property name can be $1 so it can be accessed like myObject.$1.

    • Agree. Using a numeric system is easier to remember. Things like margin-1, margin-2 is better than margin-md, margin-xl. md, xl, 2xl seems to be fine for font sizes, but applying it to other aspects is not ideal. A numeric system can be used in all cases.

    • The reason many of us prefer the “T-shirt size” model for font sizes is that it allows you to scale in either direction while maintaining semantic names. You can always continue appending *-xs or *-xl for smaller or larger sizes. Font sizes extend outward from a base/medium number rather than starting from 0.

      For spacing, I use the same approach of a stepped (multiplier) naming system. That makes far more sense, which start from 0.

      --base: 0.25rem;
      
      --margin-1: calc( 1 * var( --base ) );
      --margin-2: calc( 2 * var( --base ) );
      
      --padding-1: calc( 1 * var( --base ) );
      ...
      
      --gap-1: calc( 1 * var( --base ) );
      ...
      
      • This raises a few interesting aspects of the proposal that I think are still unsettled:

        1) Does there need to be individual margin/padding/gap values or could a single scale of spacing units work?
        2) What’s the right number of values on a spacing scale(s) that all themes should try to support and how do themes support more than that number?

        I think the pros for t-shirt sizing and numeric scales are both very compelling. I’d love to figure out a way to keep the numeric scales in some way but support indefinite ranges while keeping things interoperable/portable.

        The most obvious way is to use 0 (zero) as default and then work out in both directions. The downsides to that are that negative positions on the scale wouldn’t necessarily correspond to negative values and class naming is weird because CSS classes use so many hyphens (which are also the negative/minus symbol).

        I’ve put together this demo of a way to support a scale of values where only a few are required but themes could offer up to a set maximum. For a spacing scale, I could imagine 5 required values with up to 11 available. I think it’s pretty cool and it makes me even more excited about the possibilities!

        • You have gotten me on a bit of a rant, and much of this is just me “thinking out loud.” It’s a tough problem to solve. Sorry for the wall of text.

          If you figure out a way to make the class and property names not be awful with negative values and hyphens, it’d be less of an issue. However, I must admit that seeing something like -3 for a font size feels confusing to me in comparison to 2-xs.

          I also think this method would be confusing when comparing it to other scales. Padding, margin, and gap scales starting at 0 literally mean 0 (or, they should in my mind).

          The alternative of just starting a 0 and going up also feels odd because, you know, when do you ever need font sizes on the lower end of that range? (Actually, I know a few use cases for font-size: 0, but those are one-offs.)

          1) Does there need to be individual margin/padding/gap values or could a single scale of spacing units work?

          I would build it as a single scale. Maybe some folks work differently, but I couldn’t imagine splitting these up in my work. Of course, I always favor allowing for devs to extend this however they want.

          2) What’s the right number of values on a spacing scale(s) that all themes should try to support and how do themes support more than that number?

          That is a tough question to answer without folks just stepping up and saying, “Here’s what I do.” So, here’s the actual spacing used in my last project. However, I have went higher. Admittedly, I have relied on the Spacer block for larger spacing because I can overrule it for smaller screen sizes.

          You might notice that I start skipping numbers after a bit because I find those “in-between” points less and less useful as the scale goes up. They are great for the small spacing, but usually not so much when growing.

          Longer term, I plan on mixing in minmax() to make the larger values a bit more responsive (probably starting at 12):

          "base": {
                  "spacing": "0.25rem"
          },
          "spacing": {
                  "0": "0",
                  "1": "calc( var( --wp--custom--base--spacing ) * 1 )",
                  "2": "calc( var( --wp--custom--base--spacing ) * 2 )",
                  "3": "calc( var( --wp--custom--base--spacing ) * 3 )",
                  "4": "calc( var( --wp--custom--base--spacing ) * 4 )",
                  "5": "calc( var( --wp--custom--base--spacing ) * 5 )",
                  "6": "calc( var( --wp--custom--base--spacing ) * 6 )",
                  "8": "calc( var( --wp--custom--base--spacing ) * 8 )",
                  "12": "calc( var( --wp--custom--base--spacing ) * 12 )",
                  "16": "calc( var( --wp--custom--base--spacing ) * 16 )",
                  "global": "calc( var( --wp--custom--base--spacing ) * 8 )",
                  "px": "1px"
          }
          

          I add a specific global value there so that I can easily change that in one spot. And, I add in a px option for some edge cases where I just need a 1px.


          At the other end of all this, even if we all agree to some standard naming system, there is potential for monumental differences between implementations. For example, imagine my theme defining --wp--preset--margin-1 to 0.25rem and another theme defining that as 2rem with an ever-increasing scale. It could get out of hand when switching themes.

          So, even with a naming system in place, it does not quite go far enough. An agreed-upon implementation would be even tougher. That’s one of the key reasons I wanted WordPress to have a full CSS framework of its own. It would define that standard implementation. Crazy deviations from it would be on the shoulders of the theme author.

          • I certainly can’t argue that the classes in that demo are rough. Maybe a t-shirt scale is the answer after all. I’d love to hear other ideas and see what other systems do. That’s an area where I’ve done some research but not a ton, and it’s hard to find systems that are exactly like what I’m proposing (which is only a starting point in itself).

            You might notice that I start skipping numbers after a bit because I find those “in-between” points less and less useful as the scale goes up.

            At the other end of all this, even if we all agree to some standard naming system, there is potential for monumental differences between implementations. For example, imagine my theme defining –wp–preset–margin-1 to 0.25rem and another theme defining that as 2rem with an ever-increasing scale. It could get out of hand when switching themes.

            I think having a contiguous scale with no gaps is key. There shouldn’t be any implied connection between the position on the scale and the actual value. I actually have no problem with your example there so long as margin-1 is consistently understood to occupy the same relative position on a scale.

            A final thought I have that’s relevant here though (and gets to the questions around standardizing) is that I think the wider the scales and the greater the number of standardized values, the more disagreement there will be between themes, the “farther from center” things get. If a primary color is maintained from theme to theme, that’s super valuable. If a quaternary color is maintained, that’s probably less valuable since many themes may not even have one colors further down in a brand guide are often more specific and unique in how their use is intended. think the same goes for transferring a 5-point scale vs a 13-point scale. I think as long as there’s a system that lets theme’s use their 13-point spacing scale in their CSS but maybe only provides 5 or 7 options through the UI, that seems both like a likelier path to success and an easier set of things to agree on.

            • Just a quick note to say that I updated the demo to return to use the classses padding 1padding 7 and added an example (scale 5) that shows how a theme could use the system to certain padding levels while still not losing the user intent.

  4. The right way to “standardize CSS for WordPress layouts” is to move the platform toward more formal and uniform adoption of CSS Grid. The layout problems in legacy wordpress are not the fault of WordPress – they stem from all the bandaids and patches added over the years since the days of Netscape Navigator to get browsers to show content in a usable way. CSS Grid is the elegant, well-thought-out solution to all that. It’s the way of the future.

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Newsletter

Subscribe Via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

%d bloggers like this: