How to Show Variations on the Shop Page

When you visit online store websites, you can notice that sometimes product variations (often colors, but not only) could be displayed nicely on the shop and category pages.

Something like this:

WooCommerce show color variations on shop page

But how can we do it on our store created with WooCommerce as well? The thing is that, by default, WooCommerce doesn’t have a feature that allows you to show variations on shop and category pages.

In this tutorial, I will show you how you can do that. More than that, I am going to show you multiple approaches:

Ok, let’s dive into that.

Show Color Variations on the Shop Page with a Plugin

In case the programmatic solution is not what you need or you don’t have time to deal with the code, then I’d like to suggest my plugin – Simple Variation Swatches for WooCommerce, which not only allows you to show variations on the shop page but also provides some settings where you can choose a specific attribute, “Color”, for example.

All right, once you’ve installed and activated the plugin on your WooCommerce store:

  1. Open the plugin settings in “WooCommerce > Settings > Products > Variation Swatches.”
  2. Check the checkbox “Allow attribute selection on shop and archive pages.”

That’s pretty much it. Below is the screenshot for convenience:

Allow color variations to be displayed on shop and archive pages in the plugin settings
We have also selected a specific attribute, “Color”, because we do not want all the attributes to be displayed on the shop and archive pages.

After that, if you have already configured the “Color” attribute swatches, then color variations will be shown on the shop and archive pages of your WooCommerce store:

WooCommerce show color variations on shop page

The plugin approach will work for classic and block WooCommerce themes, as well as for stores created with Elementor, etc.

Show Variations on the Shop Page Programmatically

I am going to be honest with you; in this specific case, the programmatic approach is kind of complicated, and here is why:

  • We need to keep in mind that a store where our code can be used may have AJAX pagination (with the Interactivity API, for example) or AJAX product filters.
  • There are plenty of hooks available in WooCommerce, for example, which allow us to change the “Add to cart” button text or something else, so we don’t have to hardcode anything, which will make those filter hooks unusable.
  • Would we like to have an “Add to cart” button available on shop pages as well? Or maybe it will be enough just to show all variations, and when a customer selects a specific one and then clicks “Select options”, a product page will be displayed with the same attributes selected. Here, in this tutorial, I think it would be better to go the simple way (the last one), but if you want to add variations to the cart from archive pages, just scroll up to the plugin approach above.

All right, in total, there are going to be two steps – in the first one, we will show variations on the shop and archive pages with the woocommerce_loop_add_to_cart_link hook, and in the second step, we will do some stuff in JavaScript to make sure the proper variation attributes are selected.

I think the woocommerce_loop_add_to_cart_link filter hook is the best solution here because it allows us to modify the “Select options” button HTML (for variation products). Plus, there is a WC_Product object available as a second callback function argument, which is great.

Here is the code snippet:

<?php
add_filter( 'woocommerce_loop_add_to_cart_link', 'rudr_show_variations_shop_page', 99, 2 );

function rudr_show_variations_shop_page( $add_to_cart, $product ) {

	// do nothing in case it is not a variable product
	if( ! $product->is_type( 'variable' ) ) {
		return $add_to_cart;
	}

	// if there are no variations available, also do nothing
	if( ! $variations = $product->get_available_variations() ) {
		return $add_to_cart;
	}

	ob_start();
	?>

	<div class="variations_form" data-product_variations="<?php echo wc_esc_json( wp_json_encode( $variations ) ) ?>">

		<?php 
			foreach( $product->get_attributes() as $attribute_name => $attribute ) :
				?>
					<div class="rudr-variation-select value">
						<?php
							wc_dropdown_variation_attribute_options(
								array(
									'show_option_none' => 'Select ' . strtolower( wc_attribute_label( $attribute_name ) ),
									'options' => $attribute->get_slugs(),
									'attribute' => $attribute_name,
									'product' => $product
								)
							);
						?>
					</div>
				<?php 
			endforeach;
	
			// don't forget about the default "Select options" button
			echo $add_to_cart;
		?>
	</div>
	<?php
	
	return ob_get_clean();

}

In the code above:

  • I store the whole value of $product->get_available_variations() inside an HTML attribute data-product_variations, because WooCommerce itself does exactly that on single product pages.
  • Output buffering (ob_start() and ob_end_clean()) is required here because the function wc_dropdown_variation_attribute_options() can not return the result; it can only print it.

Last but not least, if you would like to display only one specific attribute, not all of them, for example, you would like to only show color attributes on shop pages, then you can just add the following condition inside the foreach() loop:

if( 'pa_color' !== $attribute_name ) {
	continue;
}

I think that’s pretty much it with the first step. If you have done everything correctly, the variations will be displayed on the shop page, something like this:

WooCommerce show variations on shop page

When you select any of the variations, nothing will happen at this moment; that’s why we need to continue to the second step.

Step 2. Selecting appropriate product attributes in JavaScript

All right, depending on what you’re going to achieve, this step could be super complicated or not. Previously, we decided that we would not go all in and just change the URL of the “Select options” button, and maybe we can also change the product image – why not?

Before jumping straight into the JavaScript code, I also want to highlight the moment when it could be quite tempting to include the wc-add-to-cart-variation.js file in the shop and archive pages. You could try to do that, of course, but I faced a lot of issues when working with it, so I decided that it would be better to just fork some of its functions and write my own JavaScript/jQuery code for shop pages.

And here we go:

jQuery( function( $ ) {

	$( '.archive' ).on( 'change', 'select[data-attribute_name]', function( e ) {
		// prepare a bunch of necessary variables
		const select = $(this),
		      chosenAtts = {},
		      form = select.closest( '.variations_form' ),
		      variations = form.data( 'product_variations' ),
		      productLi = form.closest( 'li.product' ),
		      attributeFields = form.find( 'select' ),
		      addToCartButton = form.find( '.add_to_cart_button' )
	
		// the URL we will set as a href attribute for the "Select options" button
		let url = new URL( addToCartButton.attr( 'href' ) )

		attributeFields.each( function() {
			const attributeName = $( this ).data( 'attribute_name' )
			const value         = $( this ).val() || ''

			// only if you need to change image on attribute selection later
			chosenAtts[ attributeName ] = value

			url.searchParams.set( attributeName, value )

		})

		// console.log( chosenAttributes );
		addToCartButton.attr( 'href', url )

		// OPTIONAL: if you want to change product images on attribute selection
		const foundVariations = findMatchingVariations( variations, chosenAtts )
		if( 0 < foundVariations.length && foundVariations[0].image ) {
			productLi.find( 'img' ).attr( {
				src: foundVariations[0].image.src,
				srcset: foundVariations[0].image.srcset,
				width: foundVariations[0].image.src_w,
				height: foundVariations[0].image.src_h
			} )
		}

	} )

} );

What is worth keeping in mind here?

  • You shouldn’t worry about jQuery. I know many of you guys don’t like it, but since WooCommerce is using it on its shop pages, why can’t we?
  • I didn’t include the findMatchingVariations() function into my code for the sake of simplicity; however, you can find its source code in the add-to-cart-variation.js file.
  • The .archive selector in the beginning assumes that you’re using the body_class() or wc_body_class() in your WooCommerce theme.

Our result when using the code correctly:

Change product image on variation select on the shop page.
Sure thing, it will work for colors as well.

If you have any questions about either the Simple Variation Swatches for WooCommerce plugin or the programmatic approach, feel free to ask in the comments below.

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