Shopify提供のwebフォントを特定ページでのみ使う方法

shopify

少々不完全ですがとりあえずこれが最もミニマルな状態かなというの形が見えたのでメモとして。

実現したいこと

  • Shopifyでwebフォントを使う
  • webフォントはShopifyのCDNから提供されるものをつかう

Shopifyのフォントの種類に関しては以下に一覧があります。

基本的には上記ページに利用方法も書かれているため、そちらを読んでいただければ当記事を読む必要性はほぼありません。

前提: 特定ページに内容を出力する方法

  • templateにしろsectionにしろ、目的のページにのみ表示できるファイルを探すなり作るなりして記載場所を確保する

TOPページならindex.liquidで対応可能でしょうし、特定のページならlayout内にそのページ専用ファイルを作って管理画面で選べば可能ですし、sectionにファイルを作りpage.liquidhandleに特定の文字列があるかどうかで分岐させたうえで読み込ませることでも可能ですし、やり方はいろいろあります。

この辺りは用途に合わせて色々と自由にかけるため必要に応じて適宜検討します。

サンプル1: body内に出力

1つ目のサンプルはliquid内にインラインでstyleタグを出力する方法です。

{% schema %}はセクションにしか記載できないので、記述対象のliquidはセクションに入れる必要があります。
テーマのカスタマイズ画面で出力予定のページを表示させれば、設定した{% schema %}に応じたフォント用の場所が出来上がっていてフォント変更などの操作が可能です。

コード


{% assign my_font = section.settings.my_font %}
{% style %}
{{ my_font | font_face }}
body {
  font-family: {{ my_font.family }};
}
{% endstyle%}

{% schema %}
{
  "name": "Typography",
  "settings": [
    {
      "type":    "font_picker",
      "label":   "My font",
      "id":      "my_font",
      "default": "helvetica_n4"
    }
  ]
}
{% endschema %}

section.settings.my_fontでフォントピッカーで設定した情報を取得し、{{ my_font | font_face }}によって以下のように必要な@font-faceが出力されます。


{% comment %}Caslon Old Faceを選んだ場合{% comment %}
@font-face {
  font-family: "Caslon Old Face";
  font-weight: 400;
  font-style: normal;
  src: url("https://fonts.shopifycdn.com/caslon_old_face/caslonoldface_n4.xxxx.woff2?&hmac=xxx") format("woff2"),
       url("https://fonts.shopifycdn.com/caslon_old_face/caslonoldface_n4.yyy.woff?&hmac=yyy") format("woff");
}

{{ my_font.family }}font-familyだけが出力されるので、これをCSSのfont-familyに設定すれば反映されます。

なおフォントピッカーに関しては以下のヘルプページが該当します。

サンプル2: head内に出力してpreload使用

サンプル1を流用しつつpreloadを使いたい場合は以下の方法が検討できます。

  • settings_schema.jsonにフォントピッカーの表示用記述を記載
  • layout内の必要なファイル(theme.liquidで分岐させるか、専用のファイルを作るか)に出力用記述を記載

仮にフォント用のsectionを作成してhead内で読み込ませた場合、sectiondivも出力され、ブラウザではこのdivを含むそれ以降がbodyに移動してしまいます。

そのためhead内にフォントピッカーの値を出力するにはsettings_schema.jsonに記載するしかないと思われます。

コード

基本的には上記のサンプルコードがそのまま使えますので、この例に習ってpreload_font.liquidを作成して所定のファイルに出力記述を記載します。なお後述する理由によりwoff2だけ読み込ませた方が効率的な可能性があるため一部書き換えています。


{% if preload_font and preload_font != blank %}
  {% capture ff_output %}
  {{ preload_font  | font_face }}
  {% endcapture %}
  {% assign font_files = ff_output | split: "src: " | last | split: 'url("' %}
  {% for line in font_files %}
    {% if line contains '")' %}
      {% assign font_url = line | split: '")' | first %}
      {% assign font_type = line | split: 'format("' | last | split: '")' | first %}
      {% if font_type contains 'woff2' %}
        <link rel="preload" as="font" href="{{ font_url }}" type="font/{{ font_type }}" crossorigin="anonymous">
      {% endif %}
    {% endif %}
  {% endfor %}
{% endif %}

head内に出力可能な所定のファイルには以下のように記載します。


{% assign my_font = section.settings.my_font %}
{% render 'preload_font' with my_font %}

{% style %}
{{ my_font | font_face }}
body {
  font-family: {{ my_font.family }};
}
{% endstyle%}

settings_schema.jsonには以下のように記載します。ここに書けばテーマのカスタマイズ画面の左メニュー下部にある「テーマ設定」からフォントの変更が可能になります。


{
  "name": "Typography",
  "settings": [
    {
      "type":    "font_picker",
      "label":   "My font",
      "id":      "my_font",
      "default": "helvetica_n4"
    }
  ]
}

webフォントのpreloadとcrossoriginとwoff2

フォントファイルのpreloadに関しては以下の記事の「webフォント」の項目が詳細だと思います。

crossoriginの必要性やwoffwoff2の両方を読み込むデメリットと対応策も書かれています。

with

本筋ではないですが、withを使うことで関数と引数のような使い方ができることを知りました。これを使うとできることが増えそうで想像が膨らみますが、includeからrenderになって速度が増したとはいえ不必要に使うものではないようにも思いますので、関数ほど気軽に使わない方がよいのかもとも思います。

実現できなかった手段

フォントの一覧ページでフォントを選ぶとHandleが表示されます。Caslon Old Faceならcaslon_old_face_n4など。当初はこのHandlefont_urlフィルターを使うことでフォントのURLが取得表示できるのではと考えていたのですが、そういう方法は見つかりませんでした。handleに関してはフォントピッカー用のschemaに用いるdefaultに使用できるので無意味に設定されているものではありません。

そういう意味ではdefaultliquidで変更することで、liquidによるShopifyのフォント指定が可能であるともいえるかもしれません。

結び

現時点ではフォントピッカーを通す方法しか見つけられませんでした。

なお一度出力してしまえばsrcに記載するパスはわかるため、それだけを直接書いてしまえばフォントピッカーを使う必要はありません。実際のところ検索で出てくる情報はほぼ全てこのタイプでした。ただ個人的にはCDNのURLを直書きするのは少々不安感があって当記事のような方法を検討しました。

1人がこの記事を評価

役に立ったよという方は上の「記事を評価する」ボタンをクリックしてもらえると嬉しいです。

連投防止のためにCookie使用。SNSへの投稿など他サービスとの連動は一切ありません。

コメント欄