The core WordPress blocks like button and group all share a global color palette. This saves a lot of time because you don’t have to style many variations of each block – every block with a class of .has-secondary-background-color
will have the same background color.
If you’re using theme.json, this becomes even more powerful because you can customize the color palette on a per-block-type level.
At CultivateWP we build a lot of custom blocks with ACF. In the past, when we needed the global color palette we would either wrap our custom block in a group block that had the color styling, or use Matt Whiteley’s guide on syncing ACF colors with the Gutenberg palette. But Matt’s approach doesn’t work with theme.json.
A developer on our team (Chris Brailsford) just found a better way.
Add ‘color’ support
When registering a new block with acf_register_block_type()
, you can use the ‘supports’ array to specify which block editor features this block supports. The documentation lists a few examples, but the important part is All properties from the JavaScript block supports documentation may be used.
To add support for the color feature, add 'color' => true
to the supports array.
acf_register_block_type(
[
'title' => __( 'Hero', 'cwp2021' ),
'name' => 'hero',
'render_template' => 'partials/blocks/hero.php',
'category' => 'cultivatewp',
'mode' => 'preview',
'align' => 'full',
'supports' => [
'align' => [ 'full' ],
'jsx' => true,
'color' => true,
],
]
);
This adds support for both the Background Color and Text Color fields.
For more control, you can pass an array to specify which of those two fields should be displayed.
acf_register_block_type(
[
'title' => __( 'Hero', 'cwp2021' ),
'name' => 'hero',
'render_template' => 'partials/blocks/hero.php',
'category' => 'cultivatewp',
'mode' => 'preview',
'align' => 'full',
'supports' => [
'align' => [ 'full' ],
'jsx' => true,
'color' => [
'background' => true,
'gradients' => true,
'text' => false,
],
],
]
);
Add the classes to your block
Selecting a color from the palette adds a class to your block for styling. This automatically works in the backend because the block editor adds the class for you, but you’ll also need to update your block markup to add the class on the frontend.
Inside your block template file, check for $block['backgroundColor']
and $block['textColor']
.
$classes = [ 'block-hero' ];
if ( ! empty( $block['className'] ) ) {
$classes = array_merge( $classes, explode( ' ', $block['className'] ) );
}
if ( ! empty( $block['align'] ) ) {
$classes[] = 'align' . $block['align'];
}
if ( ! empty( $block['backgroundColor'] ) ) {
$classes[] = 'has-background';
$classes[] = 'has-' . $block['backgroundColor'] . '-background-color';
}
if ( ! empty( $block['textColor'] ) ) {
$classes[] = 'has-text-color';
$classes[] = 'has-' . $block['textColor'] . '-color';
}
printf(
'<div class="%s"%s>',
esc_attr( join( ' ', $classes ) ),
! empty( $block['anchor'] ) ? ' id="' . esc_attr( sanitize_title( $block['anchor'] ) ) . '"' : '',
);
echo '<div class="block-hero__image">' . wp_get_attachment_image( get_field( 'image' ), 'full' ) . '</div>';
echo '<div class="block-hero__content"><InnerBlocks /></div>';
echo '</div>';
Jon Schroeder says
This looks incredible. So this will actually use the same picker that native Gutenberg blocks use (like in the screenshot?) My methodology is hackier, I think, and uses the default ACF picker instead of the default Gutenberg picker: https://elod.in/adding-wordpress-color-palettes-into-the-acf-color-picker/
I’ll have to transition over my blocks.
Will this allow for gradients as well?
Bill Erickson says
Yes, this uses the color picker feature on the core blocks. If your theme has gradients then they will also appear in here.
My theme in the screenshot didn’t have any gradients, but when I add one and have
'gradients' => true
in the color support array, it looks like this: https://a.cl.ly/Qwu4p2W5Jon Schroeder says
Awesome, thanks. Gonna have to transition. This method is just better than the one I’ve been using.
Carl Lister says
Thanks so much for this Bill.
I’m curious if there’s a way to:
a) enable background, text color by default (so users don’t need to ‘view options’ to manually enable background and text for each itteration of the block
b) set a default selection for each
Thanks in advance for any help
Bill Erickson says
You can set the default background / text color for a block with CSS using
:not(.has-background)
and:not(.has-text-color)
.If you’re using theme.json, you can specify the default values directly in there (example), as well as make block-specific color palettes. For instance, we use a different color palette for buttons (brighter colors) and groups (light colors for background).
Carl Lister says
Thanks Bill. This is exactly what I am doing already (sorry, I think I need to be clearer).
What I mean is, when a user creates a new block is there a way to enable these options by default. Instead of the user having to click into and tick each one to see them.
Here’s a screenshot to illustrate what I mean, I want these ticked by default when block is created in dashboard
https://pasteboard.co/0frNNCU4pVtI.jpg
Bill Erickson says
I would try using theme.json to specify a default background / text color for that block type. That should pre-fill in that setting and make it enabled by default.
Jason LeMahieu says
This post is amazing!
A small update to include Link Color might be appreciated by some.
if ( ! empty( $block[‘linkColor’] ) ) {
$classes[] = ‘has-link-color’;
$classes[] = ‘has-‘ . $block[‘linkColor’] . ‘link-color’;
}
Cheers!
Jason LeMahieu says
Update: The code sample in that earlier comment made some assumptions, but linkColor does NOT seem to be available in that method. I’m still working through it, but it looks like it involves $block[‘style’][‘elements’][‘link’][‘color’][‘text’]. Oof!
(All the more reason to consider an update to the post that talks about how to access it.)
Ben Palmer says
Great as always Bill, just missing gradient support
“`if ( ! empty( $block[‘gradient’] ) ) {
$classes[] = ‘has-‘ . $block[‘gradient’] . ‘-gradient-background’;
}“`