Shopify商品ページの色選択をメタフィールドを使ってカラースウォッチを実装する方法

【Shopify】メタフィールドを使って商品ページにカラースウォッチの色選択を実装

Shopifyがオンラインストア2.0にアップデートして、最も嬉しかったのがメタフィールドの実装。

現在はまだ「商品」と「バリエーション」しか使えませんが、いずれは「コレクション」や「顧客」「注文」のメタフィールドも操作できるようになるようで、楽しみで仕方ありません。

今回は、タイトルにもあるようにそのメタフィールドを使って、商品ページの色選択を「カラースウォッチ（色見本）」にカスタマイズする方法をご紹介します。

「カラースウォッチ」に関しては、テーマに実装されている場合も多いのですが、Dawnをはじめとする無料テーマなど非実装のテーマに実装するにはアプリを使った方法が一般的です。

また、カラースウォッチが実装されているテーマを見てみると、カラー名から判別し「background-color: black;」のようにスタイルを定義する仕組みなのですが、日本語表記など判別できない色は自ら定義する必要があったり、画像をAssetに登録したりというものがほとんどで、どちらかといえば玄人向けの機能でした。

しかしメタフィールド機能を使えば、バリエーション編集画面のカラーピッカーで登録できるので、管理も容易になります。

さて、本題です。
今回もDawnをベースにご紹介していきます。

1. バリエーションメタフィールドを設定

設定→メタフィールド→バリエーションの「定義を追加する」より、バリエーションメタフィールドの定義を追加し、「名前」と「ネームスペースとキー」を入力、「コンテンツタイプを選択する」にて「色」を選択し保存してください。

2. ブロック設定を編集

テーマ編集より、main-product.liquidの{% schema %}内にある「variant_picker」部分に、以下のハイライト部分を追記します。

{
"type": "variant_picker",
"name": "t:sections.main-product.blocks.variant_picker.name",
"limit": 1,
"settings": [
{
"type": "select",
"id": "picker_type",
"options": [
{
"value": "dropdown",
"label": "t:sections.main-product.blocks.variant_picker.settings.picker_type.options__1.label"
},
{
"value": "button",
"label": "t:sections.main-product.blocks.variant_picker.settings.picker_type.options__2.label"
},
{
"value": "colorswatch",
"label": "カラースウォッチ"
}
],
"default": "button",
"label": "t:sections.main-product.blocks.variant_picker.settings.picker_type.label"
}
]
},

これでカスタマイザーにてバリエーションピッカーのタイプ選択で「カラースウォッチ」を選べるようになりました。

3. liquidコードを編集

同じくmain-product.liquidにある{%- if block.settings.picker_type == 'button' -%}の部分をコピーし、そのすぐ下にペーストします。

{%- if block.settings.picker_type == 'button' -%}
<variant-radios class="no-js-hidden" data-section="{{ section.id }}" data-url="{{ product.url }}" {{ block.shopify_attributes }}>
{%- for option in product.options_with_values -%}

{{ option.name }}
{%- for value in option.values -%}
<input type="radio" id="{{ section.id }}-{{ option.name }}-{{ forloop.index0 }}"
name="{{ option.name }}"
value="{{ value | escape }}"
form="product-form-{{ section.id }}"
{% if option.selected_value == value %}checked{% endif %}
>

{{ value }}

{%- endfor -%}

{%- endfor -%}

{{ product.variants | json }}

</variant-radios>
{%- if block.settings.picker_type == 'button' -%}
<variant-radios class="no-js-hidden" data-section="{{ section.id }}" data-url="{{ product.url }}" {{ block.shopify_attributes }}>
{%- for option in product.options_with_values -%}

{{ option.name }}
{%- for value in option.values -%}
<input type="radio" id="{{ section.id }}-{{ option.name }}-{{ forloop.index0 }}"
name="{{ option.name }}"
value="{{ value | escape }}"
form="product-form-{{ section.id }}"
{% if option.selected_value == value %}checked{% endif %}
>

{{ value }}

{%- endfor -%}

{%- endfor -%}

{{ product.variants | json }}

</variant-radios>

コピペしたら、2つめの{%- if block.settings.picker_type == 'button' -%}を{%- elsif block.settings.picker_type == 'colorswatch' -%}に編集します。

{%- if block.settings.picker_type == 'button' -%}
<variant-radios class="no-js-hidden" data-section="{{ section.id }}" data-url="{{ product.url }}" {{ block.shopify_attributes }}>
{%- for option in product.options_with_values -%}

{{ option.name }}
{%- for value in option.values -%}
<input type="radio" id="{{ section.id }}-{{ option.name }}-{{ forloop.index0 }}"
name="{{ option.name }}"
value="{{ value | escape }}"
form="product-form-{{ section.id }}"
{% if option.selected_value == value %}checked{% endif %}
>

{{ value }}

{%- endfor -%}

{%- endfor -%}

{{ product.variants | json }}

</variant-radios>
{%- elsif block.settings.picker_type == 'colorswatch' -%}
<variant-radios class="no-js-hidden" data-section="{{ section.id }}" data-url="{{ product.url }}" {{ block.shopify_attributes }}>
{%- for option in product.options_with_values -%}

{{ option.name }}
{%- for value in option.values -%}
<input type="radio" id="{{ section.id }}-{{ option.name }}-{{ forloop.index0 }}"
name="{{ option.name }}"
value="{{ value | escape }}"
form="product-form-{{ section.id }}"
{% if option.selected_value == value %}checked{% endif %}
>

{{ value }}

{%- endfor -%}

{%- endfor -%}

{{ product.variants | json }}

</variant-radios>

これで、カラースウォッチの実装準備が整いました。

4. バリエーションメタフィールドを実装

3でコピペしたliquidコードの以下ハイライト部分を編集します。

{%- elsif block.settings.picker_type == 'colorswatch' -%}
{{ 'colorswatch.css' | asset_url | stylesheet_tag }}
{%- assign color = 'カラー' -%}
<variant-radios class="no-js-hidden" data-section="{{ section.id }}" data-url="{{ product.url }}" {{ block.shopify_attributes }}>
{%- for option in product.options_with_values -%}

{{ option.name }}
{%- for value in option.values -%}
<input type="radio" id="{{ section.id }}-{{ option.name }}-{{ forloop.index0 }}"
name="{{ option.name }}"
value="{{ value | escape }}"
form="product-form-{{ section.id }}"
{% if option.selected_value == value %}checked{% endif %}
>
{%- capture variant_color -%}
{%- for variant in product.variants -%}
{%- if variant.title contains value -%}
{{ variant.metafields.my_fields.color_swatch }}
{%- endif -%}
{%- endfor -%}
{%- endcapture %}
{%- assign vc = variant_color | split: ' ' | first -%}

{% unless option.name == color %}{{ value }}{% endunless %}

{%- endfor -%}

{%- endfor -%}

{{ product.variants | json }}

</variant-radios>

上から順に説明します。

まず2行目で、カラースウォッチ用のスタイルシートを読み込みます。

{{ 'colorswatch.css' | asset_url | stylesheet_tag }}

こちらについては、後ほど説明いたします。

続いて3行目にて、バリエーションのオプション名を定義します。

{%- assign color = 'カラー' -%}

今回は「カラー」で設定してありますが、「Color」や「色」の場合はその様に編集してください。

次に6行目の タグのクラス部分に以下を追記します。

{% if option.name contains color %} colorswatch{% endif %}

先程定義したオプション名だった場合は「colorswatch」というクラスが付与されるようになっています。

15〜22行目にてバリエーションメタフィールドを出力する準備をします。

{%- capture variant_color -%}
{%- for variant in product.variants -%}
{%- if variant.title contains value -%}
{{ variant.metafields.my_fields.color_swatch }}
{%- endif -%}
{%- endfor -%}
{%- endcapture -%}
{% assign vc = variant_color | split: ' ' | first %}

何故こんなに複雑になるかというと、バリエーションメタフィールドはforループでしか出力できなくて、そのまま出力しても全バリエーションのカラー値が出力されてしまうからです。
例えば3サイズ3カラーの場合は、「#ffffff#111111#777777#ffffff#111111#777777#ffffff#111111#777777」って感じに出力されちゃいます。

それを回避して各カラーに紐づくメタフィールドを出力させる為に、上記の仕組みを考えました。
もっと便利な方法があれば教えていただけると嬉しいです。

まず{% capture %}にてバリエーションのforループを設け、オプション名（カラー）を含んだバリエーションのみを選定、そのメタフィールドのカラー値を出力させます。
ただこれだと3サイズ3カラーの場合は、Whiteの出力結果が「#ffffff#ffffff#ffffff」となってしまうので、最後の{% assign %}にて1つにし、{{ vc }}で出力されるようにしてあります。

uniqでも実装可能なんですが、uniqの場合はカラー値が混在していた場合にまとめられないので、最初の値だけ抜き出すfirstを採用しました。
ちなみにlastでもOKです。

23行目の タグにて先程定義したカラー値を反映させます。

{% if option.name == color %} style="background-color: {{ vc }};" aria-label="{{ value }}"{% endif %}

オプション名が「カラー」だった場合のみにスタイルが適用されるので「サイズ」とかには反映されません。
また、カラー名のテキストを消すのでアクセシビリティの為にaria-label属性にてカラー名を定義します。

最後に24行目の{% unless %}にて、オプションが「カラー」以外はバリエーション名が出力されるようになっています。

{% unless option.name == color %}{{ value }}{% endunless %}

分岐してカラーの場合はスクリーンリーダーテキストにするのもありですね。

5. スタイルシートを作成

「新しいassetを追加する」より「colorswatch.css」を作成し、以下のCSSを貼り付けます。

.product-form__input.colorswatch input[type=radio]+label {
width: 4rem;
height: 4rem;
}
.product-form__input.colorswatch input[type=radio]:checked+label {
box-shadow: 0 0 0 2px #fff, 0 0 0 3px #333;
}

元のCSSを活かしつつ極力シンプルにしているので、お好みでデザインしてください。

6. 商品のバリエーションをでカラーを設定

商品管理より各商品のバリエーション編集にて、最下部にメタフィールド編集のブロックがありますので、全バリエーションのカラー値を設定します。
商品数やバリエーション数が多い場合は、CSVで編集すると効率が良いです。

カラー値はグレーの場合は全て#777777、ブラックの場合は#111111に統一するなど、予めバリエーション用に決めておくと便利です。

7. カスタマイザーを設定

最後にカスタマイザーにて商品ページの編集画面を開き、商品情報のバリエーションピッカーを選択、タイプを「カラースウォッチ」に、保存すればオプションのカラー部分のみがカラースウォッチに切り替わります。

以上で実装は完了となります。

Ex. さらに拡張してみる

カラースウォッチにカラー名も表示させたい場合は、オンマウスでバルーン（吹き出し）表示なんてのもいいですね。
その際はcolorswatch.cssに以下のスタイルを追記すればバルーンを実装できます。

.product-form__input.colorswatch input[type=radio]+label::before,
.product-form__input.colorswatch input[type=radio]+label::after {
position: absolute;
display: inline-block;
left: 50%;
font-size: 10px;
line-height: 1;
transform: translateX(-50%);
transition: .2s linear;
opacity: 0;
z-index: -1;
}
.product-form__input.colorswatch input[type=radio]+label::before {
content: attr(aria-label);
top: -2em;
color: #fff;
background: #000;
padding: .5em;
border-radius: 3px;
}
.product-form__input.colorswatch input[type=radio]+label::after {
content: "";
top: 0;
border: .5em solid transparent;
border-top-color: #000;
border-bottom-width: 0;
}
.product-form__input.colorswatch input[type=radio]+label:hover::before,
.product-form__input.colorswatch input[type=radio]+label:hover::after {
opacity: 1;
z-index: 1;
}
.product-form__input.colorswatch input[type=radio]+label:hover::before {
top: -3em;
}
.product-form__input.colorswatch input[type=radio]+label:hover::after {
top: -1em;
}

一昔前はjQueryUIとかで実装してましたが、便利なCSSも増えてきたのでCSSだけでアニメーションのついたバルーンが実装できます。

Dawnをはじめ新しいテーマは軽量化のためにjQueryを使っていない事が多いので、こんなことの為に重たいjQueryやjQueryUIを実装する必要はありません。

他にもメタフィールドのコンテンツタイプをファイルにすれば、サムネイルにしたりすることもできますね。

以上、商品ページの色選択をメタフィールドを使ってカラースウォッチを実装する方法でした〜