お問い合わせはコチラから

Cocoonでポップアップする目次を導入する

サイト運営

SWELLにある『目次がモーダルでポップアップする機能』をCocoonでも導入することができます。

ぽんひろさんの以下の記事に詳細が書かれているので、Cocoonでしたら基本コピペでOKです。

【Cocoon】スマホで目次を追従させる方法
WordPressテーマ「Cocoon」利用者むけのスマホで目次を追従するカスタマイズです。縦長になりがちなスマホにオススメのカスタマイズです。離脱率も下がるかもしれません!コピペで簡単なのでぜひやって見てください。

個人的に気になったところ

  1. wp_is_mobile()が使われている
    • PC/SPのキャッシュが分かれていない場合、キャッシュプラグインとの相性が悪そう
  2. jQueryでスクリプトが書かれている
    • 非jQueryな人はjQueryを読み込まないといけない
  3. モーダル表示時に背景がスクロールしてしまう
    • 目次がスクロールする場合に操作できなくなることがある

気になったところを変更してみる

wp_is_mobile()が使われている

SPの時だけスクリプト全体を読み込むように条件判定している部分にwp_is_mobile()があります。

wp_is_mobile()はキャッシュプラグインと相性が悪いので避けたいです。

修正方法としては、2つ方法があります。

  • PCでも目次を表示する
    • wp_is_mobile()をソースから消すだけでいいです。
  • PCでは目次を表示しない
    • wp_is_mobile()をソースから消して、かつ、目次ボタンをCSSで消してあげればいいです。

変更前

<?php if ( wp_is_mobile()  && is_single()) : ?>
<?php if(is_active_sidebar('mobile_toc_widget')) : ?>
<div id="mobile-toc-widget-wrap">	
    <label for="mobile-toc">
    <div class="mobile-toc-button">
      <div class="menu-trigger">
      <span></span>
      <span></span>
      <span></span>
      </div>
     <span class="mobile-toc-button-title">目次</span>
    </div>
  </label>
    <input type="checkbox" id="mobile-toc"/>
    <div class="mobile-toc-show">
      <div class="mobile-toc-widget">	      
      <?php dynamic_sidebar('mobile_toc_widget'); ?>      
      </div>
    </div>
</div>
<script>
:
</script>
<?php endif; ?>
<?php endif; ?>

変更後(wp_is_mobileを削除)

<?php if ( is_single()) : ?>
<?php if(is_active_sidebar('mobile_toc_widget')) : ?>
<div id="mobile-toc-widget-wrap">	
    <label for="mobile-toc">
    <div class="mobile-toc-button">
      <div class="menu-trigger">
      <span></span>
      <span></span>
      <span></span>
      </div>
     <span class="mobile-toc-button-title">目次</span>
    </div>
  </label>
    <input type="checkbox" id="mobile-toc"/>
    <div class="mobile-toc-show">
      <div class="mobile-toc-widget">	      
      <?php dynamic_sidebar('mobile_toc_widget'); ?>      
      </div>
    </div>
</div>
<script>
//スマホ目次追尾
jQuery('#mobile-toc-widget-wrap label').on('click', function() {
    jQuery('.menu-trigger').toggleClass('active');
});
jQuery('#mobile-toc-widget-wrap .toc-list a').on('click', function() {
    jQuery('.menu-trigger').toggleClass('active');
});
jQuery('#sidebar-menu-input').on('click', function() {
    if (jQuery('#sidebar-menu-input').prop('checked')) {
        jQuery('#mobile-toc-widget-wrap').css('display', 'none');
    }else{
    jQuery('#mobile-toc-widget-wrap').css('display', 'block');
  }
});
jQuery('#mobile-toc-widget-wrap .toc-list a').click(function() {
    if (jQuery('#mobile-toc-widget-wrap input').prop('checked')) {
        jQuery('#mobile-toc-widget-wrap input').prop('checked', false);
    }
});

//スムーススクロール
jQuery(function () {
 var headerHight = 50; 
 jQuery('a[href^="#"]').click(function(){
     var href= jQuery(this).attr("href");
       var target = jQuery(href == "#" || href == "" ? 'html' : href);
        var position = target.offset().top-headerHight;
     jQuery("html, body").animate({scrollTop:position}, 550, "swing");
        return false;
   });
});
</script>
<?php endif; ?>
<?php endif; ?>

PCでは表示しない場合(目次ボタンをCSSで消す)

ブレークポイントはテキトウです。

@media screen and (min-width: 960px){
#mobile-toc-widget-wrap{display:none;}
}

jQueryでスクリプトが書かれている

スマホ追従目次の部分のjavascriptがjQueryで書かれています。

非jQueryな人はVanilla JSに書き換えたバージョンに差し替えます。

スムーススクロールは、こちらから拝借しました。

【JavaScript】スムーススクロールをjQueryを使わずにシンプルに実装する【Vanilla JS】 – ノーズブログ

jQuery

<script>
//スマホ目次追尾
jQuery('#mobile-toc-widget-wrap label').on('click', function() {
    jQuery('.menu-trigger').toggleClass('active');
});
jQuery('#mobile-toc-widget-wrap .toc-list a').on('click', function() {
    jQuery('.menu-trigger').toggleClass('active');
});
jQuery('#sidebar-menu-input').on('click', function() {
    if (jQuery('#sidebar-menu-input').prop('checked')) {
        jQuery('#mobile-toc-widget-wrap').css('display', 'none');
    }else{
    jQuery('#mobile-toc-widget-wrap').css('display', 'block');
  }
});
jQuery('#mobile-toc-widget-wrap .toc-list a').click(function() {
    if (jQuery('#mobile-toc-widget-wrap input').prop('checked')) {
        jQuery('#mobile-toc-widget-wrap input').prop('checked', false);
    }
});

//スムーススクロール
jQuery(function () {
 var headerHight = 50; 
 jQuery('a[href^="#"]').click(function(){
     var href= jQuery(this).attr("href");
       var target = jQuery(href == "#" || href == "" ? 'html' : href);
        var position = target.offset().top-headerHight;
     jQuery("html, body").animate({scrollTop:position}, 550, "swing");
        return false;
   });
});
</script>

Vanilla JS

//スマホ目次追尾
var el = document.querySelector('#mobile-toc-widget-wrap label');
var toggle_el = document.querySelector('.menu-trigger');

el.onclick = function() {
  toggle_el.classList.toggle('active');
}

var alinks = document.querySelectorAll("#mobile-toc-widget-wrap .toc-list a")

var el_input = document.querySelector('#sidebar-menu-input');
var el_wrap = document.querySelector('#mobile-toc-widget-wrap');
if(el_input){
	el_input.onclick = function() {
		if(el_input.checked){
			el_wrap.style.display = "none";
		}else{
			el_wrap.style.display = "block";
		}
	}
}

const el2 = document.querySelector('#mobile-toc-widget-wrap input');

for (i = 0; i < alinks.length; i++) {
  alinks[i].onclick =function(){
	  if(el2.checked){
		  el2.checked=false;
	  }
	  toggle_el.classList.remove('active');
  }
}

//スムーススクロール
	var scrollElm = (function() {
  if('scrollingElement' in document) return document.scrollingElement;
  if(navigator.userAgent.indexOf('WebKit') != -1) return document.body;
  return document.documentElement;
})();
(function() {
  var headerHight = 60; 
  var duration = 500;
  var ignore = '.noscroll';
  var easing = function (t, b, c, d) { return c * (0.5 - Math.cos(t / d * Math.PI) / 2) + b; }; //jswing
  var smoothScrollElm = document.querySelectorAll('a[href^="#"]:not(' + ignore +')');
  Array.prototype.forEach.call(smoothScrollElm, function(elm) {
    elm.addEventListener('click', function(e) {
      e.preventDefault();
      var targetElm = document.querySelector(elm.getAttribute('href'));
      if(!targetElm) return;
      var targetPos = targetElm.getBoundingClientRect().top - headerHight ;
      var startTime = Date.now();
      var scrollFrom = scrollElm.scrollTop;
      (function loop() {
        var currentTime = Date.now() - startTime;
        if(currentTime < duration) {
          scrollTo(0, easing(currentTime, scrollFrom, targetPos, duration));
          window.requestAnimationFrame(loop);
        } else {
          scrollTo(0, targetPos + scrollFrom);
        }
      })();
    })
  });
})();

モーダル表示時に背景がスクロールしてしまう

iOSのモーダル表示時の背景スクロール問題は結構有名ですので、他の方が解決した方法を借用します。

モーダルウインドウを背景固定にしてスクロールバー分のガタつき問題を解決しつつ、iOS Safariにも対応してしかもjQuery非依存にしたいワガママなアナタへ捧ぐ愛のコード | ma-ya's CREATE / WEB DESIGN
もはやモーダルウインドウの実装なんて当たり前の要件となってきた昨今、サクッとプラグインを使えば、世の中の優秀なフロントエンド開発者が実装した機能を簡単に使うことができますね。ただそれでも、JSに対する興味や情熱から、自前のコードで実装したい...

適用の仕方は簡単なので概要だけ。

.active classがトグルした時のactive classの有無で、スクロール固定と解除を切り替えればいいです。

注意点としては、addEventListenerOnce(modal, ‘transitionend’, function () {})が引っかかる場合があるので、その場合はコメントアウトすれば大丈夫。

最終形(モーダル背景固定は含まず)

<?php
add_action('wp_footer',function(){ ?>
<?php if ( is_single()) : ?>
<?php if(is_active_sidebar('mobile_toc_widget')) : ?>

<div id="mobile-toc-widget-wrap">	
    <label for="mobile-toc">
    <div class="mobile-toc-button">
      <div class="menu-trigger">
      <span></span>
      <span></span>
      <span></span>
      </div>
     <span class="mobile-toc-button-title">目次</span>
    </div>
  </label>
    <input type="checkbox" id="mobile-toc"/>
    <div class="mobile-toc-show">
      <div class="mobile-toc-widget">	      
      <?php dynamic_sidebar('mobile_toc_widget'); ?>      
      </div>
    </div>
</div>
<script>
//スマホ目次追尾
var el = document.querySelector('#mobile-toc-widget-wrap label');
var toggle_el = document.querySelector('.menu-trigger');

el.onclick = function() {
  toggle_el.classList.toggle('active');
}

var alinks = document.querySelectorAll("#mobile-toc-widget-wrap .toc-list a")

var el_input = document.querySelector('#sidebar-menu-input');
var el_wrap = document.querySelector('#mobile-toc-widget-wrap');
if(el_input){
	el_input.onclick = function() {
		if(el_input.checked){
			el_wrap.style.display = "none";
		}else{
			el_wrap.style.display = "block";
		}
	}
}

const el2 = document.querySelector('#mobile-toc-widget-wrap input');

for (i = 0; i < alinks.length; i++) {
  alinks[i].onclick =function(){
	  if(el2.checked){
		  el2.checked=false;
	  }
	  toggle_el.classList.remove('active');
  }
}

	var scrollElm = (function() {
  if('scrollingElement' in document) return document.scrollingElement;
  if(navigator.userAgent.indexOf('WebKit') != -1) return document.body;
  return document.documentElement;
})();
(function() {
  var headerHight = 60; 
  var duration = 500;
  var ignore = '.noscroll';
  var easing = function (t, b, c, d) { return c * (0.5 - Math.cos(t / d * Math.PI) / 2) + b; }; //jswing
  var smoothScrollElm = document.querySelectorAll('a[href^="#"]:not(' + ignore +')');
  Array.prototype.forEach.call(smoothScrollElm, function(elm) {
    elm.addEventListener('click', function(e) {
      e.preventDefault();
      var targetElm = document.querySelector(elm.getAttribute('href'));
      if(!targetElm) return;
      var targetPos = targetElm.getBoundingClientRect().top - headerHight ;
      var startTime = Date.now();
      var scrollFrom = scrollElm.scrollTop;
      (function loop() {
        var currentTime = Date.now() - startTime;
        if(currentTime < duration) {
          scrollTo(0, easing(currentTime, scrollFrom, targetPos, duration));
          window.requestAnimationFrame(loop);
        } else {
          scrollTo(0, targetPos + scrollFrom);
        }
      })();
    })
  });
})();

</script>

<?php },99);

まとめ

脱jQueryが当たり前になってきていますが、オリジナルのjQueryのスクリプトがダメというわけではありません。

jQueryライブラリを読み込んでいるのであれば、この程度の記述量だったら違いはないと思います。

jQueryライブラリを読み込みたくない人には役にたつかもしれませんが、Cocoon自体がjQueryを読み込んでるという・・・

この記事を書いた人
ブーン

はるばる日本よりオランダ王国へやってまいりました。
自分の経験が少しでも参考になれば嬉しいです。
お問い合わせは、『こちら』からお願い致します。

\ブーンをフォロー/
スポンサーリンク
サイト運営
\シェアお願いします!/
\ブーンをフォロー/
こんな記事も読まれています

失敗しないレンタルサーバーランキング

mixhost

不正アクセスに強くて使いやすいおススメサーバー
\本サイトで利用中/
メリット①:自動ウィルス駆除対応
メリット②:サイトの表示速度が速い!
メリット③:転送量の上限が多い!
メリット④:自由にプラン変更ができ、アクセス増にも対応できる!
メリット⑤:バックアップデータが無料で復元できる!
メリット⑥:Wordpressが簡単にインストールできる!
メリット⑦:どのプランでも初期費用が無料!
メリット⑧:10日間の無料お試し期間と30日の返金保証!

Conoha Wing

国内Wordpress最速の最強サーバー
メリット①:圧倒的な表示速度
メリット②:レンタルサーバーと独自ドメインがセットでお得◎
メリット③:プラン変更はすべてのプランで自由自在
メリット④:一か月の利用転送量の制限が緩い(9TB~)
メリット⑤:WordPresサイトの移行が簡単

エックスサーバー

国内シェアNo1の安定性と実績が魅力。ALL SSDで死角なしの万能サーバー。
メリット①:サイトの表示速度が安定して速い!
メリット②:アクセス負荷に強くて安定性が高い!
メリット③:24時間365日の充実サポートで安心!電話サポートもあり!
メリット④:転送量が多い!
メリット⑤:自動バックアップ機能付き!
メリット⑥:WordPressが簡単にインストールできる!
メリット⑦:10日の無料お試し期間がある!

タイトルとURLをコピーしました