How to Display Variations with Color (or Size) Buttons

In this tutorial I will show how you can change the way the variation selection is working on the product page in WooCommerce.

We all know that by default the variations are displayed like a select dropdown.

default variation switcher on WooCommerce product page
Wouldn’t it be better to use color swatches here?

But today we will learn how to display them as color swatches. If you would like to display them as size buttons or custom images, you can do it with my plugin.

This is our goal for this tutorial:

WooCommerce display color variations with buttons

But before we dive deep into the coding part, I would like to recommend you my plugin Simple Variation Swatches for WooCommerce, it does exactly the same thing.

Add an Attribute Type

Do you know what the nicest thing is? It is that WooCommerce already has the functionality that allows you to add your own custom attribute types!

Did you know about that before? There is a hook product_attributes_type_selector and all you need to do is to pass an additional attribute type to the array of attribute types.

add_filter( 'product_attributes_type_selector', 'rudr_add_attr_type' );

function rudr_add_attr_type( $types ) {
	
	// let's add a color here!
	$types[ 'color_type' ] = 'Color'; // "color_type" // is just a custom slug
	return $types;
	
}

Even this small snippet of code will affect a lot of things on your website. Let’s assume that we have already created a Color attribute, so if you go edit that attribute, you will see Type dropdown option appeared.

select an attribute type in WooCommerce
Just using product_attributes_type_selector filter hook allows to add an attribute type selection on add / edit attribute admin pages.

Add a Color Picker Field to the Attribute Terms

Now we are about to add a custom field to term pages in WordPress admin.

Add a field

Before inserting the code I would like to highlight a couple things I am going to hardcode here.

  • I created an attribute “Color” and its slug is color which leads to the moment, that the taxonomy name is always going to be pa_color. For all the code examples below.
  • Also the meta key of a color code custom field is always color_type. In my case it matches the attribute type slug we created but it is not necessary.

In order to deal with less amount of code in our example I decided to add the color picker field only on “Edit term” pages. In order to do so I am using TAXONOMY NAME_edit_form_fields, but you can also add it to “Add term” pages with TAXONOMY NAME_add_form_fields, more on that in this tutorial.

<?php
add_action( 'pa_color_edit_form_fields', 'rudr_edit_fields', 10, 2 );

function rudr_edit_fields( $term, $taxonomy ){

	// do nothing if this term isn't the Color type
	global $wpdb;

	$attribute_type = $wpdb->get_var(
		$wpdb->prepare(
			"
			SELECT attribute_type
			FROM " . $wpdb->prefix . "woocommerce_attribute_taxonomies
			WHERE attribute_name = '%s'
			",
			substr( $taxonomy, 3 ) // remove "pa_" prefix
		)
	);

	// if it is not a color attribute, just do nothing
	if( 'color_type' !== $attribute_type ) {
		return;
	}

	// otherwise let's display our colorpicker field
	// we can use attribute type as a meta key why not
	$color = get_term_meta( $term->term_id, 'color_type', true );

	?>
		<tr class="form-field">
			<th><label for="term-color_type">Color</label></th>
			<td><input type="text" id="term-color_type" name="color_type" value="<?php echo esc_attr( $color ) ?>" /></td>
		</tr>
	<?php

}

Save field value as term meta

Do not forget about sanitizing functions here, so for hex color values I can use sanitize_hex_color().

add_action( 'edited_pa_color', 'rudr_save_color' );
function rudr_save_color( $term_id ) {
	
	$color_type = ! empty( $_POST[ 'color_type' ] ) ? $_POST[ 'color_type' ] : '';
	update_term_meta( $term_id, 'color_type', sanitize_hex_color( $color_type ) );
	
}

I used edited_TAXONOMY NAME here, but, if you decided to display the field on add term pages as well, you will also need created_TAXONOMY NAME hook.

Add color picker

There are different ways how you can implement this part. But the key ideas should be:

  • Make sure that color picker library is included in your WordPress admin, in this example I am using wp-color-picker.
  • Then initialize the color picker, I do it this way $( '#term-color_type' ).wpColorPicker();

In case everything has been done correctly, we can enjoy our brand new color picker field when we edit attributes of a color type.

create color picker field in WordPress admin

Do Some Magic with Attributes on Edit Product Page

Now it is time to go to the edit product page of any variable product, you can create a new one if you wish. But the thing is when you go to Attributes tab, you will find out that something is definitely missing there.

There is actually no field where you can add attributes to a product!

attributes form is missing on edit product pages

It is because this particular form should be altered for every custom attribute type. How? With woocommerce_product_option_terms hook.

<?php
add_action( 'woocommerce_product_option_terms', 'rudr_attr_select', 10, 3 );

function rudr_attr_select( $attribute_taxonomy, $i, $attribute ) {

	// do nothing if it is not our custom attribute type
	if( 'color_type' !== $attribute_taxonomy->attribute_type ) {
		return;
	}

	// get current values
	$options = $attribute->get_options();
	$options = ! empty( $options ) ? $options : array();
	
	?>
	<select multiple="multiple" data-placeholder="Select color" class="multiselect attribute_values wc-enhanced-select" name="attribute_values[<?php echo $i ?>][]">
		<?php
			$colors = get_terms( 'pa_color', array( 'hide_empty' => 0 ) );
			if( $colors ) {
				foreach ( $colors as $color ) {
					echo '<option value="' . $color->term_id . '"' . wc_selected( $color->term_id, $options ) . '>' . $color->name . '</option>';
				}
			}
		?>
	</select>
	<button class="button plus select_all_attributes">Select all</button>
	<button class="button minus select_no_attributes">Select none</button>
	<?php
}

I skipped a couple of escaping functions here, but if you create a plugin for example, please be more conscious with that.

Add Color Swatches on Product Pages (Frontend)

The last part of our tutorial and it is not that difficult by the way.

All we have to do is to display all the product color attributes like buttons, hide with CSS the original variation dropdown and then start changing its value when customers click on our custom variation buttons.

HTML part:

add_filter( 'woocommerce_dropdown_variation_attribute_options_html', 'rudr_swatches_html', 20, 2 );

function rudr_swatches_html( $html, $args ){

	global $wpdb;

	$taxonomy = $args[ 'attribute' ];
	$product = $args[ 'product' ];

	$attribute_type = $wpdb->get_var(
		$wpdb->prepare(
			"
			SELECT attribute_type
			FROM " . $wpdb->prefix . "woocommerce_attribute_taxonomies
			WHERE attribute_name = '%s'
			",
			substr( $taxonomy, 3 ) // remove "pa_" prefix
		)
	);

	// if it is not a color attribute, just do nothing
	if( 'color_type' !== $attribute_type ) {
		return $html;
	}

	// the thing is that we do not remove original dropdown, just hide it
	$html = '<div style="display:none">' . $html . '</div>';

	// then we display the swatches

	// in order to do so we loop all attributes in a taxonomy
	$colors = wc_get_product_terms( $product->get_id(), $taxonomy );

	foreach( $colors as $color ) {
		if( in_array( $color->slug, $args[ 'options' ] ) ) {
			// get the value of a color picker actually
			$hex_color = get_term_meta( $color->term_id, 'color_type', true );
			// add class for a selected color swatch
			$selected = $args[ 'selected' ] === $color->slug ? 'color-selected' : '';

			$html .= sprintf(
				'<span class="swatch %s" style="background-color:%s;" title="%s" data-value="%s"></span>',
				$selected,
				$hex_color,
				$color->name,
				$color->slug
			);
		}
	}

	return $html;

}

CSS part:

.swatch {
	width: 30px;
	height: 30px;
	display: inline-block;
	margin-right: 10px;
	cursor:pointer;
	border: 1px solid #fff;
	outline: 2px solid #fff;
}
.swatch.selected{
	outline: 2px solid #333;
}

JavaScript part:

$( '.variations_form' ).on( 'click', '.swatch', function ( e ) {
	// clicked swatch
	const el = $( this );
	// original select dropdown with variations
	const select = el.closest( '.value' ).find( 'select' );
	// this specific term slug, i.e color slugs, like "coral", "grey" etc
	const value = el.data( 'value' );

	// do three things
	el.addClass( 'selected' ).siblings( '.selected' ).removeClass( 'selected' );
	select.val( value );
	select.change();

} );

As you might have noticed we are just going to trick WooCommerce to make it think that customers click on the original variation dropdown while they do not.

And of course, it you’re having some difficulties with implementing this code on your website, I recommend you to take a look at my Simple Variation Swatches plugin, which by the way comes with my support.

Finally:

WooCommerce display color variations with buttons
Misha Rudrastyh

Misha Rudrastyh

Hey guys and welcome to my website. For more than 10 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 Twitter