目次プラグインは便利なので利用している人は多いでしょう。しかし、ブロックエディタを使っていると見出しの飛び先がずれるという現象に出くわします。
例えば、目次プラグインなどで挿入した目次から見出しにジャンプする時にズレたり(手前の変な位置で止まる)、ズレなかったりということがあります。
この記事では、目次プラグインを使用した時にジャンプした時に見出しからずれてしまう原因と対策をまとめています。
目次プラグインの飛び先がずれてしまう原因
実は、この現象は、LazyLoadプラグインを使用して、スムーズスクロールを使用している組合せで発生します。
LazyLoadプラグインで画像を遅延読み込みしていると、スムーズスクロールなどのJavascriptで計算した見出し位置がスクロール中に変わります。画像が読み込まれる前と後では見出しの位置が下がるので、ズレが発生するわけです。
この現象は、imgタグにheightとwidthがあればLazy Loadを使用していても問題が起きないケースもありますが、残念なことにブロックエディタを使用しているとimgタグにheightとwidthは初期状態で付加されません。そのため、ブロックエディタの使用率が高まるにつれて目次プラグインとLazyLoadプラグインを併用している時に見出しにジャンプする時にズレるという現象が起きやすくなっています。
目次プラグインの飛び先がずれる場合の対策は?
対策は、対処療法的なものを含めると結構あります。
LazyLoadプラグインを使用しない
原因が画像の遅延読み込みなので、LazyLoadプラグインを使用しなければ問題は起きません。
Page Speed Insightの点数を上げるためにLazyLoadプラグインを導入している人がほとんどだと思いますので、この対策を採用するケースはまずないと思います。
スムーズスクロールをやめる
スムーズスクロールするために、飛び先の見出し位置を計算するのが間違いの原因なので、スムーズスクロールそのものをやめることで、飛び先の位置がずれることは無くなります。
プラグインを使用して目次を入れる場合は、以下の2つのどちらかでしょう。
このうち、easy-table-of-contentsはプラグインの機能としてsmooth scrollをサポートしていますが、 table-of-contents-plusは smooth scrollの機能はついていません。
目次の見出しをクリックして飛び先がずれる現象は、 easy-table-of-contents プラグインを使用している場合に発生しますが、 table-of-contents-plusプラグインを使用している場合には発生しないことになります。
easy-table-of-contents プラグインは、smooth scrollオプションをOFFにすることができます。OFFにすれば、問題は発生しません。ただし、smooth scrollオプションをOFFにするとジャンプする時にどこに飛んだのかわかりにくいのでできればOFFにしないで済ませたいところです。
imgタグにheightとwidthを追加する
ブロックエディターを使用する以前、classicエディタの時代はimgタグにheightとwidthが付加されれるのを嫌っていました。ブロックエディタで画像ブロックで画像を挿入すると、heightとwidthはHTMLに付加されません。
imgタグにheightとwidthがあると、 LazyLoadを使用しても飛び先の見出し位置の計算時にズレが無くなります。
ブロックエディタでimgタグにheightとwidthを追加する方法
ブロックエディタの画像ブロックを使用していても、imgタグにheightとwidthを追加することができます。
完全自動ではないので少し面倒ですが、仕組みとして存在するということは覚えておいて損はありません。
100%という部分をクリックすると、HTMLタグにheightとwidthが挿入されます。
スムーズスクロールを改造する
easy-table-of-contentsはプラグインを使っている場合にはSmooth scrollのjQueryプラグインが組み込まれています。
プラグインのjavascriptを改造することでLazyloadプラグインを使用していても目次クリック時の飛び先のずれを無くすことができます。
修正の考え方はシンプルです。smooth scrollのjQueryの実行前後で飛び先の位置を保存、お互いに比較して違う場合は再度smooth scrollを実行するという流れを、違いがなくなるまで繰り返します。javascriptの場合は手続き的に書きにくいのですが、幸いcallback関数が使えるので再帰的に呼び出しています。
front.jsを改造
if ( target ) {
_smoothScroll(target,offset);
// $.smoothScroll( {
// scrollTarget: target,
// offset: offset,
// beforeScroll: deactivateSetActiveEzTocListElement,
// afterScroll: function() { setActiveEzTocListElement(); activateSetActiveEzTocListElement(); }
// } );
}
// ======================================
// 移動に失敗したら追加で移動するカスタマイズ
// ======================================
function _smoothScroll(target,offset) {
var old,now;
$.smoothScroll( {
scrollTarget: target,
offset: offset,
beforeScroll: function(){
//移動先を保存
old = $(target).offset().top;
deactivateSetActiveEzTocListElement(); // ()を追加
},
afterScroll: function() {
now = $(target).offset().top;
setActiveEzTocListElement();
activateSetActiveEzTocListElement();
if(now != old){
//もう一度スクロール
_smoothScroll(target,offset);
}
}
} );
}
front.jsを差し替える
function add_theme_scripts() {
wp_dequeue_script( 'ez-toc-js' );
wp_deregister_script( 'ez-toc-js' );
wp_enqueue_script( 'ez-toc-js', get_stylesheet_directory_uri() . "/assets/js/front.js", array( 'jquery-smooth-scroll', 'js-cookie', 'jquery-sticky-kit'),1.0, TRUE );
}
add_action( 'wp_enqueue_scripts', 'add_theme_scripts' );
まとめ
プラグインのjavascriptを変更するのは、メンテナンスのことを考えると避けたいのですが、個人的に興味があったのでLazyLoadプラグインと目次プラグインで見出しの飛び先がずれる問題を解決してみました。