SWELLの記事で、2つ目以降のH2見出しの直前に「目次に戻る」リンクを追加する方法です。実際に本文内の目次がある場合だけ追加し、ブログパーツやモーダル内の見出しを対象から外します。この記事自体でも同じJavaScriptが動いています。
動く見本と適用範囲
次の見出しから表示される「目次に戻る」をクリック、またはTabで選んでEnterを押すと、本文の目次へ戻ります。記事を読み直すための補助リンクです。最初のH2、目次のない記事、H2が1つだけの記事には追加しません。
以下のPHPは通常の投稿ページだけが対象です。カテゴリーアーカイブ、固定ページ、カスタム投稿タイプには適用しません。SWELLの本文と目次のHTML構造を前提にしているため、他テーマ共通のコードではありません。
PHPを子テーマまたはスニペットに追加する
変更前をバックアップし、子テーマのfunctions.phpのPHP内、またはCode SnippetsのPHPスニペットのどちらか一方へ追加します。PHP開始タグは既存のタグ内に重ねません。親テーマや記事のカスタムHTMLブロックへPHPを貼らないでください。
add_action('wp_footer', function () {
if (!is_singular('post')) return;
?>
<script>
(() => {
const init = () => {
const body = document.querySelector('#main_content article .post_content');
if (!body || body.dataset.wazaBackReady) return;
const toc = body.querySelector('.p-toc:not(.-modal)');
if (!toc || toc.closest('.post_content') !== body) return;
const headings = [...body.querySelectorAll('h2')].filter(h =>
h.closest('.post_content') === body && !h.closest('.p-toc, .p-blogParts, dialog, details')
);
if (headings.length < 2) return;
const id = toc.id || 'waza-main-toc';
const occupied = document.getElementById(id);
if (occupied) { if (occupied !== toc) return; }
toc.id = id;
if (!toc.hasAttribute('tabindex')) toc.tabIndex = -1;
body.dataset.wazaBackReady = '1';
headings.slice(1).forEach(heading => {
const wrapper = document.createElement('p');
wrapper.className = 'waza-back-toc';
const link = document.createElement('a');
link.href = '#' + id;
link.textContent = '目次に戻る';
link.addEventListener('click', () => toc.focus({ preventScroll: true }));
wrapper.append(link);
heading.before(wrapper);
});
};
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init, { once: true });
} else {
init();
}
})();
</script>
<?php
});旧版のmotoki_back_tocとmotoki_add_toc_idは先に停止します。旧版のHTML置換と今回のJavaScriptを同時に動かすと、リンクが重複する原因になります。
余白と固定ヘッダーの重なりを調整する
次のCSSを追加CSSか子テーマのstyle.cssへ貼ります。120pxは移動先の上側に確保する余白です。固定ヘッダーの高さに合わせて変更してください。既存の目次に独自IDが付いている場合は、先頭のセレクターをそのIDに合わせます。
#waza-main-toc { scroll-margin-top: 120px; }
.waza-back-toc { margin: 2em 0 .5em; text-align: right; }
.waza-back-toc a:focus-visible { outline: 3px solid #1769aa; outline-offset: 3px; }仕組み:本文の目次を見つけてからリンクを作る
PHPで本文の文字列に一律でリンクを差し込むのではなく、ページ内の目次と見出しを確認してから作成します。リンク先は本文内の目次です。画面下部などにあるモーダル用の目次は使いません。既存の目次IDは維持し、IDがない場合だけwaza-main-tocを付けます。
リンクのクリック時には目次へフォーカスも移します。JavaScriptが使えない場合は追加リンクが出ませんが、元の記事と目次はそのまま読めます。動的に後から追加される見出しを監視するコードではありません。
確認方法と元に戻す方法
保存後にキャッシュを消し、公開ページで2つ目以降のH2にだけリンクが付くか確認します。目次がない記事には追加されないこと、リンクをEnterで実行して本文の目次へ戻れること、固定ヘッダーに隠れないことをPCとスマホ幅で確認してください。
戻す場合は追加したPHPスニペットを無効化するか、そのPHPとCSSを取り除きます。記事本文を書き換える処理ではないため、各記事からリンクを削除して回る必要はありません。SWELLのHTML構造や遅延実行設定が変わった場合は再確認してください。
旧GitHub例とは同期していないため、この本文のコードを使用してください。
キーボードで本文の目次へ戻る
見出しの前にある「目次へ戻る」をTabで選び、Enterを押します。移動先は本文の目次#waza-main-tocで、目次自体へフォーカスが移ります。最初のH2の前にはリンクを作らず、2つ目以降のH2を対象にします。戻った位置で目次リンクを選び直して、別の見出しへ移動できます。
目次の文言を短くする場合は指定文字列の省略、サイドバーで現在位置を示す場合はハイライトの方法を参照してください。
公開画面での確認
スマホ幅390pxで「目次へ戻る」をEnterで選び、本文の目次へフォーカスが移った状態です。




