
How to Set Up Product Variations in WooCommerce?
A T-shirt comes in four sizes and three colors. Listing it as twelve separate products clutters your shop, splits reviews across listings, and makes customers hunt for their size. Listing it as one simple product with a note saying "tell us your size in the order notes" guarantees mistakes. WooCommerce solves this with variable products: one product page, a dropdown for each option, and a separate price, SKU, stock level, and image for every combination.
Variations are also where many store owners get stuck. The Variations tab is empty, the dropdown shows "Choose an option" but nothing happens, or prices display as a confusing range. Almost every one of these problems comes from the same few setup steps done out of order.
This article covers setting up WooCommerce product variations from start to finish: the difference between global and custom attributes, creating a variable product, generating variations, setting prices, stock, shipping, and images per variation, using bulk actions, choosing default selections, and front-end tweaks and programmatic creation with PHP for larger catalogs.
How Variable Products Work
A variable product has three layers:
- Attributes describe a dimension the product varies along, such as Size or Color.
- Terms (or values) are the options within an attribute, such as Small, Medium, and Large.
- Variations are the purchasable combinations, such as "Large, Blue," each with its own price, SKU, stock, and image.
The parent variable product holds the shared information: title, description, categories, and gallery. Customers pick values from dropdowns, and WooCommerce swaps in the matching variation's price, stock status, and image.
| Concept | Example | Where it is managed |
|---|---|---|
| Global attribute | Size | Products → Attributes |
| Terms | Small, Medium, Large | Products → Attributes → Configure terms |
| Custom attribute | Engraving style | On a single product only |
| Variation | Size Medium, Color Blue | Product data → Variations |
If you are still deciding whether WooCommerce is the right platform for your store, start with how to use WordPress for e-commerce.
Global vs Custom Attributes
Before creating the product, decide how to define the attributes.
Global attributes are created once under Products → Attributes and reused across many products. They are stored as taxonomies (named pa_size, pa_color, and so on), which means:
- Customers can filter the shop by them with filter blocks.
- Term names are consistent across products, so "Medium" is never spelled "Med" on one shirt.
- You can rename a term once and it updates everywhere.
Custom attributes are created inside a single product. They are quick for one-off options but cannot be used for filtering and do not stay consistent across products.
The rule of thumb: if more than one product uses the attribute, or customers might filter by it, make it global.
Creating a Global Attribute
- Go to Products → Attributes.
- Enter a Name, such as Size. The slug is filled in automatically.
- Leave Enable archives? unchecked unless you want a public archive page per term.
- Set Default sort order. Choose Custom ordering if you want to arrange sizes logically (S, M, L, XL) instead of alphabetically.
- Click Add attribute.
- In the attributes table, click Configure terms next to Size.
- Add each term: Small, Medium, Large, Extra Large.
Repeat for Color with Red, Blue, and Black.
Creating a Variable Product
Open the product editor. These steps use the classic product editor, which is WooCommerce's default product screen. If you enabled the experimental block-based product editor on your store, the same concepts apply but the screen layout and labels differ.
Step 1: Set the Product Type
- Go to Products → Add New Product.
- Enter the product name, description, and short description.
- In the Product data panel, change the dropdown from Simple product to Variable product.
The General tab's price fields disappear. In a variable product, prices belong to the variations, not the parent.
Step 2: Add Attributes
- Click the Attributes tab in the Product data panel.
- Use the dropdown at the top to add an existing global attribute, such as Size.
- In the value box, select the terms this product uses, or click Select all.
- Tick Used for variations. This is the step most often missed. Without it, the attribute shows only as product information and never as a dropdown.
- Optionally tick Visible on the product page to list the attribute in the Additional information tab.
- Repeat for Color.
- Click Save attributes.
To add a custom attribute instead, click Add new, enter a name such as Engraving, and type the values separated by a vertical bar: Script | Block | None.
Step 3: Generate Variations
- Click the Variations tab.
- Choose how to create variations:
- Generate variations creates every combination of the attribute values marked for variations. Four sizes and three colors produce twelve variations.
- Add manually creates a single variation where you pick each value yourself. Use this when only some combinations exist, for example when Extra Large comes only in Black.
- Confirm the prompt.
WooCommerce limits how many variations it generates in one run, so very large combinations may need generating more than once. If you find yourself with hundreds of variations on one product, reconsider the structure; a product with many independent options is often better served by separate products or a product add-ons extension.
Step 4: Fill In Each Variation
Click a variation's row to expand it. The fields you will use most:
| Field | What it does |
|---|---|
| Image | Shown when the customer selects this variation |
| SKU | Unique stock-keeping unit; leave empty to inherit the parent SKU |
| GTIN, UPC, EAN, or ISBN | Global product identifier for marketplaces and search |
| Enabled | Unchecked variations cannot be purchased |
| Downloadable | Adds download files, limits, and expiry |
| Virtual | Removes weight, dimensions, and shipping class |
| Manage stock? | Tracks a stock quantity for this variation alone |
| Regular price | Required. A variation without a price cannot be bought |
| Sale price | Optional discounted price, with optional schedule |
| Weight and Dimensions | Used by shipping calculations; inherit from parent if empty |
| Shipping class | Lets heavy or bulky variations cost more to ship |
| Tax class | Override the parent's tax class |
| Description | Extra text shown when this variation is selected |
The Regular price is the critical one. A variation without a price is treated as unavailable, and if none have prices, the product page shows no add-to-cart option at all.
Click Save changes at the bottom of the Variations tab, then Update or Publish the product.
Step 5: Set Default Form Values
At the top of the Variations tab, the Default Form Values dropdowns choose which options are preselected on the product page. Leaving them on "No default" forces customers to choose, which is usually right for sizes. Setting a default color can make the product page look complete on first load with the right image showing.
Using Bulk Actions
Editing twelve variations one by one is tedious; editing sixty is impractical. The Bulk actions dropdown at the top of the Variations tab applies a change to every variation at once:
- Pricing: set regular prices, set sale prices, increase or decrease prices by a fixed amount or percentage, and set scheduled sale dates.
- Inventory: toggle Manage stock, set stock quantity, change stock status, and set a low stock threshold.
- Shipping: set length, width, height, and weight.
- Status: toggle Enabled, Downloadable, and Virtual.
- Delete all variations.
A practical workflow for a shirt that costs more in larger sizes:
- Use Set regular prices to give every variation the base price, such as 20.
- Expand the Extra Large variations and change their price to 22 individually.
- Use Set stock under inventory to give every variation 10 units, then adjust the few that differ.
Changes made through bulk actions save immediately, but still click Save changes after individual edits.
Assigning Shipping Classes to Variations
If the large sizes of a product are heavier or ship in a bigger box, give those variations their own shipping class:
- Create the class under WooCommerce → Settings → Shipping → Classes with Add shipping class.
- In each heavy variation, choose that class from the Shipping class dropdown. "Same as parent" uses the parent product's class.
- Add a cost for the class in your Flat rate shipping method.
How classes, zones, and flat rate formulas fit together is covered in how to configure WooCommerce shipping zones and rates.
Front-End Tweaks with Code
The following snippets go in a site-specific plugin or a snippets plugin, not in a theme's functions.php. The options are compared in how to add custom code snippets to WordPress safely.
Show "From" Instead of a Price Range
By default, a variable product with different prices shows a range such as "$20.00 – $22.00." Many stores prefer "From $20.00":
// wp-content/plugins/store-tweaks/store-tweaks.php
add_filter( 'woocommerce_variable_price_html', 'wsm_variable_price_from', 10, 2 );
function wsm_variable_price_from( $price_html, $product ) {
$min_price = $product->get_variation_price( 'min', true );
$max_price = $product->get_variation_price( 'max', true );
if ( $min_price === $max_price ) {
return $price_html; // All variations cost the same; keep the default.
}
return sprintf(
/* translators: %s: lowest variation price */
esc_html__( 'From %s', 'store-tweaks' ),
wc_price( $min_price )
);
}
The second argument true returns the price as displayed, including or excluding tax according to your store settings.
Change the "Choose an option" Text
// wp-content/plugins/store-tweaks/store-tweaks.php
add_filter( 'woocommerce_dropdown_variation_attribute_options_args', 'wsm_variation_placeholder' );
function wsm_variation_placeholder( $args ) {
$label = wc_attribute_label( $args['attribute'], $args['product'] );
/* translators: %s: attribute name, for example Size */
$args['show_option_none'] = sprintf( __( 'Select %s', 'store-tweaks' ), strtolower( $label ) );
return $args;
}
The dropdown for Size now reads "Select size," and Color reads "Select color."
Grey Out Out-of-Stock Combinations
By default, out-of-stock variations remain selectable and show an "Out of stock" message after selection. To make them unavailable in the dropdowns:
// wp-content/plugins/store-tweaks/store-tweaks.php
add_filter( 'woocommerce_variation_is_active', 'wsm_disable_out_of_stock_variations', 10, 2 );
function wsm_disable_out_of_stock_variations( $is_active, $variation ) {
return $variation->is_in_stock() ? $is_active : false;
}
Products with Many Variations
When a product has more than 30 variations, WooCommerce stops sending all variation data with the page and instead looks up each selection over AJAX. As a result, the dropdowns no longer hide impossible combinations in advance. You can raise the threshold:
// wp-content/plugins/store-tweaks/store-tweaks.php
add_filter( 'woocommerce_ajax_variation_threshold', fn() => 60 );
Raising it increases the page size, because data for every variation is embedded in the HTML. Test the product page's load time before and after.
Creating Variations Programmatically
When you import a catalog from a supplier or need dozens of similar products, creating variations by hand does not scale. The WooCommerce CRUD classes WC_Product_Variable, WC_Product_Attribute, and WC_Product_Variation let you do it in PHP.
This script creates a variable T-shirt with a custom Size attribute and three priced, stock-managed variations:
<?php
// scripts/create-variable-product.php
// Run with: wp eval-file scripts/create-variable-product.php
if ( ! class_exists( 'WooCommerce' ) ) {
WP_CLI::error( 'WooCommerce must be active.' );
}
$product = new WC_Product_Variable();
$product->set_name( 'Classic Cotton T-Shirt' );
$product->set_status( 'publish' );
$product->set_description( 'A soft, heavyweight cotton tee.' );
$size = new WC_Product_Attribute();
$size->set_name( 'Size' ); // Custom (product-level) attribute.
$size->set_options( array( 'Small', 'Medium', 'Large' ) );
$size->set_visible( true );
$size->set_variation( true ); // Equivalent to "Used for variations".
$product->set_attributes( array( $size ) );
$product_id = $product->save();
$prices = array(
'Small' => '20.00',
'Medium' => '20.00',
'Large' => '22.00',
);
foreach ( $prices as $value => $price ) {
$variation = new WC_Product_Variation();
$variation->set_parent_id( $product_id );
$variation->set_attributes( array( 'size' => $value ) ); // Key is the sanitized attribute name.
$variation->set_regular_price( $price );
$variation->set_sku( 'TEE-' . strtoupper( $value ) );
$variation->set_manage_stock( true );
$variation->set_stock_quantity( 10 );
$variation->save();
}
WP_CLI::success( "Created variable product {$product_id}." );
Two details matter:
- Variation attribute keys. For a custom attribute, the key is the sanitized attribute name, so "Size" becomes
size, and the value is the option text as written, such asMedium. - Global attributes are different. For a global attribute, call
$attribute->set_id( wc_attribute_taxonomy_id_by_name( 'pa_size' ) ),set_name( 'pa_size' ), and pass term IDs toset_options(). The variation's key is thenpa_sizeand its value is the term slug, such asmedium.
Run the script with WP-CLI's eval-file command, which loads WordPress and WooCommerce first. For large catalogs, the built-in product CSV importer is also an option; it supports variable products and variations through parent and attribute columns.
Common Problems and Fixes
- The Variations tab says to add attributes first. No attribute is marked Used for variations. Go to the Attributes tab, tick the box, and click Save attributes.
- The product page shows "This product is currently out of stock and unavailable." Every variation is missing a price, disabled, or out of stock. Open the variations and add a Regular price.
- Dropdowns show but Add to cart stays greyed out. The selected combination does not exist as a variation, or that variation has no price. Generate missing variations or add them manually.
- A new attribute value does not appear in the dropdown. You added the term to the attribute, but not to this product. Add the value in the product's Attributes tab, then create a variation for it.
- Variation images do not change the main image. The theme overrides WooCommerce's gallery scripts. Test with a default theme such as Storefront or Twenty Twenty-Five to confirm, then contact the theme author.
- Impossible combinations are still selectable. The product has more variations than the AJAX threshold. Raise
woocommerce_ajax_variation_thresholdor simplify the product. - Prices show incorrectly after import. Variation prices are cached in transients. Clear them under WooCommerce → Status → Tools with the clear transients option.
WooCommerce Variations FAQ
An attribute is a property such as Size or Color, with values like Small or Blue. A variation is a specific purchasable combination of those values, such as Large and Blue, with its own price, SKU, stock, and image.
Use global attributes, created under Products then Attributes, when several products share the same options or when customers should be able to filter by them. Use custom attributes for one-off options that only apply to a single product.
Usually because the variations have no regular price, are disabled, or have zero stock. Every variation needs a regular price to be purchasable, and at least one must be enabled and in stock.
There is no strict maximum, but generation runs in batches and products with more than 30 variations switch to loading variation data over AJAX. Products with hundreds of variations become slow to edit and load, so consider product add-ons or separate products instead.
Yes. Assign a shipping class to the variation, then set a cost for that class in your Flat rate shipping method. Variations can also have their own weight and dimensions for carrier-calculated rates.
Yes. The built-in WooCommerce product importer supports variable products. Each variation is a row that references its parent product, with attribute columns holding the variation values.
Conclusion
Variable products let one listing handle every size, color, and option combination while tracking price, stock, and shipping for each. The setup order is what matters: create global attributes and their terms, set the product type to Variable product, add the attributes with Used for variations checked, generate or add variations, and give every variation a regular price.
From there, bulk actions keep large products manageable, shipping classes handle heavier options, and a few small filters improve the front end with "From" pricing, clearer dropdown labels, and unavailable out-of-stock combinations. For catalogs that grow beyond hand editing, the WooCommerce CRUD classes and the CSV importer create the same structure automatically.
Here are some useful references for going deeper on WooCommerce variations:
- WooCommerce Docs: Variable Product — the official step-by-step guide to attributes and variations.
- WooCommerce Docs: Managing Product Taxonomies — categories, tags, and global attributes.
- WooCommerce Docs: Product Shipping Classes — assigning classes to products and variations.
- WooCommerce Docs: Product CSV Importer and Exporter — importing variable products in bulk.
- WooCommerce Developer Docs: WooCommerce Code Reference — the WC_Product_Variable and WC_Product_Variation classes.


