【非jQueryスライダー】Flickityを設置しても全然動作しないときの確認点【備忘録】

未分類
未分類

ShopifyでFlickityを設置しても全然動作しなくて時間を無駄にした。いつも原因がまちまちだがこれまで何度も同じようなことをやらかしてしまっているミスのように思ったので、その備忘録。

Flickity公式
https://flickity.metafizzy.co/#cdn

今回の最終形↓

See the Pen Flickityでスライド後に画像がゆっくりズームアウト by Naoto Yoshikawa (@nanaironanaoto) on CodePen.

ポイント1)初歩的なこと:きちんとライブラリを読めているか

CDNであれば

<link href="https://unpkg.com/flickity@2/dist/flickity.min.css">
<script src="https://unpkg.com/flickity@2/dist/flickity.pkgd.min.js"></script>

CDNでなければ、Shopifyのassetフォルダに格納しているときの呼び出し例。
Flickityはスクリプトをdefer=”defer”として遅延ロードさせたりすると、スライダーの表示がカクつく。

{{ 'flickity.min.css' | asset_url | stylesheet_tag }}
<script src="{{ 'flickity.pkgd.min.js' | asset_url }}" defer="async"></script>

がんばっても、サブリミナル映像ほどの瞬間カクつくので、もうサブリミナルも嫌なら、スライダーにFlickityが適用されたら”flickity-enabled”というクラスが付与されるので、これを検知するまで別の待機画面やをオーバーレイさせるなどするとよいかもしれない。(今回そこまではしないものとします)

ただ、ローディングの画像で画面全体を覆うのは、SEO的にも悪い。ページのローディングを遅くするのがひとつ、もうひとつが、コンテンツがJavaScriptを完全に読み込むまで表示されない場合、検索エンジンがページの重要なコンテンツをインデックスできない可能性がある。

このPRYTHMWORKSでもローディングアニメーションを入れていたらGoogleの検索ロジックが変更になったのとタイミングが合ったのか、ガッツリ自然検索数が落ちた。

ポイント2)PHP(WordPress)やShopifyでやらかしがちなこと

公式に記載のバニラ(無加工の)JavaScript実行コードそのままでは実行されない

公式に記載の“Initialize with vanilla JavaScript”

var elem = document.querySelector('.main-carousel');
var flkty = new Flickity( elem, { /* options */ });


動かない

スクリプトの実行タイミングが原因なのか、下のだと実行できた。。

document.addEventListener('DOMContentLoaded', function() {
    var elem = document.querySelector('.main-carousel');
    var flkty = new Flickity(elem, { /* options */ });
});
document.addEventListener('DOMContentLoaded', function() { /*実施内容*/ }

で公式のJSコードをラップしているだけ。

JavaScriptがDOM要素のロードより先に実行されてしまっていたらしい。

指定した要素がまだ存在しない状態でFlickityが初期化しようとするとエラーが発生する。

わかったのは、Shopifyでtheme.liquidに直書きすると管理が汚くなるので、sectionのliquiudコードに一連のコードを記述していたことが原因だった。

どうやらShopifyではtheme.liquidで参照していてもsectionに記述したコードの実行順序が、theme.liquidのコードで見た上からの読み込みじゃないようだ。

検証していくと、sectionのコードは、テーマの最も浅いレベルのコードが読み込まれたあとに読まれていることがわかった。なので、sectionに格納しても汎用的に使用できる形としては、以下が完成系だ。

完成形:Shopifyでの記述例(シンプル版)

{{ 'flickity.min.css' | asset_url | stylesheet_tag }}
<script src="{{ 'flickity.pkgd.min.js' | asset_url }}" defer="async"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
    var elem = document.querySelector('.main-carousel');
    var flkty = new Flickity(elem, { 
      /* Flickityが提供しているオプションをここに記述 */
    });
});
</script>
<div class="banner_wrap">
  <div class="main-gallery">
  {% for block in section.blocks %}
    <a class="slider-cell" href="{{ block.settings.url }}">
      {{ block.settings.slider_image | image_url: width: 1600 | image_tag }}
    </a>
  {% endfor %}
  </div>
</div>
{% schema %}
{
  "name": "スライダー画像",
  "blocks": [
      {
        "name": "slider",
        "type": "header",
        "settings": [
          {
            "type" : "image_picker",
            "id" : "slider_image",
            "label" : "画像"
          },
          {
            "type" : "url",
            "id" : "url",
            "label" : "リンク先"
          }
        ]
      }
    ],
  "presets" : [
    {
      "name" : "スライダー画像",
      "category" : "Custom"
    }
  ]
}
{% endschema %}

オプション

Flickity v2 · Options
Touch, responsive, flickable carousels

発展型:スライド後にゆっくり画像がズームアウトする

公式からも提供されている、changeイベントを取得してjsで自分の好みのイベントを作成可能。ここでは、画像がスライド後にゆっくりズームアウトするエフェクトを追加した。

初期状態が1.2倍のズームイン状態で、スライド後に3秒かけて1倍サイズにズームアウトする。

最終形がズームインだと拡大された分、解像度が粗くなるのが目立つから、最終形はズームアウトのほうがいいんじゃないかと思う。

See the Pen Flickityでスライド後に画像がゆっくりズームアウト by Naoto Yoshikawa (@nanaironanaoto) on CodePen.

かつ、デスクトップとモバイルでそれぞれの適正サイズ、適正縦横比で、表示するスライダーを出し分けることもしている。記述した仕様ではデスクトップとモバイルそれぞれで分けて登録する必要がある。

{{ 'flickity.min.css' | asset_url | stylesheet_tag }}
<script src="{{ 'flickity.pkgd.min.js' | asset_url }}" defer="async"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
    var elem = document.querySelector('.main-gallery');
    var flkty = new Flickity(elem, { 
      autoPlay: 3000,
      wrapAround: true,
      prevNextButtons: true,
      pageDots: false
    });
    // スライドが変更されるたびに発生するイベント
    flkty.on('change', function(index) {
      // すべてのimg要素から特定のクラスを削除
      var imgs = elem.querySelectorAll('img');
      imgs.forEach(function(img) {
        img.classList.remove('active-slide-image');
      });
    
      // 新たに表示されるスライドのimg要素にクラスを追加
      var selectedImg = flkty.selectedElement.querySelector('img');
      if (selectedImg) {
        selectedImg.classList.add('active-slide-image');
      }
    });
});
  document.addEventListener('DOMContentLoaded', function() {
    var elem = document.querySelector('.main-gallery-mobile');
    var flkty = new Flickity(elem, {
      autoPlay: 3000,
      wrapAround: true,
      prevNextButtons: true,
      pageDots: false
    });
    // スライドが変更されるたびに発生するイベント
    flkty.on('change', function(index) {
      // すべてのimg要素から特定のクラスを削除
      var imgs = elem.querySelectorAll('img');
      imgs.forEach(function(img) {
        img.classList.remove('active-slide-image');
      });
    
      // 新たに表示されるスライドのimg要素にクラスを追加
      var selectedImg = flkty.selectedElement.querySelector('img');
      if (selectedImg) {
        selectedImg.classList.add('active-slide-image');
      }
    });
});
</script>
<style>
.main-gallery img {
  transition: transform 3s ease-out;
  transition-duration: transform 0.7s ease-out;
  transform: scale(1.2);
}
.main-gallery img.active-slide-image {
  transform: scale(1);
}
.flickity-prev-next-button {
  width: 24px !important;
  height: 24px !important;
}
.slider-cell {
  width: 100%;
  height: 600px;
  background: #fff;
  margin: 0 5px;
  overflow: hidden;
}
.slider-cell img {
  width: 100%;
  height: 100%;
}

@media screen and (max-width: 767px) {
  .pc {
    display: none;
  }
  .slider-cell {
      width: 100%;
      height: 400px;
  }
}
@media screen and (min-width: 768px) {
  .sp {
    display: none;
  }
}
</style>
<!--pc-->
<div class="banner_wrap pc">
  <div class="main-gallery main-gallery-desktop">
  {% for block in section.blocks %}
    <a class="slider-cell" href="{{ block.settings.bnr_url }}">
      {{ block.settings.banner_pc | image_url: width: 2000 | image_tag }}
    </a>
  {% endfor %}
  </div>
</div>
<!--sp-->
<div class="banner_wrap sp">
  <div class="main-gallery main-gallery-mobile">
  {% for block in section.blocks %}
    <a class="slider-cell" href="{{ block.settings.url }}">
      {{ block.settings.banner_sp | image_url: width: 900 | image_tag }}
    </a>
  {% endfor %}
  </div>
</div>
{% schema %}
{
  "name": "スライダー画像",
  "blocks": [
      {
        "name": "image",
        "type": "header",
        "settings": [
          {
            "type" : "image_picker",
            "id" : "banner_pc",
            "label" : "Pick an Image(PC)"
          },
          {
            "type" : "image_picker",
            "id" : "banner_sp",
            "label" : "Pick an Image(SP)"
          },
          {
            "type" : "url",
            "id" : "url",
            "label" : "リンク先"
          }
        ]
      }
    ],
  "presets" : [
    {
      "name" : "スライダー画像",
      "category" : "Custom"
    }
  ]
}
{% endschema %}

おまけ:「バナー画像」、「スライダー画像」制作の常識は固定観念かも?

最近の海外のテーマとか見てると、こんなことしてなくて、トリミング位置が厳格じゃないような一枚の「写真」を登録して、その写真の上にHTMLテキストのフォントをオーバーレイしていることが多いように思う。

「バナー画像」として規定サイズにトリミングした写真に、PhotoShopで文字装飾をした画像を登録する手法ではないのだ。たしかにそれだと、毎回バナー更新するためにデザイナーの手を借りることになるので、運営者が研ぎ澄まされたセンスでフットワーク軽く更新するスタイルなのは海外のテーマの登録方法だ。なので、その制作現場の人員リソースの関係や、運営者が少数だが抑えるポイントとして、素で「よい写真」を使用していこうというポリシーが共有されていれば、いい方法だと思う。

加工が必要になるのは、ある一枚ではイケてない、力の弱い写真しかない場合、という理由もあると思う。今は撮影センスがあればiPhoneでも力のある写真は撮れる。センス大事。。

それに、「写真の上にHTMLテキストのフォントをオーバーレイ」のメリットとしては、「パララックス」や「フォントのみあとからフェードアウト」や「画像のみゆっくりズームアウトしてくる」など、動きのある表現ができる。

Shopifyで、上のようなセクションにさらに手を加えて、スライダー画像の上に文字がオーバーレイするように設計したセクションを用意すれば、そのセクションに登録する画像とテキストの変更だけで特集バナーの運用もノーコード、ノーデザイナーでいける。この体制ではどっちかというと力のある写真を撮れる者がいることが重要になってくる。

素の写真にテキストオーバーレイのバナー画像のPC表示例
素の写真にテキストオーバーレイのバナー画像のSP表示例

余談でしたが、以上です!

Webサイト制作を依頼したい方へ

PRYTHM WORKS(プリズムワークス)は、東京都墨田区、東京スカイツリーのふもとにあるWebコンテンツ制作事務所です。

華々しいおしゃれなECサイトをはじめ、アンダーグラウンドな案件まで幅広くご依頼をいただき、どんな案件でも真心・丁寧・楽しくを理念に掲げて制作しております!

作りたいサービスはあるけど、まずは費用感が知りたい!という方も、まずはお問い合わせください!

mail@prytymworks.tokyo

PRYTHM WORKSが手掛ける仕事の一部をご紹介します。

制作のご依頼者様用 費用かんたんお見積もりフォーム

おそらく本記事を読まれるのは、制作の現場の、法人またはフリーの、プロデューサーの方、ディレクターの方、エンジニアの方がほとんどかと存じます。
いつもおつかれさまです!そして本記事をお読みいただきありがとうございます。
紹介した記事の内容について、またはその他制作のご依頼について、以下のフォームより簡易お見積もりができます!
試算だけならフォーム送信しなくてもできますので、ぜひ試しにいかがでしょう?

お仕事をご希望の制作者様用 お問合せフォーム

また、まずはライトなご相談から…ということであれば、こちらのコンタクトフォームからお気軽にどうぞ!ご縁を大切にしてご返信いたします!

    ShopifyでのECサイト制作を行うならPRYTHMWORKS(プリズムワークス)へ

    ShopifyでのECサイト制作を外注しようとお考えの方は、PRYTHMWORKS(プリズムワークス)にご依頼ください。高品質なWebサイト制作で、お客様のビジネス成長を支援する会社です。Shopifyを使ったECサイト制作に力を入れており、売上向上に貢献するECサイト構築を代行いたします。豊富な経験と実績にもとづき、お客様のニーズに最適なECサイトを構築しますので、費用相場や制作事例など、気になることがございましたらお気軽にお問い合わせください。移行のご相談も承っております。

    社名合同会社PRYTHMWORKS
    事業内容EC/Webサイトの構築、管理保守
    CEO吉川直人
    法人事務所所在地〒150-0001
    東京都渋谷区神宮前六丁目23番4号桑野ビル2階
    設立日2023年(令和5年)7月3日
    沿革2020年(令和2年)10月
    個人事業主PRYTHMWORKS事業開始
    2023年(令和5年)7月
    合同会社PRYTHMWORKS設立

    会社に関するご連絡は以下よりお願いいたします。

    mail@prytymworks.tokyo


    お問い合わせ用LINEはこちらからどうぞ!

    お問い合わせ用LINEはこちらからどうぞ!

    LINE

    GoogleMeetの相談予約が可能になりました!

    以下の空いている日からサクッとGoogleMeet(ビデオ通話)の予約をどうぞ!