DEV Community

Rock
Rock

Posted on

How to Build a Dynamic Product Variant Selector with Vanilla JavaScript

When building an e-commerce site, few things are as painful as managing product variants. Sizes, colors, materials, fits—especially for apparel like men’s shorts. One wrong dropdown and a customer buys a size 30 waist when they wanted a 34. Let’s walk through a clean, flexible solution using vanilla JavaScript and a little CSS that keeps your variant selector sane.

We’ll use a simple product data structure for our men’s shorts collection. Imagine a product with three attributes: size (S, M, L), color (Black, Navy), and fit (Slim, Relaxed). We need to generate all valid combinations, then let the user pick one, updating price and stock.


First, define your variants as an array of objects. Each object has an id, attributes, price, and inStock boolean.

const variants = [
  { id: 1, attributes: { size: "S", color: "Black", fit: "Slim" }, price: 29.99, inStock: true },
  { id: 2, attributes: { size: "M", color: "Black", fit: "Slim" }, price: 29.99, inStock: true },
  // ... more variants
];
Enter fullscreen mode Exit fullscreen mode

Now, we need to dynamically generate the option selectors. Loop through the unique keys (size, color, fit) and create a <select> for each. When a user changes any selector, we filter the variants to find the one matching all current selections.

function getUniqueOptions(variants, key) {
  return [...new Set(variants.map(v => v.attributes[key]))];
}

function updateVariant() {
  const selected = {};
  document.querySelectorAll('.variant-select').forEach(select => {
    selected[select.dataset.attr] = select.value;
  });
  const match = variants.find(v => 
    Object.keys(selected).every(key => v.attributes[key] === selected[key])
  );
  if (match) {
    document.getElementById('price').textContent = `$${match.price.toFixed(2)}`;
    document.getElementById('stock').textContent = match.inStock ? 'In Stock' : 'Out of Stock';
  }
}
Enter fullscreen mode Exit fullscreen mode

For the HTML, wrap each selector in a label:

<label>Size: <select class="variant-select" data-attr="size">...</select></label>
Enter fullscreen mode Exit fullscreen mode

This approach is lightweight, avoids heavy frameworks, and scales to any number of attributes. You can easily extend it to show images per color or disable out-of-stock options.

If you want a live example, I built this for a men’s shorts collection at Frishay where we have dozens of variants per product. The logic stays the same—just the data gets bigger.

Building your own variant picker gives you full control over UX and performance. No bloated plugins, just clean, maintainable code. Give it a try in your next project.

Top comments (1)

Collapse
 
frishay_ltd_a1987ef83aa1f profile image
Amelia

Great point! I've found that consistency matters more than intensity when building habits. What's one small change that made the biggest impact for you?