Product pages - Add color swatches to products

Highlighted
Tourist
4 0 0

Hi, 

I am using the debut theme too, but I could not find where to add the code, could you help?

{% if product.available and product.variants.size > 1 %}
  {% render 'swatch' with 'Color' as swatch %}
{% endif %}

 

0 Likes
Highlighted
Tourist
7 0 1

Hi,

 

If you scroll down the theme.liquid you'll see this:

// BEGIN SWATCHES

 

// END SWATCHES

 

Place it inside. I hope this works for you

0 Likes
Highlighted
Shopify Partner
8 1 0

My images no longer change based on the variant selected. Is there a way correct this?

0 Likes
Highlighted
New Member
1 0 0

In sections/product-template.liquid

Before this line (~150):

{% for option in product.options_with_values %}
0 Likes
Highlighted
New Member
1 0 2

I had to modify the code a bit to work with Debut (v16.5.6) but to get things working, I added the callback script to the theme.js file (in Assets)

Under the following code in theme.js:

 

    _updateAddToCart: function(evt) {
      var variant = evt.variant;

 

I added the following code:

 

// Swatch code when variant updates
var form = $(this.selectors.productForm, this.container)
      for (var i=0,length=variant.options.length; i<length; i++) {
        var radioButton = form.find('.swatch[data-option-index="' + i + '"] :radio[value="' + variant.options[i] +'"]');
        if (radioButton.size()) {
          radioButton.get(0).checked = true;
        }
      }

 

2. I also got rid of all the inline jQuery script in the swatch.liquid file and put it at the bottom of the theme.js file instead:

 

// Swatches
$(function() {
  $('.swatch :radio').change(function() {
    var optionIndex = $(this).closest('.swatch').attr('data-option-index');
    var optionValue = $(this).val();
    $(this)
    .closest('form')
    .find('.single-option-selector')
    .eq(optionIndex)
    .val(optionValue)
    .trigger('change');
  });
});

$(window).load(function() { $('.selector-wrapper:eq({{ option_index }})').hide(); });

// End of Swatches Code

 

 

3. Then I modified the swatch.liquid to capture the first available variant, since it seemed to check/select the very first variant on page load. I changed it to only check the first available variant (since that's typically the variant that is selected on debut by default)

Here is the updated swatch.liquid with variant capture code + removed inline jquery:

 

{% assign file_extension = 'png' %}
{% if swatch == blank %}
<div class="swatch error">
  <p>You must include the snippet swatch.liquid with the name of a product option.</p> 
  <p>Use: <code>{% raw %}{% include 'swatch' with 'name of your product option here' %}{% endraw %}</code></p>
  <p>Example: <code>{% raw %}{% include 'swatch' with 'Color' %}{% endraw %}</code></p>
</div>
{% else %}
{% assign found_option = false %}
{% assign is_color = false %}
{% assign option_index = 0 %}
{% for option in product.options %}
  {% if option == swatch %}
    {% assign found_option = true %}
    {% assign option_index = forloop.index0 %}
    <style>
      label[for="product-select-option-{{ option_index }}"] { display: none; }
      #product-select-option-{{ option_index }} { display: none; }
      #product-select-option-{{ option_index }} + .custom-style-select-box { display: none !important; }
    </style>  
    {% assign downcased_option = swatch | downcase %}
    {% if downcased_option contains 'color' or downcased_option contains 'colour' %}
      {% assign is_color = true %}
    {% endif %}
  {% endif %}
{% endfor %}
{% unless found_option %}
<div class="swatch error">
  <p>You included the snippet swatch.liquid with the name of a product option — <code>'{{ swatch }}'</code> — that does not belong to your product.</p>
  <p>Use <code>{% raw %}{% include 'swatch' with 'name of your product option here' %}{% endraw %}</code></p>
  <p>Example: <code>{% raw %}{% include 'swatch' with 'Color' %}{% endraw %}</code></p>
  <p><strong>This is case-sensitive!</strong> Do not put in <code>'color'</code> if your product option name is <code>'Color'</code>.</p>
</div>
{% else %}
<div class="swatch clearfix" data-option-index="{{ option_index }}">
  <div class="header">{{ swatch }}</div>
  {% assign values = '' %}  
{% comment %} Capture first available variant {% endcomment %}
  {% for variant in product.variants %}  
    {% if variant.available %}
      {% assign firstAvailable = forloop.index0 %}
    {% break %}
    {% endif %}
  {% endfor %}   
  {% for variant in product.variants %}      
    {% assign value = variant.options[option_index] %}
    {% unless values contains value %}
      {% assign values = values | join: ',' %}
      {% assign values = values | append: ',' | append: value %} 
      {% assign values = values | split: ',' %}
      <div data-value="{{ value | escape }}" class="swatch-element {% if is_color %}color {% endif %}{{ value | handle }} {% if variant.available %}available{% else %}soldout{% endif %}">
        {% if is_color %}
        <div class="tooltip">{{ value }}</div>
        {% endif %}
        <input id="swatch-{{ option_index }}-{{ value | handle }}" type="radio" name="option-{{ option_index }}" value="{{ value | escape }}"{% if forloop.index0 == firstAvailable %} checked {% endif %} {% unless variant.available %}disabled{% endunless %} />
        {% if is_color %}
        <label for="swatch-{{ option_index }}-{{ value | handle }}" style="background-color: {{ value | split: ' ' | last | handle }}; background-image: url({{ value | handle | append: '.' | append: file_extension | asset_url }})">
          <img class="crossed-out" src="{{ 'soldout.png' | asset_url }}" />
        </label>
        {% else %}
        <label for="swatch-{{ option_index }}-{{ value | handle }}">
          {{ value }}
          <img class="crossed-out" src="{{ 'soldout.png' | asset_url }}" />
        </label>
        {% endif %}
      </div>
    {% endunless %}
  {% endfor %}
</div>
{% endunless %}
{% endif %}

 

 

Once I had completed this and added the swatch images, everything worked perfectly.

Some tips:

  • If your option value contains a space or symbol, then replace the symbol with "-" in the swatch image filename. For example: "Red & Yellow" will turn out to be "red-yellow", "A 1 ! B 2 C" will turn out to be "a-1-b-2-c"
  • If you don't want swatches to impact all of your products, then make new product.liquid and product-template.liquid files (something like, product-swatches.liquid and product-template-swatches.liquid) - then you can assign the template suffix to the new swatches template instead of the default template from product admin page. Simply assign the new template to products you want the swatches on and leave the other products on the default template.
  • If you are getting any errors with variants not updating or wrong variants being added to the cart, check for any errors via the chrome console. Most likely it's due to some jquery scripts not executing since jquery doesn't work when run outside of theme.js (for debut)

Hope that's helpful for some!

2 Likes
Highlighted
Excursionist
29 2 5

@mayasplaceny wrote:

So I did the first step of adding the a new snippet no problem. But the second part of pasting this code 

{% if product.available and product.variants.size > 1 %}
{% render 'swatch' for product.options as swatch %}
{% endif %}

I'm not sure where to paste that. I am working with the Supply theme any help would be appreciated. TIA 


In Supply theme, open Sections > product-template.liquid and look for <select name="id" (Hint: Press Ctrl-F to open the Find box.). Paste the code snippet after the closing </select> tag.


@SugarCubeProduc wrote:

Thank you for this.

I've just tried to install it on the Supply theme, which also doesn't have the callback code anywhere.

Also swatch.liquid makes a LOT of inline script calls, which set everything as in stock, even when it isn't, so the soldout image never gets used.


In Supply theme, the callback function is named productVariantCallback instead of selectCallback. You can find this function in theme.js.liquid and you may insert the code as described in the body of the function.

You must also make the following change to the first line of the function. This line:

productVariantCallback: function(variant) {

must be changed to:

productVariantCallback: function(variant, selector) {

So your callback function is something like this:

    productVariantCallback: function(variant, selector) {
      var self = this;

// ********* PASTE THE SWATCHES CODE HERE! ************

      if (variant) {
        //  Only change unit price for main product
...

Then continue with the remaining instructions, but when you need to paste the CSS file, it should be done at the end of theme.scss.liquid instead of the mentioned files like styles.css.liquid, style.css.liquid or shop.css.liquid (Note: Do not replace the existing content. Just go to the very end and paste in a new line.)

Hint: For those using other themes, if the above doesn't work, feel free to reply and let me know. If you have the technical skills needed, you can easily investigate this through the Developer Tools of your browser. In short, use the Debugger to create and activate a breakpoint at the first line of the change event of your currently existing variant drop-down. Then change the variant on the page, hit the breakpoint and step into the function. Go through the code execution call by call using "Step Into" until you arrive at some sort of a callback function that looks similar to selectCallback.

I'll test the soldout image problem and update the fix later. Feel free to reply if you need any help. 

If my reply helped you, please give it a Like and mark it as Accepted Solution.
You're welcome, and thank you too! :)
Do you want me to fix your theme code? PM me.
0 Likes
Highlighted
Excursionist
29 2 5

Additional changes for implementing this in Supply theme (and similarly structured themes):

While all of the above changes would make this solution work at the bare minimum, you'll have some inconsistent experiences:

  1. The drop-down selector still appears when the page is loading. You'll see both the drop-down and the buttons for a second or two, then the drop-down disappears.
  2. The buttons don't appear when the entire product (all variants) is out of stock, or when there's only one variant registered on the product. In both these cases, the drop-down is shown instead.
  3. The changes are not reflected in the "Featured product" section of the Home page. If you use this section, you'll notice that it always has the drop-down.

Fix for #1:

Go to Assets > theme.scss.liquid and add this block in a new line at the very end of the file. (Tip for pro users: You could insert it anywhere you see fit, like the "Product details" section.)

 

.selector-wrapper {
  display: none;
}

 

Explanation: The original solution dynamically hides the drop-down when it shows the buttons. But since it takes a while for the JavaScript to execute and hide the drop-down, you see both for a short time. In this fix, the drop-down is permanently hidden by a CSS rule.

NOTE: This will permanently hide the drop-down. Therefore you must apply all the next fixes too to make sure the buttons always show.

Fix for #2:

In Sections > product-template.liquid change the following line of the code you pasted from:

 

      {% if product.available and product.variants.size > 1 %}

 

to:

 

      {% if product.variants.size > 0 %}

 

Explanation: The original code would only show the buttons when the product is "in stock" and has at least two variants. In this fix, we force the buttons to show up regardless of whether the product is "in stock" or "out of stock", and if it has at least one variant.

Fix for #3:

In Sections > featured-product.liquid you need to do something similar to what you did in product-template.liquid. Find the portion <select name="id" and insert the code below after the closing "</select>" tag.

 

      {% if product.variants.size > 0 %}
        {% render 'swatch' for product.options as swatch, product: product %}
      {% endif %}

 

Explanation: When you add the "Featured product" section in the Home page (under theme customization), this file is used to display the featured product.

Note: There's a small change from the original code in product-template.liquid, where product: product is added to manually pass the product object to the swatch snippet. This happens automatically in product-template but doesn't happen automatically in featured-product. Hence the change.

That's it! Your website will now be fully consistent in showing the buttons (or color swatches*) anywhere and everywhere. If you come across some other bug, just post a reply and I'd be happy to look into it.

* I didn't say color swatches wherever I said buttons as I'm using this solution in my site for buttons only. But everything will work exactly the same for color swatches as well.

Further Enhancement (optional):

If you're using this solutions for buttons, or you want to style the buttons and tool-tips better than the boring grey colors, simply edit the swatch CSS you had pasted in theme.scss.liquid. You can hard-code the hex colors, but since this is a Liquid file, you can also pull the colors from your customization using variables. That is what I have done here:

 

.swatch label {
...
  /* Background color */
  background-color:$colorBody;
  color:$colorTextBody;
  /* Styling text */
...
}
...

.swatch input:checked + label {
...
  background-color:$colorTextBody;
  color:$colorBody;
} 
...

.swatch .tooltip {
  text-align:center;
  background:$colorAccent;
  color:#fff;
...
}
...

.swatch .tooltip:after {
...
  border-top:solid $colorAccent 10px;
...
}

 

PS: @SugarCubeProduc The soldout image is working fine for me. I couldn't reproduce the problem you mentioned.

If my reply helped you, please give it a Like and mark it as Accepted Solution.
You're welcome, and thank you too! :)
Do you want me to fix your theme code? PM me.
1 Like
Highlighted
New Member
2 0 0

Dear Madame, Sir,
We have done 5 times the tutorial and it still does not work.
First issue : We cannot find any selectCallback function, can you help us please ?
Can you confirm it is still working with the current Debut version ?

0 Likes
Highlighted
New Member
2 0 0

Thank you so much for the solution. It helps a lot!

 

Do you know how to make the colour variants show in circle shape?   

0 Likes
Highlighted
New Member
1 0 0

Hi, I'm here through Google. I see most of here could not implement this on debut theme. It is really disappointing. However, if anyone needs help to implement this swatch on their debut theme please contact through my sky.pe shamim.hossain.jakir 

I'll make happen this perfectly.

0 Likes