Products with variants (Size, Color, and more)

How to set up a single product that comes in multiple sizes, colors, or other options — each with its own price, inventory, SKU, and photo.

Products with variants

If you sell one thing that comes in multiple flavors — a t-shirt in three sizes and two colors, a rug in four dimensions, a candle in six scents — you don't need six separate products. You need one product with variants.

Simple vs. with variants

When you create a product you'll choose:

  • Simple — one price, one inventory count, one SKU. That's it. The product has one "default" variant under the hood but you never see it.
  • With variants — you define option groups ("Size", "Color") and their values ("S / M / L", "Red / Blue"). The system generates every combination and you set a price + inventory per combo.

You can switch from simple to with-variants anytime later — your default variant becomes one combination, and you add the rest.

The two vocabulary pieces

  • Option group — the axis of choice. "Size" is a group. "Color" is a group.
  • Option value — one choice on that axis. "Large" is a value of "Size". "#D87A3C" is a value of "Color" (with a hex color swatch).

Each option group has a value type:

  • Text — plain text labels ("Blue", "Vanilla", "8×10")
  • Color swatch — vendor-picked hex color renders as a round swatch
  • Image swatch — vendor-picked media asset renders as a thumbnail (great for fabric swatches, wood grains)
  • Size — ordered text (S/M/L auto-sorts correctly; 7/8/9/10 auto-sorts correctly)

Generating variants

Once your groups and values are set, hit Generate combinations. The system creates every combination:

  • 3 Sizes × 2 Colors = 6 variants
  • 4 Sizes × 3 Colors × 2 Materials = 24 variants

Generating is idempotent — if you run it again after adding a size, it only creates the NEW combinations. Your existing prices and inventory on the other combinations stay put.

If you remove an option value, variants that used it get deactivated (not deleted — you can undo by re-adding the value and running Generate again).

Per-variant fields

Each variant row has:

| Field | What it does | |-------|--------------| | Price | In dollars; required. Different from your product's base price — variants can cost more or less. | | Compare-at price | Struck-through "was $X" price on the product page. | | Inventory | Integer count. | | Inventory policy | Track (refuse to oversell), Oversell (accept orders below zero — you'll have to make or restock), Infinite (never-out-of-stock). | | SKU | Your internal code. Must be unique across your whole store. | | Weight | Grams — used to compute shipping rates later. | | Image | Pick any asset from your media library. If the shopper picks this variant on the product page, the main image swaps to this one. | | Active | Unchecked variants don't show on the product page. |

More robust than Shopify (yes, really)

Three places we do this better:

  1. Swatch images are separate from variant images. Shopify conflates them — your fabric-swatch thumbnail is the same file as the product hero on that variant. We let you pick them independently so the swatch can be a close-up while the hero is a product shot.
  2. Value-type is first-class. Shopify forces you to build color swatches with metafield hacks. Our color_swatch and image_swatch types render the picker UI correctly out of the box.
  3. Inventory policy per variant. Shopify is all-or-nothing at the variant level. We let each variant independently pick Track / Oversell / Infinite so your "Made to order" one-of-ones never block a sale while your in-stock staples still respect inventory.

When to split into separate products instead

Keep it as one product with variants when the base thing is the same (a mug in different colors). Split into separate products when the experience or story is materially different (a mug vs. a tumbler — even if both are ceramic).

If shoppers have to scroll past six paragraphs of prose to find the variant they want, that's a sign to split.