How to nest product variants such as "color > size" with only liquid?

New Member
1 0 0

My current theme was built under the assumption that variants would be size OR color, because that's all that was needed until now.

currently, all variants are flat, like "Sm, Md, Lg, XL", or "Black, White, Red"

However, if you added a product that has black and white, each with Sm, Md, Lg, XL my theme would give you this: "B Sm, W Sm, B Md, W Md, B Lg, W Lg, B XL, W XL"


I'd like to add the ability for user to select first a color, and then a size. the theme needs to update which sizes are available based on the color that has been selected.

i.e. Choice 1 (Black or white) -> Choice 2 (Sm, Md, Lg, XL)


basically, i think the logic should be: if the product has multiple colors, show a dropdown. once you have selected a dropdown, show the size radio buttons for variants that also match that color.

I've been reading the shopify cheat sheet but i can't see how to sort variants by specific options, or check those options to show more options.


here is how my code currently works:

{% unless product.has_only_default_variant %}
          <div class="shop__size">
              {%- assign current_variant = product.selected_or_first_available_variant -%}
              {% assign firstavailable = product.selected_or_first_available_variant.title %}
              {% for variant in product.variants %}
              {% if variant.title == "SMALL" %}{% assign sizelabel = "s" %}{% endif %}
              {% if variant.title == "MEDIUM" %}{% assign sizelabel = "m" %}{% endif %}
              {% if variant.title == "LARGE" %}{% assign sizelabel = "l" %}{% endif %}
              {% if variant.title == "EXTRA-LARGE" %}{% assign sizelabel = "xl" %}{% endif %}
              {% if variant.title != "SMALL" and variant.title != "MEDIUM" and variant.title != "LARGE" and variant.title != "EXTRA-LARGE" %}{% assign thisVariant =  variant.title | truncate: 1, "" %}{% assign sizelabel = thisVariant %}{% endif %}
                  class="product-form__variants no-js js-cursor-minus"
                  {% if variant.available == false %}disabled{% endif %}
                  {% if variant.title == firstavailable %} checked{% endif %}
                  <label for="ProductSelect-{{variant.title}}" class="shop__size_button js-cursor-minus {% unless variant.available %}scratched{% endunless %}" {% if variant.available == false %}disabled{% endif %}>{{ sizelabel }}</label>
              {% endfor %}
          {% else %}
          <div class="shop__size">
            <li {% unless product.available %}class="scratched"{% endunless %}>O/S</li>
          {% endunless %}