'Reorder attribute dropdown terms in Woocommerce single variable products

In the Woocommerce single variable product pages, I would like to change the order of the sizing options on the related drop-down menu.

Actually It is like this (In alphabetical order):
- L
- M
- XL

I would like to have it like this (in logical size order):
- M
- L
- XL

How can I reorder the sizing options drop-down menu in single variable product pages?

Any help is appreciated.



Solution 1:[1]

This is just about settings in the Attributes section for your "Size" product attribute.

1) You need to click on "configure terms":

enter image description here

2) You are now on the list of the terms. You can reorder terms by drag and drop on the icon located in the right:

enter image description here

3) Then you will get the following

enter image description here

The dropdown "Size" options on related variable products will be in the correct order now.

Solution 2:[2]

Sorting attributes in Product -> Attributes can be extremely inconvenient, especially if you have a lot of attributes. The problem can be solved through the woocommerce_dropdown_variation_attribute_options_html filter.

To make drag-and-drop sorting work on the product page, try adding to your functions.php the following code:

add_filter('woocommerce_dropdown_variation_attribute_options_html', 'wc_dropdown_variation_attribute_options_sorted', 20, 2);
function wc_dropdown_variation_attribute_options_sorted( $html, $args ) {
$args = wp_parse_args(
    apply_filters( 'woocommerce_dropdown_variation_attribute_options_args', $args ),
    array(
        'options'          => false,
        'attribute'        => false,
        'product'          => false,
        'selected'         => false,
        'name'             => '',
        'id'               => '',
        'class'            => '',
        'show_option_none' => __( 'Choose an option', 'woocommerce' ),
    )
);

// Get selected value.
if ( false === $args['selected'] && $args['attribute'] && $args['product'] instanceof WC_Product ) {
    $selected_key = 'attribute_' . sanitize_title( $args['attribute'] );
    // phpcs:disable WordPress.Security.NonceVerification.Recommended
    $args['selected'] = isset( $_REQUEST[ $selected_key ] ) ? wc_clean( wp_unslash( $_REQUEST[ $selected_key ] ) ) : $args['product']->get_variation_default_attribute( $args['attribute'] );
    // phpcs:enable WordPress.Security.NonceVerification.Recommended
}

$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'];
$show_option_none      = (bool) $args['show_option_none'];
$show_option_none_text = $args['show_option_none'] ? $args['show_option_none'] : __( 'Choose an option', 'woocommerce' ); // We'll do our best to hide the placeholder, but we'll need to show something when resetting options.

if ( empty( $options ) && ! empty( $product ) && ! empty( $attribute ) ) {
    $attributes = $product->get_variation_attributes();
    $options    = $attributes[ $attribute ];
}

$html  = '<select id="' . esc_attr( $id ) . '" class="' . esc_attr( $class ) . '" name="' . esc_attr( $name ) . '" data-attribute_name="attribute_' . esc_attr( sanitize_title( $attribute ) ) . '" data-show_option_none="' . ( $show_option_none ? 'yes' : 'no' ) . '">';
$html .= '<option value="">' . esc_html( $show_option_none_text ) . '</option>';

if ( ! empty( $options ) ) {
    if ( $product && taxonomy_exists( $attribute ) ) {
        // Get terms if this is a taxonomy - ordered. We need the names too.
        $terms = wc_get_product_terms(
            $product->get_id(),
            $attribute,
            array(
                'fields' => 'all',
            )
        );
        
        //sorting starts here
        foreach($terms as $key => $term) {
            $i = 0;
            foreach($product->get_available_variations() as $variation) {
                $i++;
                if ($term->slug == $variation['attributes'][$name]) {
                    $key = $i - 1;
                    unset($terms[$key]);
                    $terms[$key] = $term;
                }
            }
        }

        ksort($terms);

        foreach ( $terms as $term ) {
            if ( in_array( $term->slug, $options, true ) ) {
                $html .= '<option value="' . esc_attr( $term->slug ) . '" ' . selected( sanitize_title( $args['selected'] ), $term->slug, false ) . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name, $term, $attribute, $product ) ) . '</option>';
            }
        }
    } else {
        foreach ( $options as $option ) {
            // This handles < 2.4.0 bw compatibility where text attributes were not sanitized.
            $selected = sanitize_title( $args['selected'] ) === $args['selected'] ? selected( $args['selected'], sanitize_title( $option ), false ) : selected( $args['selected'], $option, false );
            $html    .= '<option value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option, null, $attribute, $product ) ) . '</option>';
        }
    }
}

return $html .= '</select>';

}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 LoicTheAztec
Solution 2 Qzya Qznetsov