今回は必要に迫れれわけではないのですが、カラーパレットのあるテンプレートってカラー展開が多いお店には、便利だよなあぁ。
っとぼんやりテーマストアを眺めていた時に・・・ん?自作すりゃいいんじゃないか?って急に思い立って作ってみたカスタマイズです。
上級者向けな記事ではあるので、少なくともこの辺の記事は理解できているといいかと思います。
Debutテンプレートに実装していきますが、別に他のテンプレートでもだいたい同じコードで行けるはずです。(設置場所はテンプレート毎変わると思います)
今回の記事では
liquidタグ
・assign
・for
liqudiフィルター
・split
・last
オブジェクト
・product
この辺りの事が学べますよ。
どんなものか確認してカスタマイズのプロセスを考える
まずはカラーパレットってなんですか?ってところから確認しましょう。
この赤枠で囲ってるとこですね。商品がカラー展開してるときに、どの色があるのか一目瞭然に確認できる奴です。
今回はこれをとりあえず見た目だけも表示できるようなカスタマイズをしていきます。カートに入れる時にパレットをクリックすれば選択できる機能までは持たせてませんのであしからず。
なるほど、色が商品毎に表示されている機能だと言う事がわかるかと思います。特にコレクショングリッドとかで商品一覧が見えるシーンだと、あると嬉しい機能ですよね^^
これをカスタマイズで実装する時に考えるべきことは
- 色情報の取得方法
- 色情報の出力方法
と言う事になります。こ
今回はこれをオプション情報から取得しようかとも思ったんですが、出力するのにcssで出力しようと思っていたので、オプションネームをcssのカラーネームで入力する必要が出てくるので、カタカナ表記したい場合などに使えなくなります。
それでは困るので「商品タグ」に色を入れて色情報を取得する事にしました。
後で説明するのですが、今回商品タグには「color_red」「color_white」「color_blue」などのタグを付けています。redやwhiteの表記はそのままcssで使えるのでこれを利用します。
じゃあカスタマイズしてみよう
と言う事で次はこれをカスタマイズで作っていきます。
まずは商品自体に元となるタグを付けていきます。商品一覧で見えれることも確認したかったので、過去最高の「くまちゃん」4体にタグを付けていきました!
こんな感じです。色々もてあそばれまくってる「くまちゃん」なので悲惨なタグがいっぱいつけられていますが、この際そのままにしておきました(意味は実は後でわかります)
その他「くまちゃん 2号」「くまちゃん 3号」「くまちゃん 4号」にもcolor_redなどのタグを適当に割り振って付けてあります。
ではまずこいつをどうやって商品ページの載せるのかを考えましょう。
商品タグの一覧を取得する
書く商品の商品ページは基本的に「product.liquid」テンプレートを元に生成されます。Debutの場合はそのテンプレートがセクションファイルの「product-template.liquid」を読み込む構造なので、実際にいじるのはこの「product-template.liquid」と言う事になります。
今回カラーパレットを表示したいのはこの赤丸の辺りです。ここに色が一目でわかるような物を出力していきます。
まずは手始めに、出力の元となる「タグ」がどういう風に、liquidでは管理されているのかを確かめましょう。
商品には商品固有の「productオブジェクト」があります。
確かこの辺の記事で、オブジェクトとプロパティについて解説したかと思いますが、今回はそのオブジェクトの中でも「productオブジェクト」の「tagsプロパティ」を参照したいと思います。
{{ product.tags }}
このliquidを出力したい場所に書くだけです。これの意味が「productオブジェクトのtagsプロパティ」と言う事になります。んで今回はDebutテンプレートで「カートに追加する」ボタンの上ぐらいなのでformタグのちょい上に書けばいいですね
{{ product.tags }}
{% capture "form_classes" -%}
product-form product-form-{{ section.id }}
{%- if section.settings.enable_payment_button and product.has_only_default_variant %} product-form--payment-button-no-variants {%- endif -%}
{%- if current_variant.available == false %} product-form--variant-sold-out {%- endif -%}
{%- endcapture %}
{% form 'product', product, class:form_classes, onsubmit:'return false;',novalidate: 'novalidate', data-product-form: '' %}
こんな感じです。これを書くとどうやって出力されるかと言えば
こんな感じですね。商品に付けたタグが、スペースも,(カンマ)もなく、そのまま連なった文字列で表示されているのがわかるかと思います。このままではちょっと処理できないので、こいつをバラバラにして処理をするのにfor構文を使います。
{% for color_tag in product.tags %}
{{color_tag}}
{% endfor %}
これでproduct.tagsを毎回color_tagって変数にいったん入れて出力してね!って意味になるので、これを表示すると
おいっ!さっきと何が・・・違うの??ってレベルですがよくよく見ると半角スペースぐらい入ってます。まぁ、今回タグとかで囲まないでそのまま文字列で出力したので、あまり違いが判らないかったですけど、一応これで1つ1つ処理されていることがわかるかと思います。
今度はこの中で、邪魔なタグを除去する事を考えなくてはいけません。
何を使うかと言うと今度はif構文です。今回ここで意味を成してくるのですが、色タグにはcolorが必ず付いています。これはこの時の為に付けていたのです!
colorを含むタグだけを抽出できれば、邪魔なタグは除去されていきます。そのために使えるのは「contains」と言う命令タグです。
{% if color_tag contains "color" %}
意味としては「color_tag(変数)が文字列のcolorを持っている時はtrue」と言う意味になっています。つーことで今度はこれをつけ足したコードで
{% for color_tag in product.tags %}
{% if color_tag contains "color" %}
{{color_tag}}
{% endif %}
{% endfor %}
こういうことになります。これで出力すると
ほら、すっきり。colorが付いたタグだけが残りましたね。だいぶ絞られてきましたが、colorが邪魔です。欲しいのは色情報だけなので、次はこのcolorを除去しましょう。
今度使うフィルターは「split」です。そのまま分割すると言う意味なので、これを使って書くコードはこうです
{% for color_tag in product.tags %}
{% if color_tag contains "color" %}
{% assign color_name = color_tag | split: "_" %}
{{ color_name | last }}
{% endif %}
{% endfor %}
ポイントはsplitをする為の起点になる文字を「_」に設定している事と、それを一旦、変数「color_name」に格納しています。
そして変数「color_name」の出力時に謎のフィルター「last」が使われていますね。
これは、splitした瞬間のcolor_tag君は単純に「_」が取り除かれた状態なので、もし
{{ color_name }}
で出力すると「colorred」みたいにあ、ただ_がなくなった文字列が出てきます。ただ、splitした瞬間の最大のメリットは見た目にはカンマもないし、スペースもないですが、配列になっている事です!!
なのでこの配列の最後を取り出してね!と言う意味で「last」フィルターを使っています。
ちなみにindex番号での指定も出来るので {{ color_name[1] }} でも出力結果は同じです。実際に見てみると
ご覧の通り!色名だけが単純に取り出せています!ここまで加工出来たら・・・こっちのもんです!!あとはこれをcssでスタイルを付けてやるだけです。
だもんで、最終的なコードは
<div class="color-swatch-wrap">
{% for color_tag in product.tags %}
{% if color_tag contains "color" %}
{% assign color_name = color_tag | split: "_" %}
<div class="color-circle color-circle-{{ color_name | last }}">
</div>
{% endif %}
<style>
.color-circle-{{ color_name | last }} {
background: {{ color_name | last }};
}
</style>
{% endfor %}
</div>
<style>
.color-swatch-wrap {
display: flex;
}
.color-circle {
width: 20px;
height: 20px;
border: 2px solid #666;
border-radius: 50%;
margin: 0 2px;
<div class="color-swatch-wrap">
{% for color_tag in product.tags %}
{% if color_tag contains "color" %}
{% assign color_name = color_tag | split: "_" %}
<div class="color-circle color-circle-{{ color_name | last }}">
</div>
<style>
.color-circle-{{ color_name | last }} {
background: {{ color_name | last }};
}
</style>
{% endif %}
{% endfor %}
</div>
<style>
.color-swatch-wrap {
display: flex;
}
.color-circle {
width: 20px;
height: 20px;
border: 2px solid #666;
border-radius: 50%;
margin: 0 2px;
}
</style>
こうなっています。
あれ?なんか想定している物と違うぞ?ってなりました?!
styleタグが2回も登場してますしね。これにはもちろん秘密があります。
まず最初のstyleタグはfor構文の中に書かれています!ここがとってもミソで、ループのたびに呼び出されるわけですが、その時にクラス名のところにも {{ color_name | last }} が付けれれてますよね?そうするとループのたびに
color-circle-red
color-circle-green
等のクラス名を作ってくれます。ループのたびに違うクラス名が生成されるので、何と重複しないクラス名を生み出し、さらにその下でループのたびにその生成されたクラス名に対して、backgroundで色を付けています。
for構文の外にあるスタイルは、これをまるで囲って「20px四方のまん丸」にしている感じですね。実際に出力してみましょうかね!
ほーら、出来ちまいました!意外と簡単だったでございましょ?しかし、まだこれでは終わらんです。次は一覧でも表示するです!!
商品一覧でもカラーを出力したい
さて、商品ページで出力に成功したので、今度はコレクションの一覧表示でもこれを出してやろうじゃないですか!!
やる事はめっちゃ簡単です。適切な箇所にさっきのコードを張り付けるだけ!!
でもこれじゃ、2回も同じコード書いてスマートじゃないので、こう言う時はパーツファイルを作りましょう。shopifyならこういう時にこそsnippetを使うのです!
やる事は簡単でsnippetフォルダで新規作成「color-swatch.liquid」(パレットよりスウォッチのが僕的にしっくり来てるので、swatchになってます)を作って中身はさっきのコードです。
こんな感じです。これでパーツファイル化は完了ですから、次はこれを呼び出すだけです。さっきの商品ページのも直しておくと
{% include "color-swatch" %}
{% capture "form_classes" -%}
product-form product-form-{{ section.id }}
{%- if section.settings.enable_payment_button and product.has_only_default_variant %} product-form--payment-button-no-variants {%- endif -%}
{%- if current_variant.available == false %} product-form--variant-sold-out {%- endif -%}
{%- endcapture %}
{% form 'product', product, class:form_classes, onsubmit:'return false;',novalidate: 'novalidate', data-product-form: '' %}
{{ form | payment_terms }}
こんな感じで、snippetを呼び出しているわけですね。
では今度はDebutのコレクション表示セクションに移動しましょう。Debutの場合はセクションフォルダ内のずばり「collection.liquid」がそれになります。
しかしよくよく見ると、このファイルの中で2か所、snipeptを呼び出している場所があるのですよね
{% include 'product-card-grid', max_height: max_height, product: product, show_vendor: section.settings.show_vendor %}
{% include 'product-price' %}
この2か所でincludeしてやがるので、このどちらかの中身に書かなくてはならんことがわかります。今回のターゲットプレイスをまずは確認してみます。
うーん、商品写真のサイズを揃えていないと醜いぞ!って好事例ですね!写真のサイズはそろえましょう!!
で、ターゲットはこの赤丸部分。商品タイトルの上あたりを狙いたい所です。となると商品タイトルだから・・・ {{ product.title }} なんて形で呼び出してそうだな?と目星を付けてから探すと
product-card-grid.liquidファイル内の一番下付近にそれっぽいのがあるのでここにさっき作ったsnippetをぺったんこ貼り付けます
{% include "color-swatch" %}
<div class="h4 grid-view-item__title product-card__title" aria-hidden="true">{{ product.title }}</div>
じゃんじゃじゃーーん!ほらね!全部出ていらっしゃるでしょ♪原色がまぶしいぜ!!
ちなみに今回はセクションフォルダ内のcollection.liquidを元にカスタマイズしていますが、このセクションはトップページにコレクション一覧を表示するセクションファイルです。
コレクションページの方はレイアウトフォルダ内のcollection.liquid が セクションファイル内のcollection-template-liquid を呼び出しているのです構造です。とはいえ結局グリッド表示用にproduct-card-grid.liquidを呼び出しているので、特に新しいカスタマイズをせずとも、同時に反映されます!
今な感じですね。まぁ、見た目あまり変わらんのですが、こっちはコレクションページです。これでしっかりとカラーパレットの表示が成功しました!
まとめ
最後にまとめると
- タグのルールを作る
- liquidでsnippetを作る
- snippetを貼る
作業的にはこんな感じですね。この今回のタグの使い方は覚えておくと色んなシーンで役に立ちます。別に「color_red」と言うタグは「cat_ぬいぐるみ」「cat_くまちゃん」とか(catはカテゴリーの略称として使ってます)のタグを作って、さっきの要領で抽出すれば「ぬいぐるみ」とか「くまちゃん」を文字列で出力できます!
実は説明の途中でも blue green red 辺りは文字列で表示してましたよね?文字列で出力出来たら、例えば一覧表示グリッドの中に「送料無料」とかも、タグ付けだけで出力出来たりします。
かなり応用力があるタグ使いなのでぜひ覚えましょう!
やる事は
- product.tagsをfor構文で回す
- color が付いてるタグだけをif構文で抽出
- color を除去
と言う仕組みです。この流れを叩き込んで最後にもうsnippetのコードを貼っておきます。
お粗末様でした!
<div class="color-swatch-wrap">
{% for color_tag in product.tags %}
{% if color_tag contains "color" %}
{% assign color_name = color_tag | split: "_" %}
<div class="color-circle color-circle-{{ color_name | last }}">
</div>
<style>
.color-circle-{{ color_name | last }} {
background: {{ color_name | last }};
}
</style>
{% endif %}
{% endfor %}
</div>
<style>
.color-swatch-wrap {
display: flex;
}
.color-circle {
width: 20px;
height: 20px;
border: 2px solid #666;
border-radius: 50%;
margin: 0 2px;
}
</style>