Cocoon の一覧リストにスクロールアニメーションを適用するカスタマイズ

Akira

福岡在住の Web デザイナー。Web サイト制作に役立つ情報を紹介しています。AMP が大好き。

FacebookTwitter で記事の更新をお知らせしています。

WordPress テーマ Cocoon の一覧リストに、スクロールに応じたアニメーションを実装するカスタマイズの紹介です。

カスタマイズは 3 ステップの 100% コピペででき、カスタマイズ所要時間は 2 ~ 3 分ほどです。

動作

完成図は、下の動画のとおりです。画面内に入ったカードが、ふんわりと表示されます。

執筆時点の Cocoon の一覧リストには、7 種類のカードタイプがあります。どのカードタイプを選んでも、今回のアニメーションを実装できます。

IE・Safari・iOS で動くようにする

今回の方法は、そのままでは IE と Safari、iOS でアニメーションが動きません。

下記の 2 つの条件のどちらにも該当する場合は、対策が必要です。

  • IE と Safari、iOS でもアニメーションを動かしたい
  • Cocoon 設定の「高速化」で「Lazy Load を有効にする」が無効になっている

IE と Safari、iOS でアニメーションが動く必要がなければ、次のステップに進みます。また、Cocoon 設定の「高速化」で「Lazy Load を有効にする」が有効になっている場合も、次のステップに進みます。

2 つの条件のどちらにも該当する場合は、intersection-observer.js を子テーマの javascript.js に追加します。

やり方は簡単です。上記リンクを開いた後に「Raw」をクリックすると、ブラウザのタブにコードが表示されます。

表示されたコードを ctrl + a で全て選択後にコピーをし、子テーマの javascript.js の 1 番上(javascript.js に最初から書かれている説明後の 4 行目から)に貼り付けます。貼り付け後の javascript.js の状態は、下記のとおりです。

//ここに追加したいJavaScript、jQueryを記入してください。
//このJavaScriptファイルは、親テーマのJavaScriptファイルのあとに呼び出されます。
//JavaScriptやjQueryで親テーマのjavascript.jsに加えて関数を記入したい時に使用します。
/**
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the W3C SOFTWARE AND DOCUMENT NOTICE AND LICENSE.
 *
 *  https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
 *
 */
(function() {
'use strict';

// Exit early if we're not running in a browser.
if (typeof window !== 'object') {
  return;
}
以下省略

今後、javascript.js にコードを書く場合は、追加したコードの下に書いていきます。

これで IE と Safari、iOS でもアニメーションが動きます。

尚、追加する intersection-observer.js は 700 行を超えるため、「Minify your JavaScript」「Online JavaScript/CSS/HTML Compressor」などでコードを縮小した後に追加しても構いません(縮小すると 1 行になります)。

Cocoon 設定の「Lazy Load を有効にする」が有効の場合は、親テーマが intersection-observer.js を読み込みます。そのため、「Lazy Load を有効にする」が有効の時は、何もせずとも IE・Safari・iOS でもアニメーションが動きます。

JavaScript を追加

次に、子テーマの javascript.js にコードを追加します。

ただ、アニメーションの動く回数が異なる 2 つのコードがあります。お好みに合わせて、コードを選択します。

何回でもアニメーションが動くコード

一覧リストのカードが画面内に入る度に、アニメーションが動くタイプです。

何回でもアニメーションを動かしたい場合は、下記のコードを子テーマの javascript.js に追加します。

(function() {
  const list = document.querySelectorAll('.entry-card-wrap');
  
  const observer = new IntersectionObserver(function(entries) {
    entries.forEach(function(entry) {
      if (entry.intersectionRatio > 0) {
        entry.target.classList.add('list-animation');
      } else {
        entry.target.classList.remove('list-animation');
      }
    });
  });
  
  Array.prototype.forEach.call(list, function(card) {
    observer.observe(card);
  });
})();

1 回のみアニメーションが動くコード

一覧リストのカードが最初に画面内に入った時のみ、アニメーションが動くタイプです。1 度アニメーションが動いたカードは、再び画面内に入ってもアニメーションが動きません。

何回もアニメーションが動くのは避けたい場合は、下記のコードを子テーマの javascript.js に追加します。

(function() {
  const list = document.querySelectorAll('.entry-card-wrap');
  
  const observer = new IntersectionObserver(function(entries) {
    entries.forEach(function(entry) {
      if (entry.intersectionRatio > 0) {
        entry.target.classList.add('list-animation');
        observer.unobserve(entry.target);
      }
    });
  });
  
  Array.prototype.forEach.call(list, function(card) {
    observer.observe(card);
  });
})();

CSS を追加

最後に CSS を指定すれば終わりです。

子テーマの style.css に、下記の CSS を追加します。

.list {
  overflow: hidden;
}

.list-animation {
  animation: list-animation 1.2s cubic-bezier(.4, 0, .2, 1);
}

@keyframes list-animation {
  from {
    opacity: 0;
    transform: scale(1.1) translateY(24px);
  }
  
  32% {
    opacity: 0;
    transform: scale(1.1) translateY(24px);
  }
}

これで完成です。

おわりに

さらにカスタマイズをすれば、関連記事や投稿記事内の画像などにも今回のアニメーションを適用できます。

また、CSS の @keyframes を変更することで、お好みのアニメーションを表現できます。

今回の Intersection observer によるアニメーションの詳細は、「Intersection observer によるスクロールアニメーション」で説明しています。

コメント

  1. Akiraさん、こんにちは。

    今日ようやくcocoonに1サイト更新しました。

    早速、こちらのアニメーションを使わせて貰ってます。ありがとうございます!

    ひとつ、質問ですがPCでは、ちゃんと動作するのですが、スマホでは動いてないように見えます。こちらはPCだけの設定でしょうか?

    それと、要望みたいなものですが、サイトタイトルなどのアニメーションについて、記事を作成して貰えると助かります。

    simplicityの時には、出来ていたのですがcocoonになって動かなくなってしまいました。たとえば、上から降りてくるとか、右から出てくるとかです。

    動きがあったほうが、なんか華やかで良い感じがします。もし出来たらで良いのでお願いします。

    • こんにちは。

      ご参考くださり、ありがとうございます。

      スマホで動かない原因は、 2 つ考えられます。

      1 つ目は、ブラウザのキャッシュが邪魔をしていることです。

      2 つ目は、記事内で提示していた CSS です。 Cocoon の高速化設定で「 CSS を縮小化する」を有効にしている時に、提示していた CSS の一部が削除されてしまいました…。意図しないアニメーションになるため、 CSS を一部変更しています。具体的には、 @keyframes0%from に変更しました。

      原因がどちらでもない場合には、サイトを拝見したいところです。

      サイトタイトルなどのアニメーションは、 Simplicity で動いていた CSS などを貼り付けていただければ、こちらで Cocoon で動くように微調整します。

  2. おはようございます。

    二つ目のサイトもcocoon化してみました。
    https://chan-bike.com/
    スマホ表示は同じで動作してないようです。

    アニメーションは、はてなブログで使っていたものです。
    wordpressでは、タイトルとサブタイトルが動いてました。

    /**********アニメーション設定**********/
    /*右から左*/
    @keyframes RightToLeft {
    0% {
    opacity: 0;/* 透明 */
    transform: translateX(50px);/* X軸方向に50px */
    }
    100% {
    opacity: 1;/* 不透明 */
    transform: translateX(0);/* X軸方向に0px */
    }
    }

    /*上から下*/
    @keyframes SlideDown {
    0% {
    opacity: 0;/* 透明 */
    transform: translateY(-50px);/* Y軸方向に-50px */
    }
    100% {
    opacity: 1;/* 不透明 */
    transform: translateY(0);/* Y軸方向に0px */
    }
    }

    /*下から上*/
    @keyframes SlideUp {
    0% {
    opacity: 0;/* 透明 */
    transform: translateY(50px);/* Y軸方向に50px */
    }
    100% {
    opacity: 1;/* 不透明 */
    transform: translateY(0);/* Y軸方向に0px */
    }
    }
    /**********アニメーション設定end**********/

    /*ヘッダーを上から下へ*/
    #site-name {
    animation-name: SlideDown;/* アニメーション名 */
    animation-duration: 2s;/* アニメーション時間 */
    }

    /*グローバルナビを上から下へ*/
    /*
    #menu-menu {
    animation-name: SlideDown;
    animation-duration: 2s;
    }
    */

    /*サイトの副タイトル*/
    #site-description {
    animation-name: SlideDown;/* アニメーション名 */
    animation-duration: 2s;/* アニメーション時間 */
    }

    /*記事一覧を下から上へ*/
    .home blog logged-in admin-bar customize-support {
    animation-name: SlideUp;/* アニメーション名 */
    animation-duration: 2s;/* アニメーション時間 */
    }

    /*記事タイトルを右から左へ*/
    .entry-title {
    animation-name: RightToLeft;/* アニメーション名 */
    animation-duration: 2s;/* アニメーション時間 */
    }

    /* 「RightToLeft」を適用する箇所 */
    h1 {
    animation-duration: 2s;/* アニメーション時間 */
    animation-name: RightToLeft;/* アニメーション名 */
    }

    • スマホで確認したところ、一応アニメーションは動いてはいます。

      ただ、サイトが遅く重いために、速くスクロールするとアニメーションがスムーズに動いていません。特に画像が重いため、 PC よりパワーのないスマホで影響が出ています。

      対策として考えられるのは、下記の 3 つです。

      • サイトスピードを根本的に速くする
      • 今回のカスタマイズを止める
      • 今回の JavaScript のコードを変更する

      1 番良いのは、サイトスピードの改善です。 Test My Site の計測結果が、 2 ~ 3 秒であるのが理想的です。とりあえず簡単にできそうなことは、画像の圧縮と、 Cocoon の高速化設定で「ブラウザキャッシュの有効化」を有効にすることだと思います。

      今回の JavaScript のコードを変更する場合には、子テーマの javascript.js に追加したコードを下記のコードに変更します。

      ( function() {
          const list = document.querySelectorAll( '.entry-card-wrap' );
          
          const observer = new IntersectionObserver( function( entries ) {
              entries.forEach( function( entry ) {
                  if( entry.intersectionRatio > 0 ) {
                      entry.target.classList.add( 'list-animation' );
                  } else {
                      entry.target.classList.remove( 'list-animation' );
                  }
              });
          }, {
              rootMargin: '40px 0px',
          });
          
          Array.prototype.forEach.call( list, function( card ) {
              observer.observe( card );
          });
      })();

      カードが画面内に入る 40px 手前で、アニメーションが動き出す内容です。 13 行目の 40px を調整することで、タイミングを変更できます。値が大きければ大きいほど、アニメーションが早く動き出します。ただ、対症療法なので、全てに完全には対応できないと思います。

      サイトタイトルなどのアニメーションは、下記の CSS で Cocoon でも動きます。

      /**********アニメーション設定**********/
      /*右から左*/
      @keyframes RightToLeft {
        from {
          opacity: 0;/* 透明 */
          transform: translateX(50px);/* X軸方向に50px */
        }
      }
      
      /*上から下*/
      @keyframes SlideDown {
        from {
          opacity: 0;/* 透明 */
          transform: translateY(-50px);/* Y軸方向に-50px */
        }
      }
      
      /*下から上*/
      @keyframes SlideUp {
        from {
          opacity: 0;/* 透明 */
          transform: translateY(50px);/* Y軸方向に50px */
        }
      }
      /**********アニメーション設定end**********/
      
      /*ヘッダーを上から下へ*/
      .header-in {
        animation: SlideDown 2s;
      }
      
      /*記事一覧を下から上へ*/
      .list {
        animation: SlideUp 2s;
      }
      
      /*記事タイトルを右から左へ*/
      .entry-header {
        overflow: hidden;
      }
      
      .entry-title {
        animation: RightToLeft 2s;
      }
  3. アニメーション動きました。
    タイトルのアニメ設定もばっちりです! ありがとうございます。

    サイト計測してみると7秒と5秒でした。

    画像ですが、EWWW Image Optimizerが入っているので問題ないと考えていました。
    一括で最適化もしてみましたが、かわりませんでした。

    htaccess も確認してみましたが、ちゃんと反映されているようです。

    サイト高速化するアドバイスがあればお願いします。

    • どちらのアニメーションも動いてよかったです。

      今 Test My Site で計測してみると、さらに速くなって 4 秒でした。十分な速さだと思います。昼に計測した時は 13 ~ 15 秒でしたので、その時間帯だけ何かしらの理由で遅くなっていたのかもしれません。

      また、昼は PageSpeed Insights で画像やキャッシュに対して注意がなされていたのですが、現在は注意されていません。なので、特に高速化対策は必要ないと思います。

      ただ、体感できるほど速くはならないと思いますが、私であれば下記のコードを子テーマの function.php に追加します。

      add_action( 'wp_enqueue_scripts', function() {
          if( is_page( 7 ) === false ) {
              wp_dequeue_style( 'contact-form-7' );
              wp_dequeue_script( 'contact-form-7' );
          }
      });

      「メールください」の固定ページ(ページ id は 7 )以外では、 Contact Form 7 のスタイルシートとスクリプトを読み込まない内容です。

      Contact Form 7 の読み込みは少し遅いので、お問い合わせページ以外では読み込む必要はないかなと思います。

  4. 大変ありがとうございました。
    高速化についても、もう少し頑張ってみます。

    また、よろしくお願いします。

送信に失敗しました

ボットと判定された可能性があります。

大変お手数をおかけしますが、以下の内容をご確認の上、再度のコメントの送信をお願い申し上げます。