Display Variations as Radio Buttons

In this tutorial I’d like to show you an example how to replace the default variation select dropdowns with radio buttons without plugins. Maybe for specific WooCommerce product attributes or product IDs only.

Something like that:

how to display WooCommerce variations as radio buttons

We’re going to do it without any plugins, though, you might think that it’d be better to display the “Color” attribute not as radio buttons but as color swatches. Like this:

how to display WooCommerce product variations as color swatches

In this case I would recommend you to take a look at my plugin which allows to do that.

But now let me describe a little bit more what we are about to do in this tutorial:

Now let’s get started.

We will begin with a simple PHP code snippet I created on base of wc_dropdown_variation_attribute_options() function and actually used the hook woocommerce_dropdown_variation_attribute_options_html which is inside that function.

My goal here is to display the variations radio buttons exactly under the default variation selection and hide the default one with display:none. Then, with JavaScript we’re going to emulate the interaction with the select dropdown when users are using radio buttons.

That simple!

add_filter( 'woocommerce_dropdown_variation_attribute_options_html', 'rudr_radio_variations', 20, 2 );
function rudr_radio_variations( $html, $args ) {

	// in wc_dropdown_variation_attribute_options() they also extract all the array elements into variables
	$options   = $args[ 'options' ];
	$product   = $args[ 'product' ];
	$attribute = $args[ 'attribute' ];
	$name      = $args[ 'name' ] ? $args[ 'name' ] : 'attribute_' . sanitize_title( $attribute );
	$id        = $args[ 'id' ] ? $args[ 'id' ] : sanitize_title( $attribute );
	$class     = $args[ 'class' ];

	if( empty( $options ) || ! $product ) {
		return $html;
	// HTML for our radio buttons
	$radios = '<div class="rudr-variation-radios">';

	// taxonomy-based attributes
	if( taxonomy_exists( $attribute ) ) {

		$terms = wc_get_product_terms(
				'fields' => 'all',

		foreach( $terms as $term ) {
			if( in_array( $term->slug, $options, true ) ) {
				$radios .= "<input type=\"radio\" id=\"{$name}-{$term->slug}\" name=\"{$name}\" value=\"{$term->slug}\"" . checked( $args[ 'selected' ], $term->slug, false ) . "><label for=\"{$name}-{$term->slug}\">{$term->name}</label><br />";
	// individual product attributes
	} else {
		foreach( $options as $option ) {
			$checked = sanitize_title( $args[ 'selected' ] ) === $args[ 'selected' ] ? checked( $args[ 'selected' ], sanitize_title( $option ), false ) : checked( $args[ 'selected' ], $option, false );
			$radios .= "<input type=\"radio\" id=\"{$name}-{$option}\" name=\"{$name}\" value=\"{$option}\" id=\"{$option}\" {$checked}><label for=\"{$name}-{$option}\">{$option}</label>";
	$radios .= '</div>';

	return $html . $radios;

Don’t know where to insert the code?

As you can see the code above gives us tons of space for customisation – we can display prices as part of radio buttons labels or even images.


if( ! in_array( $product->get_id(), array( 1, 15, 25 ) ) ) {
	return $html;
if( 'pa_color' !== $attribute ) {
	return $html;

And of course, the JavaScript part:

jQuery( function( $ ) {
	// on radio button change(click)
	$( document ).on( 'change', '.rudr-variation-radios input', function() {
		// for each checked radio button we reflect the same changes to select dropdowns
		$( '.rudr-variation-radios input:checked' ).each( function( index, element ) {
			const radio = $(element)
			const radioName = radio.attr( 'name' )
			const radioValue  = radio.attr( 'value' )
			$( 'select[name="' + radioName + '"]' ).val( radioValue ).trigger( 'change' );


Have any questions? Let me know in the comments.

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 X