[WordPress+Cocoon]スクロール追従サイドバーの目次を着色する方法

スポンサーリンク

対象読者

  • WordPressテーマ「Cocoon」ユーザーの方
  • この件をやろうといろいろコピペしてみたが、失敗した方

結論

WordPressでは、記事上部に目次を自動生成できる。しかし、スクロールすると、折角の目次がフェードアウトしてしまい、記事構造や現在位置が分からなくなってしまう。

そこで、

  • 目次をサイドバーに追従させ、
  • スクロール位置に応じてハイライトさせる

ことで、UXを高めることができる。私のサイドバーの目次を確認していただきたい(デスクトップ限定)。

以下では、これを実現するための手順や補足を説明する。

手順

2つの手順から成る。

  1. サイドバー追従の目次の設定
  2. それをハイライトさせる処理の記述

それぞれの具体的手順は以下だ。

  1. WordPressの管理画面 -> 外観 -> ウィジェット にて、サイドバースクロール追従に「[C]目次」を追加(詳細は参考1)
  2. WordPressの管理画面 -> 外観 -> テーマエディター にて、style.css、javascript.jsに追記(後述のコードをコピペ)

以下では、手順2のコピペ用コードを示す(元にしたのは参考1のコード)。

style.cssへのコピペ

a.current {
    background-color: #EEEEFF;
}

a要素のclass名は何でもいいが、javascript.jsのclass名と対応させる必要がある。

javascript.jsへのコピペ

const GAP     = -50;
const CLSNAME = "current" //cssと対応

class SidebarTOC{
	constructor(selector){
		this.$a = $(`${selector} a`);
	}

	getCurrentAnchor(currentTop){
		var heads = this.getHeads();
		var tops  = heads.map(x => x.offset()["top"]);
		var n_anchor = tops.length - 1;

		for(var i=0; i < n_anchor; i++){
			let first  = tops[i]     + this.GAP;
			let second = tops[i + 1] + this.GAP;
			if(first < currentTop && currentTop < second){
				return $(this.$a[i]);
			}
		}
	}

	getHeads(){
		var arr = [];
		this.$a.each(function(_, a){
			var href = $(a).attr("href");
			arr.push($(href));	
		});
		arr.push($(".article-footer"));
		return arr;
	}

	clear(){
			this.$a.removeClass(CLSNAME);
	}

	inRange(currentTop){
		var tops = this.getHeads().map(x => x.offset()["top"]);
		var min = tops.reduce((a, b) => a < b ? a: b);
		var max = tops.reduce((a, b) => a > b ? a: b);
		return min < currentTop && currentTop < max + this.GAP;
	}
}


$(function(){
   //引数は人によって異なるかも
   //サイドバー目次の属性をF12で確認してください
	 var toc = new SidebarTOC("#sidebar-scroll .toc-content");
    $(window).on('load scroll', function() {
		  toc.clear();
        var wTop = $(window).scrollTop();
		  if(toc.inRange(wTop)){
			  toc.getCurrentAnchor(wTop).addClass(CLSNAME);
		  }
    });
});

このコードはCocoonではないWordPressテーマでも使えると思う。結局、似たような処理をしているし、私のコードの方が整理されているからだ(参考2)。

プラグインTOC+(Table Of Content Plus)による悪影響

私の環境では、目次生成用のプラグインTOC+が入っていた。使っていなかったけど。

見出し要素には、自動でIDが付与されるが、{i, i-2, i-3, …}のようにちょっと不規則に与えられていた。そのせいで、試行錯誤が困難なものとなった。

いくつかの自分の記事をチェックすると、正しく動作しないものがあった。[F12]で確認すると、このような規則に従っていないIDが発見された。

しかし、TOC+を削除すると、IDが規則正しく与えられるようになった。

原因はWordPressテーマの仕様なのか、それとプラグインの干渉なのか、分からない。変なことが起こっている場合、プラグインを掃除するといいかもしれない

コピペカスタマイズの困難さ

私もまずはいろいろググって、コードをコピペしてみたが、正常に動かなかった。

  • JavaScriptを編集 
  • ブラウザの開発ツールを[F12]キーで開きつつ、自分の記事を確認

を繰り返し、遂に動作させることができた。

人ごとに環境が異なるため、コードを修正する必要があるかもしれない。故に、処理が分離してあり、理解しやすいコードじゃないと苦労する

私のコードはまあまあ分かりやすく書けていると思う。letとvarが混在していてキモかったりするけどw。

処理を分離することの重要さや綺麗なコードを書く方針について、以下の記事にまとめたので、是非、参考にしてくだされ。

[文法以前の超入門]プログラミングの本質は抽象化にある

 

参考

  1. Cocoon記事のスクロールに連動して見出しがマークされる目次
  2. 【Luxeritas】サイドバーにQiita風目次を設置

コメント

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