Color Palette with ACF custom blocks

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

Bill Erickson

Bill Erickson is the co-founder and lead developer at CultivateWP, a WordPress agency focusing on high performance sites for web publishers.

About Me
Ready to upgrade your website?

I build custom WordPress websites that look great and are easy to manage.

Let's Talk

Reader Interactions

Comments are closed. Continue the conversation with me on Twitter: @billerickson

Comments

    • 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/Qwu4p2W5

  1. Jon Schroeder says

    Awesome, thanks. Gonna have to transition. This method is just better than the one I’ve been using.

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

  3. 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.)

  4. Ben Palmer says

    Great as always Bill, just missing gradient support

    “`if ( ! empty( $block[‘gradient’] ) ) {
    $classes[] = ‘has-‘ . $block[‘gradient’] . ‘-gradient-background’;
    }“`