Notes on Working with Custom Colors in the WordPress Block Editor

Several (okay, many) months ago, I ran into what I thought was a bug with the WordPress block editor and how it handled custom colors. I reported it and was told that it was an expected behavior. It’s true, but it was still causing me issues and I could not understand why, until I had an epiphany about it this week. I am a slow thinker, what can I tell you? If I am not the only one working through this, here’s a post to explain what’s happening and why.

With the new block editor, we have the ability to add colors to a lot of different blocks. WordPress provides a default set of colors, and allows you to use any custom color you can imagine. On the one hand, that’s great, but on the other hand, I don’t find them to be particularly useful colors.

However, if you use a predefined color, it’s added to your block using a class; if you use a custom color, it’s added to your block using an inline style. Compare:

  • <p class="has-background has-theme-primary-background-color"
  • <p style="background-color:#1d5e8a"

That’s the beginning of a paragraph block. The first has a custom color background which I’ve defined, and it’s named theme-primary. The second one is [currently] the same color, but it’s added as an inline style on the paragraph. I tweak my own brand colors every couple of years, depending on how I feel. With a CSS class, I can just change the CSS rule. With the inline styles, if I change my brand color down the road, I have to search my posts for every place I used that custom color.


So I definitely encourage you to define your own color palette, so that you’re using CSS classes instead of inline styles. Bill Erickson has a great tutorial on that, which I won’t repeat here. My purpose in writing this post is to clarify some of the behind the scenes work that happens when you use the colors you’ve defined.

If you are adding colors to an existing site using PHP, you can go ahead and throw in your custom styles as well, instead of manually writing out the CSS. Here’s an example:

add_action( 'enqueue_block_assets', 'rgc_editor_color_palette', 15 );
 * Add custom colors to the site using wp_inline_style, attached to the wp-block-library stylesheet.
 * Colors must be defined in your theme or functionality plugin.
function rgc_editor_color_palette() {
	list( $colors, ) = (array) get_theme_support( 'editor-color-palette' );
	if ( ! $colors ) {

	$css = '';
	foreach ( $colors as $color ) {
		$css .= sprintf(
			'.has-%1$s-color {color: %2$s;} .has-%1$s-background-color {background-color: %2$s;} ',

	wp_add_inline_style( 'wp-block-library', $css );
Code language: PHP (php)

One nice thing about adding the styles this way is that it’s appended to the end of the block library stylesheet, so it will override any similarly named WordPress defined styles. Additionally, if you tuck a new color into your PHP editor-color-palette array, it will automatically be added to your CSS as well.

WordPress adds multiple classes to blocks when you use custom colors.

This is the key point which I didn’t completely realize until this week. Let’s say I define a custom color called theme-primary (I use something generic like this so that if my primary accent color changes from blue to red down the road, the classes still make sense). If I set a block to use this as the background color, WordPress adds two classes to the block:

  • has-background: this is a general class which is added to any block with a color background. WordPress doesn’t do a whole lot with this, but it does a little. For example, it automatically adds some padding to any paragraph block with a background color. Super helpful.
  • has-theme-primary-background-color: this is the color specific class added to the block, which generally just defines the background color. The padding is added by the more general class. This saves some repetition.

Now, if I set a block to use this as the font color, two different classes are added:

  • has-text-color: this is the general class which is indicating that the paragraph has a custom color of some type for the text. In this case, WordPress adds a general CSS rule to indicate that links should inherit the custom color, instead of being the default link color. This is helpful, because who wants a blue link on a blue background when the rest of the text is white?
  • has-theme-primary-color: this is the specific class which says to make the text the actual color.

You can see with the specific classes where your custom color name gets inserted, right? But the two general classes are somewhat different, and this is where I got tripped up.

See, I want to define a color palette which includes not only branding colors, but also pretty much every color I use throughout the site. So I’ll define rules for a color which matches my basic text color for the site, usually a dark gray, but which may have a tint, and a light gray, and I’ll throw in a white as well because it just makes sense. I do not usually call my text color black or dark-gray because it’s not. In my Sass variables, I usually call it $text, and so my initial color classes used that as well.

This resulted in two new classes: has-text-background-color and has-text-color…except WordPress considers that a general, all-purpose class to indicate that the text is any color other than the default text color. And by defining it as a specific kind of color class, things like that inheritance get lost quickly.

So, here’s a key takeaway: do not use text as a color slug when defining a custom color palette. Use theme-text instead, or pretty much anything else. Consider text to be an off-limits name/slug for colors.

Use the general classes for CSS rules which apply to any blocks with custom color treatments; use the specific classes for the color information.

And now, define all the colors you like. CSS classes are awesome.

photo credit: Toa Heftiba

Reader Interactions

Leave a Reply

Your email address will not be published. Required fields are marked *

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