We will continue working with our “Subscription form” block here. If you want to have a peek at the source files of the block, you can get them below.

Sorry, but you don’t have access to the source files. Sign in or buy the course.

Using block.json to Allow Color Setting Controls

Before we dive into an interesting and a little bit complicated part, I would like to remind you that you can add some simple color settings for a Gutenberg block using a block.json file.

As easy as that:

"supports" : {
	"color": {
		"text" : true,
		"background" : true,
		"gradients": true,
		"link": true
	}
}

So, the long story short, using this way, you can add the following color settings:

  • text – the text color of your block,
  • background, gradients – background of your block (color and gradient),
  • link – link colors.

Let’s take a look at the screenshot below:

Gutenberg color palette for a custom block

You can see in the screenshot above that the background is already predefined there; it can be done with the help of the following configuration in your block.json:

"attributes" : {
	"style" : {
		"type": "object",
		"default": {
			"color": {
				"background": "#f9f9f9"
			}
		}
	}
}

As easy as that!

But now we’re going to talk about something more interesting – specifically about ColorGradientSettingsDropdown (__experimentalColorGradientSettingsDropdown) and also about PanelColorSettings components that allow us to add custom color settings for literally anything in your block.

Using ColorGradientSettingsDropdown and Custom InspectorControls Tabs

If you continue reading this, it means that text, background, and link color settings are not enough for your custom block configuration 😁 Let’s say, for example, that you also need to change the color of the “Subscribe” button and the border color of the input field as a whole.

Something like this:

Using ColorGradientSettingsDropdown component to create custom color controls

And just right now, I am about to show you how to develop these kinds of controls.

Block attributes in block.json

Everything starts in your custom block block.json file anyway, because any custom color setting requires an attribute. It is going to contain a HEX color code, so the type string is more than enough in this case.

"attributes" : {
	"buttonAndBorderColor" : {
		"type" : "string"
	}
}

edit()

Now let’s continue to the edit.js file (or index.js) file of your block, and here we will need to do the following:

  • Add a CSS class and a CSS style rule with the help of useBlockProps() when our custom color setting is not empty,
  • Create an InspectorControls panel, and not just a regular panel, we need to add it into a color group. More about InspectorControls you can read in this lesson.
  • Last but not least, we’re going to use ColorGradientSettingsDropdown component.

The (almost) complete code:

import classnames from 'classnames'

import {
	useBlockProps,
	InspectorControls,
	__experimentalColorGradientSettingsDropdown as ColorGradientSettingsDropdown,
	__experimentalUseMultipleOriginColorsAndGradients as useMultipleOriginColorsAndGradients
} from '@wordpress/block-editor'

export default function Edit( { attributes, setAttributes, clientId } ) {
	
	const classes = classnames( {
		'has-button-and-input-color' : attributes.buttonAndBorderColor
	} )

	const styles = {
		'--button-and-input-color' : attributes.buttonAndBorderColor
	}

	const blockProps = useBlockProps( {
		className: classes,
		style: styles
	} )

	const colorGradientSettings = useMultipleOriginColorsAndGradients()

	return (
		<>
			<InspectorControls group="color">
				<ColorGradientSettingsDropdown
					panelId={ clientId }
					settings={ [
						{
							label: 'Button and input border',
							colorValue: attributes.buttonAndBorderColor,
							onColorChange: ( color ) => setAttributes( { buttonAndBorderColor: color } ),
						}
					] }
					{ ...colorGradientSettings }
				/>
			</InspectorControls>
			<div { ...blockProps }>
				the form block content goes here
			</div>
		</>
	)
}

Is everything clear to you in this code? If not, below are some details:

  • I’m using the “classnames” library here. I can not be sure that you have it installed on your project, so maybe you will need to do it with the command npm i classnames --save-dev. Basically, it allows to easily add has-button-and-input-color CSS class to our custom block when the attribute buttonAndBorderColor is not empty. I think you can also do the same for styles with the help of Object.assign() or something, but it is not really necessary in the editor.
  • The component useMultipleOriginColorsAndGradients (or to say it more exactly – __experimentalUseMultipleOriginColorsAndGradients is required to display your current WordPress theme color palette in the color picker.
  • Grouping InspectorControls is super-easy; you just need to pass group into it.
  • ColorGradientSettingsDropdown component is very similar to PanelColorSettings which we’re going to discuss below as well. As you can see, the required parameters are: clientId (otherwise it won’t be displayed correctly in the “Styles” tab), settings (where we can pass as many color settings as we want) and we’re using …colorGradientSettings, as I already said before, to get the theme color palettes and settings.

Not very difficult now, right?

There are two things left to do: to add some CSS rules to style.scss and to configure save() function, which I am not going to describe in this tutorial, because it is very similar to the edit() function anyway.

style.scss

We’re just using our custom CSS class, which we added in the edit() function, so it is has-button-and-input-color and a CSS variable --button-and-input-color.

.has-button-and-input-color{
	.input{
		border-color: var(--button-and-input-color);
	}
	.button{
		background-color: var(--button-and-input-color);
	}
}

Using PanelColorSettings

I also want you to take a look at the PanelColorSettings component, which, to be honest, seems like an obsolete one, and let me explain why.

You can not put it into the “Styles” sidebar section, so it can only be displayed like a custom InspectorControl section:

Using PanelColorSettings component

So I don’t like to use this approach, but I am going to explain it to you anyway.

First of all, of course, we need to import it from @wordpress/block-editor:

import {
	InspectorControls,
	PanelColorSettings
} from '@wordpress/block-editor';

And then we’re using it similarly to the ColorGradientSettingsDropdown component:

<InspectorControls>
	<PanelColorSettings
		title="Button and input border"
		colorSettings={ [
			{
				label: 'Button and input border',
				value: attributes.buttonAndBorderColor,
				onChange: ( color ) => setAttributes( { buttonAndBorderColor: color } ),
			}
		] }
	/>
</InspectorControls>

The cool thing here is that it is really simple – we don’t need to pass clientId to the component, and also no need to use useMultipleOriginColorsAndGradients() because the theme color settings are going to be applied anyway.

But as I already said before, it seems to me that this component is a little bit outdated.

Using Colors from a Color Palette

I intentionally decided not to include this explanation at the beginning of the lesson. So we’re kind of learning everything step by step.

The thing is that there is a difference between colors from color palettes (the theme palette and the default palette) and custom colors. When we’re using custom colors, your block style attribute may look like this style="--button-and-input-color: #345C00;", but for colors from color palettes, we have to use CSS variables predefined in your WordPress theme, so it will be: style="--button-and-input-color: var( --wp--preset--color--secondary );". It is a proper way of creating color controls for a custom Gutenberg block.

Ok, and what do we need to do then?

First of all, let’s begin with the block.json file and replace the one and only attribute buttonAndBorderColor with two attributes:

"attributes" : {
	"buttonAndBorderColor" : {
		"type" : "string"
	},
	"customButtonAndBorderColor" : {
		"type" : "string"
	}
}

Both attributes are of a string type. Why? Because the first one will contain a color slug from a color palette, for example secondary, the second one will contain a HEX color code itself, for example #345C00.

The next thing we need to do is to wrap the edit() function into a HOC (Higher Order Component) with the help of withColor.

import classnames from 'classnames'

import {
	useBlockProps,
	withColors, // I added this line as well
	InspectorControls,
	__experimentalColorGradientSettingsDropdown as ColorGradientSettingsDropdown,
	__experimentalUseMultipleOriginColorsAndGradients as useMultipleOriginColorsAndGradients
} from '@wordpress/block-editor'

const Edit = ( {
	attributes,
	setAttributes,
	buttonAndBorderColor,
	setButtonAndBorderColor,
	clientId
} ) => {
	
	const classes = classnames( {
		'has-button-and-input-color' : buttonAndBorderColor.color || attributes.customButtonAndBorderColor
	} )

	const styles = {
		'--button-and-input-color': buttonAndBorderColor.slug 
			? `var( --wp--preset--color--${ buttonAndBorderColor.slug } )` 
			: attributes.customButtonAndBorderColor
	}

	const blockProps = useBlockProps( {
		className: classes,
		style: styles
	} )

	const colorGradientSettings = useMultipleOriginColorsAndGradients()
	
	// it is not necessary to move this function out of <ColorGradientSettingsDropdown>
	const onButtonAndBorderColorChange = ( color ) => {
		setButtonAndBorderColor( color )

		setAttributes( {
			customButtonAndBorderColor: color
		} )
	}
	
	return (
		<>
			<InspectorControls group="color">
				<ColorGradientSettingsDropdown
					panelId={ clientId }
					settings={ [
						{
							label: 'Button and input border',
							colorValue: buttonAndBorderColor.color || attributes.customButtonAndBorderColor,
							onColorChange: onButtonAndBorderColorChange
						}
					] }
					{ ...colorGradientSettings }
				/>
			</InspectorControls>
			<div { ...blockProps }>
				the form block content goes here
			</div>
		</>
	)
	
}

export default withColors( 'buttonAndBorderColor' )( Edit )

That’s pretty much it.

One more time I decided to skip the save() function, because it is very similar to the edit() function here, or maybe you’re even working with dynamic blocks, in that case it will be in PHP.

There is also a handy function getColorClassName() that can be imported from @wordpress/block-editor, you can use it to create a class name for your block when a specific color from a palette is selected, for example has-{SLUG}-button-and-input-color. But here I decided to use another approach – the only CSS class has-button-and-input-color and CSS variables.

Misha Rudrastyh

Misha Rudrastyh

Hey guys and welcome to my website. For more than 15 years I've been doing my best to share with you some superb WordPress guides and tips for free.

Need some developer help? Contact me

Follow me on X