How To Add Color Swatches [Dawn 13.0.1]

Shopify has been adding some cool new features this year, like letting you show product colors with swatches on the product page. This feature is supposed to be available to everyone by now, but it seems like it’s still under wraps. We hear you! That’s why we put together this guide to help you add color swatches to your store, even if you’re on theme version 13.0.1.

Step 1: Add code in settings_schema.json

Add the following code in settings_schema.json

{
    "name": "Color Swatches by WebSensePro",
    "settings": [
      {
        "type": "paragraph",
        "content": "Support WebSensePro by [Subscribing our Channel](https:\/\/youtube.com\/@websensepro?sub_confirmation=1)"
      },      
      {
        "type": "text",
        "id": "optionName",
        "label": "Swatch option name",
        "default": "Color",
        "info": "Make sure capitalization is same as variant for e.g Color not color "
      },
      {
        "type": "paragraph",
        "content": "If your store is in different languages, type in all the different words and separate them with commas. For example: Color, Colour, Couleur"
      },
      {
        "type": "select",
        "id": "swatchType",
        "label": "Swatch type",
        "options": [
          {
            "value": "color",
            "label": "Color"
          },
          {
            "value": "variantImage",
            "label": "Variant image"
          }
        ],
        "default": "color"
      },
      {
        "type": "textarea",
        "id": "swatchColors",
        "label": "Colors",
        "placeholder": "Red:#ff0000\nGreen:#00ff00\nBlue:#0000ff",
        "default": "Black:#000000\nWhite:#f5f5f5\nBlue:#005eff\nRed:#c9002c\nPink:#ffd5e6\nBrown:#a2896b\nOlive:#808000\nGreenRed:#008000#c9002c\nGreenRedBlue:#008000#c9002c#005eff",
        "info": "One rule per line. Example: Blue:#005eff\n2 Color Swatch Example: GreenRed:#008000#c9002c\n3 Color Swatch Example: GreenRedBlue:#008000#c9002c#005eff"
      },
      {
        "type": "paragraph",
        "content": "You can also add [image files](\/admin\/content\/files?selectedView=all&media_type=Image) instead of using colors, in lowercase with spaces replaced by hyphens. Example: Green kaki: green-kaki.png"
      },
      {
        "type": "select",
        "id": "swatchStyle",
        "label": "Swatch style",
        "options": [
          {
            "value": "round",
            "label": "Round"
          },
          {
            "value": "square",
            "label": "Square"
          },
          {
            "value":"square-round-corners",
            "label":"Square round corners"
          },
          {
            "value": "portrait",
            "label": "Portrait"
          }
        ],
        "default": "round",
        "info":"Portrait mode is only available for the variant image type."
      },
      {
        "type": "range",
        "id": "swatchSize",
        "min": 20,
        "max": 120,
        "step": 2,
        "unit": "px",
        "label": "Swatch size",
        "default": 40
      }
    ]
  },

Step 2: Replace Code in product-variant-picker

Please replace the code on line 52 of the file named “product-variant-picker.liquid”:

<fieldset class="js product-form__input product-form__input--pill">
          <legend class="form__label">{{ option.name }}</legend>
          {% render 'product-variant-options',
            product: product,
            option: option,
            block: block,
            picker_type: picker_type
          %}
        </fieldset>

With the following code:

<fieldset class="js product-form__input product-form__input--pill">
            {%- liquid
                assign optionNames = settings.optionName | split:","
                assign useColor = false 
                for optionColor in optionNames 
                  if optionColor == option.name 
                      assign useColor = true 
                      break
                  endif 
                endfor
            -%}
          {%- if useColor -%}
             <legend class="form__label ">{{ option.name }}:<span id="selected-{{ option.name }}"> {{ option.selected_value }}</span></legend>
              {% render 'color-option', product: product, option: option, block: block %}
              {%- else -%}
            <legend class="form__label">{{ option.name }}</legend>
            {% render 'product-variant-options', product: product, option: option, block: block, picker_type: picker_type %}
          {%- endif -%}
          </fieldset>

Step 3: Create A New Snippet File

Create new snippet file color-option.liquid

{% comment %}
  Renders product variant options

  Accepts:
  - product: {Object} product object.
  - option: {Object} current product_option object.
  - block: {Object} block object.


  Usage:
  {% render 'product-variant-options',
    product: product,
    option: option,
    block: block
  %}
{% endcomment %}
{%- liquid
  assign variants_available_arr = product.variants | map: 'available'
  assign variants_option1_arr = product.variants | map: 'option1'
  assign variants_option2_arr = product.variants | map: 'option2'
  assign variants_option3_arr = product.variants | map: 'option3'

  assign product_form_id = 'product-form-' | append: section.id

  assign swatchType = settings.swatchType
  assign swatchStyle = settings.swatchStyle
  assign swatchSize = settings.swatchSize
  assign swatchColors = settings.swatchColors | newline_to_br | split: '<br />'

-%}

<style>
.product-form__input input[type='radio'] + label.color-swatch,
.product-form__input input[type='radio'] + label.color-swatch:after,
.product-form__input input[type='radio'] + label.color-swatch:before{
        border-radius: 0;
}
.product-form__input input[type='radio'] + label.color-swatch.round,
.product-form__input input[type='radio'] + label.color-swatch.round:after,
.product-form__input input[type='radio'] + label.color-swatch.round:before{
    border-radius: 100%;
  }
.product-form__input input[type='radio'] + label.color-swatch.round-corners,
.product-form__input input[type='radio'] + label.color-swatch.round-corners:after,
.product-form__input input[type='radio'] + label.color-swatch.round-corners:before{
        border-radius: 5px;
  }
  .product-form__input input[type='radio'] + label.color-swatch{
    border:1px rgb(214,214,214) solid;
    width: {{swatchSize}}px;
    height: {{swatchSize}}px;
    background-repeat: no-repeat;
    background-position: center;
    background-size: cover;
    margin-right: 9px;
  }
  .product-form__input input[type='radio'] + label.color-swatch:before{
    content: "";
    position: absolute;
    top: -1px;
    left: -1px;
    width: calc(100% + 2px);
    height: calc(100% + 2px);
    border: 1px rgb(214,214,214) solid;
    z-index: 0;
  }
  .product-form__input input[type='radio'] + label.color-swatch:after{
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 1;
    {%- if settings.dark or swatchType == "variantImage" -%}
       border: none;
    {%- else -%}    
      border: 3px rgb(255 255 255) solid;
    {%- endif -%}
  }
  .product-form__input input[type='radio'] + label.color-swatch:hover:before{
    border: 1px rgb(125 124 124) solid;
  }
  .product-form__input input[type='radio']:checked + label.color-swatch:before{
  {%- if settings.dark -%}
    box-shadow: 0 0 0 2px rgb(var(--color-foreground));
    {%- else -%}
    box-shadow: 0 0 0 1px rgb(var(--color-foreground));
    {%- endif -%}
    border-color:rgb(var(--color-foreground));
  }
  .product-form__input input[type='radio'] + label.color-swatch.variant-swatch{
    background-color:white;
    {%- if swatchStyle == "portrait" -%}
    height: calc({{swatchSize}}px/ 0.66);
    {%- endif -%}
  }
</style>

{%- for value in option.values -%}
  {%- liquid
    assign option_disabled = true

    for option1_name in variants_option1_arr
      case option.position
        when 1
          if variants_option1_arr[forloop.index0] == value and variants_available_arr[forloop.index0]
            assign option_disabled = false
          endif
        when 2
          if option1_name == product.selected_or_first_available_variant.option1 and variants_option2_arr[forloop.index0] == value and variants_available_arr[forloop.index0]
            assign option_disabled = false
          endif
        when 3
          if option1_name == product.selected_or_first_available_variant.option1 and variants_option2_arr[forloop.index0] == product.selected_or_first_available_variant.option2 and variants_option3_arr[forloop.index0] == value and variants_available_arr[forloop.index0]
            assign option_disabled = false
          endif
      endcase
    endfor
  -%}

  {%- if block.settings.picker_type == 'button' -%}
    <input
      type="radio"
      id="{{ section.id }}-{{ option.position }}-{{ forloop.index0 }}"
      name="{{ option.name }}"
      value="{{ value | escape }}"
      form="{{ product_form_id }}"
      {% if option.selected_value == value %}
        checked
      {% endif %}
      {% if option_disabled %}
        class="disabled"
      {% endif %}
    >
    {%- if swatchType == "variantImage" -%}
      <label 
      data-{{ option.name }}="{{value}}"
      style="background-image:url(
      {%- liquid
        assign optionIndex = option.position | minus: 1 
        for variant in product.variants
            if variant.options[optionIndex] == value
              assign swatchSizePortrait = swatchSize | times: 2 
              echo variant.image | image_url: width: swatchSizePortrait 
              break
            endif
        endfor
    -%}
       );"
       class="color-swatch variant-swatch {% case swatchStyle %}{% when "round" %}round{% when "square-round-corners" %}round-corners{% endcase %}"
          for="{{ section.id }}-{{ option.position }}-{{ forloop.index0 }}">
      <span class="visually-hidden">{{ 'products.product.variant_sold_out_or_unavailable' | t }}</span>
			
    </label>
    {%- else -%}
        {%- liquid
        for colorData in swatchColors 
            assign colorDataArr = colorData | split:":" 
            assign ruleName = colorDataArr[0] | strip
            if value == ruleName
                assign colorCodes = colorDataArr[1] | strip | split :"#"
                assign colorNumber = 0 | plus: colorCodes.size
                break 
            endif 
        endfor
    -%} 
    <label 
      data-{{ option.name }}="{{value}}"
      style="    
    {%- case colorNumber -%} 
        {%- when 2 -%}
            background-color: #{{ colorCodes[1] }}
        {%- when 3 -%}
            background: linear-gradient(135deg, #{{ colorCodes[1] }} 50%, #{{ colorCodes[2] }} 50%);
        {%- when 4 -%}
            background: linear-gradient(to right,#{{ colorCodes[1] }} 33%,#{{ colorCodes[2] }} 33%,#{{ colorCodes[2] }} 66%, #{{ colorCodes[3] }} 66%);
        {%- else -%}
            background-image:url({{ colorCodes[0] | downcase | replace: ' ', '-' | file_img_url }})
        {%- endcase -%}
        ;"class="color-swatch {% case swatchStyle %}{% when "round" %}round{% when "square-round-corners" %}round-corners{% endcase %}"
        for="{{ section.id }}-{{ option.position }}-{{ forloop.index0 }}">
      <span class="visually-hidden">{{ 'products.product.variant_sold_out_or_unavailable' | t }}</span>
    </label>
    {%- assign colorCodes = "" -%}
    {%- endif -%}
  {%- elsif block.settings.picker_type == 'dropdown' -%}
    <option
      value="{{ value | escape }}"
      {% if option.selected_value == value %}
        selected="selected"
      {% endif %}
    >
      {% if option_disabled -%}
        {{- 'products.product.value_unavailable' | t: option_value: value -}}
      {%- else -%}
        {{- value -}}
      {%- endif %}
    </option>
  {%- endif -%}
{%- endfor -%}

<script>
  document.querySelectorAll('input+label[data-{{ option.name | downcase }}]').forEach(el=>{
    el.addEventListener('click',()=>{
      document.querySelector('#selected-{{option.name}}').textContent = " "+el.getAttribute('data-{{ option.name | downcase }}')
    })
  })
</script>
5/5 - (8 votes)

About

Leave a Comment

Your email address will not be published. Required fields are marked *