WordPress / gutenberg

The Block Editor project for WordPress and beyond. Plugin is available from the official repository.
https://wordpress.org/gutenberg/
Other
10.16k stars 4.05k forks source link

Default Colors, Theme Colors, and Custom Colors #29568

Open mtias opened 3 years ago

mtias commented 3 years ago

What is the problem?

Color handling in Gutenberg comes in two forms: colors picked from a palette and custom colors. Core provides a default color palette which can be overwritten by a theme. Colors assigned to a palette are expressed through classes. The same model applies to gradients. This is issue is not about the technical aspects of when to classes, inline styles, variables, etc, are employed but about the user expectations and theme integration.

At the moment, it’s frustrating as a user that upon switching to a theme that overwrites the default color palette you lose access to the rainbow-color set that comes with core. The core palette aims to provide quick access to distinct hues reliably. A theme palette generally aims to define a restricted set of semantic colors for branding.

The heart of the issue is the conflict that arises since colors are not always used semantically but also for individual expression. A theme might have added a color palette with just two colors — a green and a black — to define its aesthetics. Now, if a user is interacting with a pattern that contains an image with a rural landscape and the green color is picked because it matches the tone of the image, that use is not semantic in the sense the user wouldn’t expect it to change if they switch themes. Gradients are even more pronounced given there’s no sense of “primary”, “secondary”, not even distinct color names and they can be a lot more decorative (the theme Seedlet is a good example, with gradients that work more as background patterns). Assembling a gradient from scratch is also more laborious.

This distinction between semantic colors and local colors has implications for theme switching, global styles, etc. So we need to expand the handling of colors.

Another problem is tying user customization to globally used colors. Right now a custom color can only be replicated by remembering and replicating its color code. There should be an easier way to transfer a local color choice into the shared palette.

Finally we have the situation of patterns, which need to set inline colors right now to ensure they work as expected. This shouldn’t be needed if the pattern wants to use a color from the default color palette.

Proposal

Separate the core palette from the theme palette

A first step is to make the theme color palette something that works in addition to the default palette. That would allow themes to register preferred colors without necessarily overwriting the default palette. Of course, it still needs to be possible to fully disable the default palette since sites that have stricter branding guidelines might prefer to remove it entirely, the same way the custom colors interface can be disabled, but it should not be the default behaviour that a theme palette overwrites the color palette.

image

Treat theme colors semantically

The other part is treating theme colors as colors that should change upon a theme switch. This is obvious for the global styles context, where headings or link colors set to a theme color should change when switching themes. But it can also be extended to theme colors employed locally.

There is always going to be some uncertainty in determining what the intention is when applying a local color, but by having a more clearly defined “Theme” group we can set a better expectation than what is currently the case — if I apply a theme color rather than a color from the spectrum to a button block, it’s easier to expect it to change upon theme switching.

The approach of having theme colors more clearly presented in the UI, in addition to the default color-spectrum, will allow us to finally tackle a big part of the conundrum outlined in #7553. Theme colors (of the primary and secondary kind) will be expected to map to the same variables on the next theme while dark-red and light-blue are consistently provided by core but could still be tweaked within their hue range in a still predictable way (for example, we might update the default color palette with a "vibrant" or "muted" variant of the same color-coded names).

Extending the default palette

The default palette should be user customizable (as it is now in Global Styles), so a user can add, edit, or remove from it and sustain it through theme changes. That doesn't change. It's conceivable that the current colors in the default palette would need to be added, updated, or removed in the future. We should work with the assumption that we might add more default palettes in the future and that we should retain the current mappings indefinitely.

Bubble up local changes

Colors picked locally could automatically become part of the custom user palette so that the next time they want to pick the same color it's present there. A user should be able to remove a custom color at any time so that the custom palette doesn’t grow indefinitely if you use many custom colors locally. A tricky implementation detail is how to go from inline disposable color to a class-based one for this reuse, but this also helps address that problem by making it more obvious that adding a color (at least in certain contexts) automatically creates a class mapping for it.

Integration with patterns

By ensuring the default colors are present through their class mappings patterns can reliably work with them even in cases where they might not figure out in the UI for whatever reason. This is important to support a wide range of patterns and limit the need to resort to inline styles for effects.

aristath commented 3 years ago

Implementing multiple palettes as described above would go a long way and improve things both for end-users and developers. The only thing I would like to add to the above proposal is that ideally we'd also have some sort of universal naming convention for theme-defined colors. This way the "primary" color will most likely be named primary and not mytheme-primary-dark, sothings won't break when switching themes.

pbking commented 3 years ago

Reading the above I imagine:

Gutenberg by default will provide a given set of styles. "Semantic" styles. These are the agreed-upon colors that will always be provided. Themes depend on it, patterns depend on it, blocks depend on it.

--wp--preset--colors--primary is always something we can depend on. This is what you mean by "core palette".

A theme can use that variable to style blocks. "Primary goes in this color, foreground goes in that color" A theme can set those variables. Maybe even from colors in the palette it provides. "Primary = 'golden pond'"

A user can set that value to whatever they want. When they do change that value it sticks between themes. If they change any value of the primary, etc set that it's locked in. That's their global palette. If they reset the global styles then that palette goes to whatever the theme expressed or whatever Gutenberg defaults it to if the theme doesn't express anything.

Templates and blocks can use those variables and styles in their templating. ".has-primary-color" will always be available what you (and the user) think it is.

mtias commented 3 years ago

@nosolosw one of the quick steps I imagine here would be to introduce a new defaultColorPalette = true property in theme.json, which themes can disable if they don't want default colors at all.

oandregal commented 3 years ago

one of the quick steps I imagine here would be to introduce a new defaultColorPalette = true property in theme.json, which themes can disable if they don't want default colors at all.

Thinking on UI: what do you think would be a good first step to match that change? Do we need to create separated palettes in the UI or can we start by having a long list of colors with what we have today (sorted: first core, then theme)?

The default palette should be user customizable (as it is now in Global Styles), so a user can add, edit, or remove from it and sustain it through theme changes. That doesn't change.

So, the user can change all palettes (core, theme, user). In terms of theme.json shape/keys, everything can remain the same, we just need to change behavior (don't overwrite palettes).

What are your thoughts on themes changing the color value of the color palette? For example, does it make sense that a theme can change the core yellow's value to a different sort of yellow? I'm thinking we don't need this to start, it seems to go against the spirit of this issue. If we wanted to do this, we could offer the option to only change the values but not the slug (so the generated classes still have the same names) or the UI name (so there's an incentive that themes that change the color don't do things like changing a yellow to a purple).

We should work with the assumption that we might add more default palettes in the future and that we should retain the current mappings indefinitely.

I'm thinking that we may want to cross that bridge when we get to it? Food for thought: depending on our needs, we could do different things such as allow multiple palettes per origin (multiple palettes for core, multiple for themes, etc), allow for having colors that aren't shown in the UI but still generate classes (deprecated colors, so to speak), etc.

mtias commented 3 years ago

Do we need to create separated palettes in the UI or can we start by having a long list of colors with what we have today (sorted: first core, then theme)?

Yes, listing one after the other is fine for now.

For example, does it make sense that a theme can change the core yellow's value to a different sort of yellow? I'm thinking we don't need this to start, it seems to go against the spirit of this issue.

Right, this is not planned to be changeable at first through themes. In the future we might unlock the values like you describe.

I'm thinking that we may want to cross that bridge when we get to it?

Agreed :)

oandregal commented 3 years ago

I've prepared a PR that could be a first step for this https://github.com/WordPress/gutenberg/pull/31669

dashkevych commented 3 years ago

one of the quick steps I imagine here would be to introduce a new defaultColorPalette = true property in theme.json, which themes can disable if they don't want default colors at all.

This is a great idea! I was recently looking for a solution on how to add additional colors to the default colors. I am happy to hear there will be a solution to it.

I am wondering, would it be possible to add additional colors via PHP in classic themes?

Will we be able to use, for example add_theme_support( 'editor-color-palette' ); to extend default colors?

youknowriad commented 3 years ago

Initial version of this landed, we have a couple follow-up PRs to address some related issues but for now, I'm removing this issue from the must-have board as the UI is not expected in 5.8.

colorful-tones commented 3 years ago

I love where this is going! I think having colors coming from core is ideal and gives a great baseline API for theme authors to work with.

Naming variables is never easy. Leveraging a baseline set of semantic variable names and then adding a layer of aliasing on top for theme authors to override is ideal (to me).

justintadlock commented 3 years ago

Splitting theme and core palettes:

Yes, absolutely, yes. This will be a good thing for the block directory since we would have standard names from core that are always available.

What I'd like to see is the ability for themers to disable the UI part of core colors though while still supporting them as part of the core CSS package. Freelancers/agencies might not want clients choosing something outside of the color scheme.

Semantic theme color palette naming:

I've been working on a solution for this in the last few weeks. Here's a theme.json look at the result: https://gist.github.com/justintadlock/0003b82a1fc753b8bae54fad5b8cfd55

It is a combination of a Tailwind-like "shade" system based on the feedback from several theme designers on what they need on the average project. There are 4 groups of colors: 1) always-available, 2) neutral, 3) primary, and 4) secondary.

The shading system goes from 100, 200...900 (lightest - darkest). Using this system gives us 30 colors in total, which may be complete and utter overkill for many. An easy way to cut back on that is to skip the even shades, going from 100, 300...900. That will cut it down to 18 in total.

I also think such a shading system could have applications as we consider dark mode down the line.

Group 1: Always Available

.wp--preset--color--transparent
.wp--preset--color--black
.wp--preset--color--white

Group 2: Neutral Color

These are often text, borders, backgrounds, etc. Usually your "grays".

.wp--preset--color--neutral-100
.wp--preset--color--neutral-200
.wp--preset--color--neutral-300
.wp--preset--color--neutral-400
.wp--preset--color--neutral-500
.wp--preset--color--neutral-600
.wp--preset--color--neutral-700
.wp--preset--color--neutral-800
.wp--preset--color--neutral-900

Group 3: Primary Color

This would be the primary/brand color used throughout the site. Links, buttons, etc.

.wp--preset--color--primary-100
.wp--preset--color--primary-200
.wp--preset--color--primary-300
.wp--preset--color--primary-400
.wp--preset--color--primary-500
.wp--preset--color--primary-600
.wp--preset--color--primary-700
.wp--preset--color--primary-800
.wp--preset--color--primary-900

Group 4: Secondary Color

Often unneeded, but this is for a secondary or accent color that is separate from the primary.

.wp--preset--color--secondary-100
.wp--preset--color--secondary-200
.wp--preset--color--secondary-300
.wp--preset--color--secondary-400
.wp--preset--color--secondary-500
.wp--preset--color--secondary-600
.wp--preset--color--secondary-700
.wp--preset--color--secondary-800
.wp--preset--color--secondary-900
colorful-tones commented 3 years ago

Instead of having all those -100 and -800 variants. I would rather maybe see a mechanism like a stepper, slider UI that can be controlled via API. So, if a purple exists but theme developer only wants to allow for certain steps (e.g. --200, --400, --900) then it would have just those increments on slider.

colorful-tones commented 3 years ago

Instead of having all those -100 and -800 variants. I would rather maybe see a mechanism like a stepper, slider UI that can be controlled via API. So, if a purple exists but theme developer only wants to allow for certain steps (e.g. --200, --400, --900) then it would have just those increments on slider.

Upon second thought, the existing color picker UI would still be more suitable for this, as opposed to input type="range". Surfacing the colors as visual color is always more ideal user experience 😄

colorful-tones commented 3 years ago

@justintadlock @kjellr and I discussed this in #themereview the other day.

I've come to appreciate @justintadlock approach and naming convention.

I think this lays a solid foundation for theme authors to work with. Standardizing on these variable names is critical to setting up a scaffolding for themes to operate, while allowing interoperability when users switch themes.

colorful-tones commented 3 years ago

I've also gone ahead and put this on the radar for #core-css weekly, as we're currently having ongoing discussions about CSS Custom Property naming conventions.

Recently we've been focused on @ryelle experimental work on WP Admin color schemes with Custom Properties. Here is our single source of truth in shared Google Doc: WordPress Core CSS custom property naming

richtabor commented 3 years ago

A couple thoughts after diving into colors lately:

I've been playing around with the Automattic theme.json supported themes and across a few other points. BlockBase, Seedlot Blocks, and Blank Canvas all have primary, secondary, background, and foreground colors added. Quadrat does not, but perhaps it will (or should).

1. Should we consider background and foreground also standard colors that should be accounted for in block themes?

If so, it would enable patterns to do flex a bit more creatively, if for example, they used a primary color for a background, and the site background color for the foreground/text — like this:

Screen Shot 2021-07-06 at 2 55 16 PM

Looks great — and can make for interesting styles. However... that only works if the primary color and background color are contrasting. In the case of BlockBase and Seedlet, the primary colors are dark, whereas the background color is white (high contrast). So naturally, swapping the two works. 🤨

2. So, should we account for light & dark colors?

Should we have --light or --dark appended to slugs to indicate a primary--dark or primary--light color? This way, a pattern could declare that it should have a dark background with light text (via the theme's color declarations) — instead of working some of the time?

And this wouldn't happen:

Screen Shot 2021-07-06 at 3 24 02 PM

3. And (or instead of #2) should we have baseline mono--light and mono--dark colors?

They don't have to be white/black but variations of the like.

These may be a lot to standardize, but if we're really trying to open up flexibility between themes/patterns/block styles, I think we need to lean in this direction.

🎨

leeshadle commented 3 years ago

How about a required minimum default palette for themes?

Like @richtabor, I've also been doing a deep dive into handling global colors in block-based themes, here are some findings:

Global Color handling in Elementor = Sensible Defaults + Flexibility

Elementor has done an excellent job as far as handling global colors by offering both sensible defaults and lots of flexibility. In Elementor, you can easily achieve a Tailwind-esque palette as @justintadlock is proposing as well as a more semantic approach like @pbking is referring too.

The default palette naming strategy in Elementor is Primary, Secondary, Text, and Accent. The palette labels can be changed but the underlying custom properties remain the same and can't be deleted: --e-global-color-primary, --e-global-color-secondary, --e-global-color-text, --e-global-color-accent

Screen Shot 2021-07-06 at 3 44 07 PM Screen Shot 2021-07-06 at 3 43 58 PM Screen Shot 2021-07-06 at 3 45 51 PM

Tailwind-esque & Semantic Global Colorl Color handling in Gutenberg

I've found myself testing both versions of these palettes in block-based themes and ultimately it comes down to the design and what colors I need.

In one site build I need multiple shades of a primary color (tailwind-esque variants), in another I need 4 distinctly different but semantically named colors:

Screen Shot 2021-07-06 at 3 52 07 PM

So far I've landed here as my default for block-based themes, which also echos @richtabor's light & dark palette slugs:

Screen Shot 2021-07-06 at 4 06 52 PM

Required minimum default palette for themes?

With all that being said, how about a required minimum default palette for themes that uses a standard naming convention?

karmatosed commented 3 years ago

I do like the idea of cornerstones of colours you can count on across all themes. Background and foreground make sense to me as meaningful terms. Whatever naming appending numbers seems a slippery slope, so avoiding that seems great to me.

What I find problematic actually is the use of primary/secondary and other words that tend to mean less - but that might be because I really want my theme.json right now to read like a recipe, not code. I don’t know if this is going to change for me with time and a personal feeling. Accent also feels strange to me as a term, accent to what? If we settle on some core fixed words, we have to think about translation, their comprehension, meaning and implications. All very doable as this process happens.

I really am intrigued by the light/dark append @richtabor suggested, which reminds me of the approaches in various preprocessors. I think that is also needed to get around some block and pattern issues I think anyone who has played with this for even a short while has encountered now.

aristath commented 3 years ago

Over the years I have found that primary, secondary, accent etc are usually opinionated colors and not always suitable for text or backgrounds of large areas. I agree with the suggestion above, background and foreground (or more appropriately text, since foreground can be perceived as a 2ndary background color which is more on the forground) should be required. Required: background, text. Optional: Everything else.

I have a black&white theme for example, where primary, secondary, accent etc don't make any sense... Background & text will always make sense no matter the theme or context. And they also have the additional benefit that they open the door to dark-mode as well. It's a lot easier to flip background & text colors when we know what they are, and that they will be some reasonable, high-contrast colors that can work.

MaggieCabrera commented 3 years ago

I've been playing around with the Automattic theme.json supported themes and across a few other points. BlockBase, Seedlot Blocks, and Blank Canvas all have primary, secondary, background, and foreground colors added. Quadrat does not, but perhaps it will (or should).

We ended up iterating on Quadrat and going the semantic route as well. I feel like themes need to use semantic colors if they want their users to be able to customize their site's colors in a comprehensive way. Having a "blue" color defined makes little sense when the user goes to the Global Styles panel and changes its value to a red color. Changing a "background" color from blue to red does mean something instead.

In the end, it all boils down to how the user is going to customize their site and a theme providing a color is not useful for that, but a color that is common to certain blocks or elements to the site. What those are named it would be interesting to discuss. I think that since the editor is already providing the ability to change the background and text color, those colors should exist as variables too, and be able to be assigned to other places by the theme (and the user). And then if the theme needs to add extra semantic colors (be it secondary, foreground, accent, or whatever you name it) then that could be a theme decision.

colorful-tones commented 3 years ago

I have a black&white theme for example, where primary, secondary, accent etc don't make any sense...

@aristath This does not land for me. I think that monochromatic grays can easily be assigned to primary, secondary and accent, which reinforces the naming convention as a sound choice.

I definitely lean towards non-semantic color naming (e.g. seaside-blue) when developing a theme. But, I'm now seeing the more significant consideration of the user who would be interacting with the Global Styles UI in WP Admin. In this case, I think that primary, secondary, and accent strike a common ground.

I agree that a set of semantic color variables should be required within themes (and theme.json).

I also agree with @richtabor note on some sort of light/dark variables are necessary.

I think this might be a good required palette:

I think it would be a great polishing feature to put some checks in place in the WP Admin UI for contrast validation (likely similar to what exists in color picker UI for blocks) for --light vs --dark and --text vs --background.

I think that --light vs --dark and --text vs --background will often get assigned the same values by developers, but would like to see them nonetheless.

Also, I wanted to note that I would love to see the ability for a theme.json color palette to contain a duplicate color, which I think would be necessary for allowing theme developers to reuse color variables and names.

I'm currently working on my first theme.json theme and it is for a client that has several brands, which requires several palettes. While this would be more ideal for a child theme or even Multisite scenario, but it is not part of requirements. Therefore, I have about 20-25 colors in palette and some I would like to reuse, but theme.json fails if you try to reuse same hex color for multiple keys with unique slugs.

However, this is a separate issue for implementers to overcome and should not hold up progress on this color discussion.

aristath commented 3 years ago

I have a black&white theme for example, where primary, secondary, accent etc don't make any sense...

@aristath This does not land for me. I think that monochromatic grays can easily be assigned to primary, secondary and accent, which reinforces the naming convention as a sound choice.

I meant literally a black & white theme (for designs a-la every-layout.dev). No grays or shades, no colors of any kind in the palette other than a black and a white, and the theme also disables custom-colors :smile:. Enforcing a wide array of colors would make it impossible to build a theme like that, I'd have to add a bunch of other colors that I didn't want to add - just because WP "thinks" that I I should have more.

If we are going to require a palette, then the requirements should be limited to colors that are actually required - and that is no more than the background & text colors. Everything else is not strictly speaking required and should be opt-in

JiveDig commented 3 years ago

Enforcing a wide array of colors would make it impossible to build a theme like that, I'd have to add a bunch of other colors that I didn't want to add - just because WP "thinks" that I I should have more.

I think a standard set of named variables/options for colors still fits here. If the theme only needs black and white, the json file can have false or null for those color names, then they won't show up as options in the palette at all. The only concern would be fallbacks for code/content/themes that rely on those colors.

MaggieCabrera commented 3 years ago

I'm on the fence about the need for more standard semantic colors beyond background and text. On one hand, I agree with @aristath that a theme shouldn't have to define more than those two, but on the other hand, I see the value of having those names always mean a thing between theme changes so that when we create patterns or the user changes themes those class names are still there.

But "primary" or "accent" may mean different things between two themes while background and text are very specific on their intent and theme switching between themes that care about "primary" colors differently can lead to unexpected results for the end user.

JiveDig commented 3 years ago

But "primary" or "accent" may mean different things between two themes while background and text are very specific on their intent and theme switching between themes that care about "primary" colors differently can lead to unexpected results for the end user.

I agree. If we had to choose between 2, I'd prefer some way to know if a color is dark or light vs where it would be used in the theme. Our premium theme now uses element names, but that doesn't fit everything. Background, background alt (expects a light value), header, body text, heading text, primary button, secondary button.

I'm not opposed to a generic/vague naming convention, with focus on dark/light/neutral.

A not perfect set of examples: --light-1, --light-2, etc. --dark-2, --dark-3, etc. --neutral-2, --neutral-3, etc.

A theme designer can think of -1 as primary and -2 as secondary if they choose, or not, at least they'd know if it was dark/light so when switching themes it would still mostly work. The only thing the user would have to do is change the colors, not "fix" a broken theme.

The key things to figure out IMHO:

  1. Having set names that themes can (optionally) use, so switching themes breaks a minimal amount of things.
  2. A way for theme designers to know if the color is dark, light, or neutral. This would help # 1.
  3. Not limiting the theme design/layout. A theme with a bunch of core colors and 20 other custom colors in the design and a black/white theme should be easily doable, as well as.
colorful-tones commented 3 years ago

Yes, I think it needs to be a balance of WYSIWYG (what you see is what you get) and WYSIWYMNG (what you see is what you might not get).

I.e. background and text are a great base requirement and would likely fall in to the WYSIWYG category when perusing Block Patterns as an everyday user.

Whereas, primary, secondary, accent would fall in to the WYSIWYMNG category, which I see as a positive experimentation for theme developers to explore, experiment, and/or ignore (with duplicate values). 🤔

kjellr commented 3 years ago

If we are going to require a palette, then the requirements should be limited to colors that are actually required - and that is no more than the background & text colors. Everything else is not strictly speaking required and should be opt-in

I agree strongly with this — If there are any required palette colors for themes, the requirements should be as minimal as possible. Some themes will only need a foreground and background, and will have no use at all for dark, light, etc. I don't think it makes sense to enforce values for those.

You don't have to look too far to find a theme that doesn't require a large palette either. If you ignore the dark mode stuff, Twenty Twenty-One primarily relies on just two colors: a foreground and background. It would generally work fine if all the rest were stripped out.

If we want to establish suggested naming practices for more colors beyond foreground/background that's fine, but I don't think it makes sense to require more than just those two values.

scruffian commented 3 years ago

One aspect to consider here is patterns. If I insert a pattern that relys on the theme colors, when I customize the theme or switch themes, I would expect the colors to change to the new defaults of the theme. If some themes define a set of 5 colors and others only define 2 then what would happen to these other colors in the pattern?

justintadlock commented 3 years ago

We should clarify what we mean by "required" here.

A theme should never be required to implement specific color slugs. There are too many use cases outside of our bubble where such subjective "rules" don't make sense.

Instead, we should have a standard that is used by core and the pattern directory. This convention should be 100% opt-in. However, if a theme chooses not to, core will automatically output those classes/colors.

For example, core already handles --wp--preset--color--white and --wp--preset--color--black. It is not a stretch to have defaults for --wp--preset--color--foreground and --wp--preset--color--background.

That's as far as I would go with "required" colors: background and foreground. Beyond that, we should have a recommended practices document.

For the patterns directory, we can always enforce the background/foreground colors too.

JiveDig commented 3 years ago

There will absolutely be a ton of themes that do enable a bunch of colors though. I'd guess that a majority will.

I think we need a plan for the themes that do enable more than foreground/background. It can still all be opt-in. If any theme defines colors, and switches to another that also defines colors, it shouldn't break. Those themes should have consistent naming/output.

If a user has a theme that does define colors, then switches to a theme that doesn't (only has foreground/background), that is a separate concern that needs to be discussed.

mtias commented 3 years ago

Thank you all for the discussion and thoughts!

It's important to establish and clarify that background and text are not to be understood as theme colors in this proposal but instead as concrete elements that a theme can customize. This is an important distinction because elements are not part of a theme color palette but could be set to a theme color. A theme color palette should be an optional thing and used when a theme wants to express branding colors semantically and make them available to the user to pick when they interact with color tools.

When a theme specifies the background of a site using its palette what it would do is assign one of its colors to a concrete element (Background -> Theme Primary). But it doesn't have to use a color defined in its palette for this purpose, it can also use a custom color (Background -> {hex}) or a default color (Background -> Default White). The important point, though, is that the overall look of a theme will be defined by what colors are assigned to what elements in theme.json not strictly by what the theme might supply as a color palette.

All in all, we cannot be too performative on what colors a theme declares for its palette since it could range anywhere from no colors at all to twenty or more. But we can establish and encourage the use of probably primary and secondary as a desirable convention; beyond which it gets extremely blurry and confusing since a theme's interpretation of what each represents is going to differ in ways that cannot be anticipated nor mapped cleanly. Elements, though, are used across blocks, hence their global nature, and properly understood across themes. Initially, these are a provided set (background, text, titles, captions, etc) but it stands to reason this would eventually be extensible or configurable (this ties a bit with style variations and that separate roadmap, so I won't get too far there).

Finally, patterns should be able to use primary and secondary (if we establish them as conventions) or any color from the default palette (non-semantic colors). That's why it's important, even if the UI is not present to pick a default color, that we can still provide the class mappings under the hood so that patterns don't need to go exclusively with inline hex codes alone.

Variants and shades of a color would be really nice to prefigure, though there is currently no UI designed for it, so that should be explored as well separately. How can we introduce ranges like -900 -100 without overwhelming people? Should it be calculated or supplied? Should it be part of the palette or the color picker?

It'd also be interesting to have the default color palette split between colors and neutrals, as @justintadlock shared, even if gets presented visually as a single palette. Right now we have black, white, and two grays supported (only one selectable!), and it can be limiting. It also stands to reason that core, plugins, or themes would want to eventually provide an entire replacement of the default palette with non-semantic colors (a more vibrant or more muted palette).

fwazeter commented 2 years ago

While today, adding default CSS custom props to the body scope isn't such a big deal - as it's adding all of ~28 properties, it's easy to see how this will end up creeping and growing over time as block patterns evolve. Plus, as a general matter of good practice, you want as few props being called globally as possible, and ideally those being called being used consistently across the majority of pages.

Patterns by nature are more modular than templates, able to pass between themes much like blocks, and their behavior and dependencies should be isolated similar to how core blocks are when it comes to styling.

I've been developing quite a few FSE themes for clients in a production setting lately, in anticipation of the inevitable change-over. When it comes to color conventions, all of these themes we create presets for --primary, --secondary and some --accent, as in pretty much every case, it's just about sticking to brand colors.

Aside from those cases, what's useful is grayscale, for example, we override --wp--preset--color--black to be slightly off black for accessibility/useability reasons hsl(0, 0%, 15%) as default for text, and create a separate preset --pure-black for #000. Likewise, we keep white, and create an --off-white preset with hsl(240,33%,99%), and typically keep the default --wp--preset--color--cyan-bluish-gray because it's a nice shade of gray.

Expanding some shades of gray for a palette could be seen, as well as shades of the brand primary and secondary colors, although this functionality likely could be handled via a plugin.

In other words, the most common use cases for color that I've come across is brand-primary, brand-secondary, shades of those colors (which could be achieved with a slider, more or less) and shades of gray - even the most average implementation of gradients used globally are some combination of the brand primary & secondary colors, or shades of.

Some themes will, by nature, enable a thousand colors, but that should be a theme creation choice, the default should be the minimum use case possible when talking about enqueueing colors across the entire body element scope. Likewise, patterns will want to showcase color's as a way of attracting people to install them, but these color palettes should be scoped specifically to the block pattern itself - that way someone can override them if they want to dig into them, just like you can override individual block presets.

The legwork is already done for enabling block.json for blocks and theme.json for themes - I'd imagine it wouldn't be too tricky to add a pattern.json for patterns - else just defining the variables they use to the php code itself via an associative array (because it has to be done anyway).

It's great that the defaults load so you can see them when you're first creating a theme to see how it's all connecting - but this should at least be opt-outable by setting a parameter in the theme.json file.

fwazeter commented 2 years ago

Thinking on this further - a possible solution to shades could be to incorporate a function similar to the duotone color filter - effectively a shade filter. In that sense, you'd have your core colors that you chose and then the option to apply shading.

In this case you'd have core colors: primary, secondary, black, white (although Theme Shapers makes a good argument for deliberately naming colors vs. just primary/secondary in terms of user confusion - accommodating that convention, but that's a semantic conversation for another time).

With a range of 'shade' filters, and using HSL as the primary color tool, you could very easily create shade variables, similar to how you might set a variable for, say, font-sizes (Sm, Med, Lg, Xlg, etc) and apply them to any color selection.

Let's take two example 'brand colors', a teal and a red, + the black and white.

primary - hsl(194, 60%, 53%) (teal) secondary - hsl(355, 59%, 39%) (red) black - hsl(0, 0%, 0%) white - hsl(0, 100%, 100%)

Making things lighter or darker (shading), requires just manipulating the L value in HSL. To make it lighter, add to the L value, to make it darker, subtract from the L value.

So, 3 base 'shade' values, 20%, 40%, 60% would look like the following: primary - hsl(194, 60%, 20%) , hsl(194, 60%, 40%), hsl(194, 60%, 60%)

Of course, an L value of 0% will always return black, and 100% will always return white. A way around this would be to take advantage of css's calc function, and a sample implementation might look like this:

primary color palette - hsl(194, 60%, 53%)

--primary-color-h: 194 --primary-color-s: 60% --primary-color-l: 53%

--lighter: 15%; --darker: -15%

primary-color-lighter: hsl(var(--primary-color-h), var(--primary-color-s), calc(var(primary-color-l) + var(--lighter))); primary-color-darker: hsl(var(--primary-color-h), var(--primary-color-s), calc(var(primary-color-l) + var(--darker)));

You could get into a lot of cool things like making color triads, complementary colors and such by further manipulating H or S values - which could auto generate a palette of colors based on the primary color selected. The initial values or final values could be returned as RGB, HEX, etc if there was a wrapper to convert the value to HSL.

Alternatively, you could select your desired 'shade' sets, and a function would simply spit out your primary color recalculated with the different shades for each color you wanted.

To keep things clean on the editor side, similar to how gradients has a toggle at the top, you could have a toggle for color / shades.

The above implementation uses pure CSS, and certainly a more powerful function could be created on the php / js side of things.

A reference article implementing above: https://tsh.io/blog/why-should-you-use-hsl-color-representation-in-css/

There was some company that had a similar implementation to generate color palettes based on an HSL seed color that was pretty cool, but I can't for the life of me remember it.

skorasaurus commented 2 years ago

Issue that requests the guidelines/best practices being discussed here > https://github.com/WordPress/gutenberg/issues/19352

richtabor commented 2 years ago

I wrote some detailed thoughts on standardizing color entries in theme.json here, examples and all: https://richtabor.com/standardizing-theme-json-colors/

overclokk commented 2 years ago

First of all I think that if I add colors, gradients or font sizes to a theme.json those generated by the core should not be loaded at all. Core should add defaults only if theme doesn't have its own.

Second, the UI is primarly for who cretes the layout, who really uses the site is who inserts articles and media (so there should be also a role for theme.json settings).

And I agree with this:

@mtias

one of the quick steps I imagine here would be to introduce a new defaultColorPalette = true property in theme.json, which themes can disable if they don't want default colors at all.

I don't like to have dead CSS used nowhere.

And I like the idea of @fwazeter to use HSL() inside the Global Styles interface.

Just a note before starting

From my point of view slug should be as generic as possible and the name should be as specific as possible like a description for the element, example:

{
    "slug": "background",
    "color": "rgba(255,255,255,1.00)",
    "name": "Background for the body of the page"
},

The name can be used to add more context on where the value should be used.

Color naming convention

Starting with background and foreground

Instead of foreground I prefer text as a word, it is more clear the intent.

so it will be

--wp--preset--color--background
--wp--preset--color--text

Now if we want to be more specific we can add where they are used:

--wp--preset--color--body-background
--wp--preset--color--body-text

But this will increase the lenght of the slug and I prefer to be less verbose.

And also I Agree with this: @aristath

If we are going to require a palette, then the requirements should be limited to colors that are actually required - and that is no more than the background & text colors. Everything else is not strictly speaking required and should be opt-in

But we have an issue

The editor UI has "Text color" and "Background color" with both the same palette so we have to consider some confusion from the users.

About light, dark and accent

Even if light and dark are half generics and I can change light/dark color with another light/dark color whitout loosing the scope of the CSS variable I think they should be created by themes, not by core because how many light/dark should the themes need?

And accent also it confuses me as well as it does to @karmatosed , accent to what?

Brand color

Now what about the brand colors?

We can have a palette with base of colors, (one, two or three) and with variants of colors (base color with its shade of variants) and this can create many CSS variables that we don't want, but we know for sure that brands have at least one color, so:

{
    "slug": "base",
    "name": "The main color of the brand"
},
--wp-preset-color-base

So, why not just calling it base color and having just this one?

Second, third and so on

How about the second, or third color?

Now I see a lot use of primary, secondary, tertiary and so on but for me that I'm not native english from tertiary to beyond are a litle bit difficult to remember :-)

Maybe from the second color to beyond they should be created by theme authors.

Gradients

I don't have an idea about that, I'm still testing, but less gradients we have the better, at least 1 or 2 from background, text and base colors, not something strange like luminous-vivid-amber-to-luminous-vivid-orange

Font sizes

For font sizes we know that there are at least one size, the base size for the browser, normally 16px, so we can use the same approach seen above:

--wp--preset--font-size--base

For the others I don't like the actual naming, huge, gigantic, what? And what if I want to have a bigger size than gigantic, should I have to call it titanic?

I prefer 2 different approach, the first one is to simply use acronyms like, xxs, xs, s, m, l, xl, xxl, and base, in total 8 font sizes

--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

The second is to use the name of the elements that usually use those font size, h1, h2, h3, h4, h5, h6, small, and base, in total 8 font sizes.

--wp--preset--font-size--base // where h5 or h6 could be the base font
--wp--preset--font-size--h1
--wp--preset--font-size--h2
--wp--preset--font-size--h3
--wp--preset--font-size--h4
--wp--preset--font-size--h5
--wp--preset--font-size--h6
--wp--preset--font-size--small // like <small> html element

Maybe could confusing to apply --wp--preset--font-size--h1 to a p elements but it is not so hard to read, font-size--h1 applyed to p element, or p has h1--font-size.

Both approach from my point of view are simple to use.

With first approach to add bigger size simply put another x: xxxl With the second approach to add bigger sizes maybe using something like fontawesome does: font-size--h1-2x

Spacing

For spacing I will use the same approach seen until now with base slug, so

--wp--preset--spacer--base

Wrapping up

This is more or less my approach to organize CSS, it is not to complicated, it requires only a few CSS variables and stop, so base is my slug to use in core and we could have, 3 colors, 8 font size and 1 spacing, about gradients I don't know, normally I use one or two and no more.

overclokk commented 2 years ago

I forgot that slug: "h1" will be converted in --wp--preset--font-size--h-1 So the second approach correct for font sizes is this:

--wp--preset--font-size--base // where h5 or h6 could be the base font
--wp--preset--font-size--h-1
--wp--preset--font-size--h-2
--wp--preset--font-size--h-3
--wp--preset--font-size--h-4
--wp--preset--font-size--h-5
--wp--preset--font-size--h-6
--wp--preset--font-size--small // like <small> html element
overclokk commented 2 years ago

I found this video about font sizes https://www.youtube.com/watch?v=wARbgs5Fmuw The interesting thing is how it creates the structure, using a syntax similar to the font weight. I add it because it could be interesting as a method.

khoipro commented 2 years ago

I think a video from @overclokk brings a great modern typography responsive set to the light. Currently we print out all CSS variables in CSS inline.

I also suggest:

--wp-preset--section-spacer

The section spacing is great approach to match all spacing between blocks in vertical list. For example, we use this variable for setting up spacing between blocks.

Screenshot_3
overclokk commented 2 years ago

I was doing some tests to see in practice which was the best approach for naming color variables and I found an issue if we use the name background, an example:

--wp--preset--color--background

Than the editor will create these css classes:

// For text color
.has-background-color {
    color: var(--wp--preset--color--background) !important;
}

// For background color
.has-background-background-color {
    background-color: var(--wp--preset--color--background) !important;
}

This creates a lot of confusion to me.

So I starting using bodyBg as slug for background color (like bootstrap does):

--wp--preset--color--body-bg

.has-body-bg-color {
    color: var(--wp--preset--color--body-bg) !important;
}

.has-body-bg-background-color {
    background-color: var(--wp--preset--color--body-bg) !important;
}

.has-body-bg-border-color {
    border-color: var(--wp--preset--color--body-bg) !important;
}

And I also think for text a better slug could be bodyText or bodyColor,

I keep testing this to see which ones I'm more comfortable with

sdwire commented 2 years ago

I imagine this goes a bit beyond the initial scope of what was trying to be solved here, but there's another facet of color branding and application that I'd like to explore. Here's the experience I've been wanting to offer my clients:

  1. With whatever standard names this thread lands on, have the theme allow the admin to select the absolute colors for those names to define the branded palette.
  2. In all other color pickers, be able to switch between relative and absolute color modes. Relative color mode would let us select a root color from the branded palette and then have a Value slider to create shades/tints and an Alpha slider. Absolute color mode would be the standard color picker that we have now, with the rainbow hue selector and the large square for choosing saturation and lightness to create any arbitrary color. And let a theme choose to disable absolute color mode for color pickers, constraining the design to various shades, tints, and opacities of the branded color palette.
  3. When the root color is changed in the branded palette, any relative color based on that root color would also change.

The CSS system for this could be similar to the "shading system" that @justintadlock proposed back on May 31. One possible downside to this addition of opacity to that proposal is that it would likely need a cross-product of shades x opacities to be defined for every single color to allow the color pickers to generate the correct class name semantics. It would also mean revisiting the Color Picker design to introduce "relative color" mode. I'm not sure if this issue is the right place to make that big of a suggestion, or if this needs to go somewhere else.

sdwire commented 2 years ago

Thinking more about my previous comment, I'm hopeful that the experience I described is something that I could offer in my theme by programmatically adding value/opacity sliders to the color picker. Perhaps this isn't something that would need to be built-in.

fwazeter commented 2 years ago

I have a few new thoughts on this: lately we've been developing a lot within themes.json and creating flexible themes that all require similar elements (e.g. brand color, secondary color, monochromatic shades/tints of them, grayscale etc).

Splitting up HSL values in themes.json doesn't work too well in practice because you end up with A) an entirely way tooo huge json file and B) when a user inputs a color into the site editor, it overrides it anyway - so any calculations based on the input are instantly invalid.

BUT, where we have had better programmatic success is using the filter: property to programmatically use a custom variable to add a CSS filter for contrast, hue, saturation etc and create monochromatic / triadic / whatever colors based on the original input value OR the client value and it works across whatever color code is preferred - whether it's HSL, RGB or Hex.

So a prop for filtering could be something to consider.

skorasaurus commented 2 years ago

I forgot that slug: "h1" will be converted in --wp--preset--font-size--h-1 So the second approach correct for font sizes is this:

@overclokk FYI, there's an issue for this at https://github.com/WordPress/gutenberg/issues/31629

overclokk commented 2 years ago

@skorasaurus should be solved by https://github.com/WordPress/gutenberg/pull/35751 I had already opened an issue https://github.com/WordPress/gutenberg/issues/35708

johnstonphilip commented 2 years ago

DaisyUI has a pretty great system that includes things like focus states:

{
          'primary': '#570df8',
          'primary-focus': '#4506cb',
          'primary-content': '#ffffff',
          'secondary': '#f000b8',
          'secondary-focus': '#bd0091',
          'secondary-content': '#ffffff',
          'accent': '#37cdbe',
          'accent-focus': '#2aa79b',
          'accent-content': '#ffffff',
          'neutral': '#3d4451',
          'neutral-focus': '#2a2e37',
          'neutral-content': '#ffffff',
          'base-100': '#ffffff',
          'base-200': '#f9fafb',
          'base-300': '#d1d5db',
          'base-content': '#1f2937',
          'info': '#2094f3',
          'success': '#009485',
          'warning': '#ff9900',
          'error': '#ff5724'
}
Screen Shot 2022-01-07 at 10 37 56 AM

https://daisyui.com/core/colors/

overclokk commented 2 years ago

I think now it's too late to create a good pattern for color names.

2022 theme is in place, all developer will use the pattern used in that theme as default now, you can only create your own using custom preset and not with regular preset.

skysarwer commented 1 year ago

Can we revive this thread? I think it's really odd that there is no option for theme developers to cleanly opt-out of having the default color palette rendered on the frontend.

I understand that "some plugins might use these variables" -- but that is a weak excuse to not have an opt-out option.

There are SO many websites that do not need "vivid-luminous-orange" and "vivid-luminous-amber" -- to state just the tip of the iceberg here.

Sorry for the strongly stated opinion, but this convo has been ongoing for over 3 years and decision makers seem to be missing the forest for the trees here.

naumanahmed19 commented 1 year ago

is this possible to get color style with hex instead of slug in markup? it will make it more consistent for API building each theme has its own naming conventions.

<!-- wp:paragraph {"style":{"color":{"text":"#cf2b2b"}}} -->

<!-- wp:paragraph {"textColor":"vivid-red"} -->
daviedR commented 1 year ago

Reviving this thread...


I think we already have color naming standards as mentioned in the Developer Handbook (https://developer.wordpress.org/themes/advanced-topics/theme-json/#color-palette).

Themes should use at least 2 colors:

And then more colors could be added using the sequential color slugs, just like what TwentyTwentyThree theme does:


Possible Issues

There are cases in designs, we need more than 1 contrast color or more than 1 base color.

Here are a few examples:

  1. The page body has a white background color, while the footer area has a subtle gray background color.
  2. For text colors, designers might use different colors for the heading and body text, or even use 3rd color for small meta text.

We could have assigned the alternative colors to one of the sequential slugs. For example:

But some theme designers might assign the opposite. tertiary is for the heading text color and quarternary is for the subtle gray background.

This might cause consistency issues when switching between themes.

Any thought on this?

erikjoling commented 1 year ago

I'm using base, contrast, primary, secondary [...] for color naming as well. For subtle color differences I use derived names, like base-x or primary-2.

So if I have a base color of white, I use base-2 (or base-x) for a light shade of gray.