ブログ記事が長くなると、読者にとって記事内のどこに何が書かれているのかを把握するのが難しくなります。そんな時、目次を設置することで、読者はすぐに見たい情報にアクセスできるようになります。この記事では、JavaScriptを使って自動的に目次を生成する方法を2つ紹介します。1つ目はh2
タグのみを対象にしたシンプルな方法、2つ目はh2
タグとh3
タグを取得して階層構造を持たせる方法です。
h2
タグのみを対象にした目次の生成
まずは、記事内のh2
タグのみを対象にして目次を生成する方法を紹介します。この方法では、記事内のh2見出しをすべてリストアップし、クリックするとその見出しにジャンプできるリンク付きの目次を生成します。
// 自動目次生成
let tocContainer = document.querySelector('.toc-container'); // 目次を表示するコンテナ
if (!tocContainer) {
tocContainer = document.querySelector('#toc'); // 目次を表示する別のコンテナ
}
if (tocContainer) {
let contentWrapper = document.querySelector('.content-wrapper'); // 記事本文を囲んでいるラッパー
let h2Tags = contentWrapper.querySelectorAll('h2'); // 記事内のH2タグを全て取得
if (h2Tags.length > 1) {
let tocList = document.createElement("ol");
let listItems = "";
for (let i = 0; i < h2Tags.length; i++) {
let heading = h2Tags[i];
let headingText = heading.innerHTML.trim(); // h2タグ内のHTMLを取得
let tempDiv = document.createElement('div');
tempDiv.innerHTML = headingText;
headingText = tempDiv.textContent || tempDiv.innerText || ""; // HTMLタグを削除したテキストを取得
heading.setAttribute('id', "heading_id" + i); // リンクで飛べるようにIDをつける
listItems += '<li><a href="#heading_id' + i + '">' + headingText + '</a></li>';
}
tocList.innerHTML = listItems;
tocContainer.appendChild(tocList);
} else {
tocContainer.style.display = "none";
}
}
このコードでは、まず目次を表示するためのコンテナを取得します。次に、記事本文を囲んでいるラッパーからすべてのh2
タグを取得し、それぞれにIDを付与します。最後に、取得したh2
タグのテキストを目次リストとしてコンテナに追加します。
h2
タグとh3
タグを対象にした階層構造の目次生成
次に、記事内のh2
タグとh3
タグを取得し、h3
タグを対応するh2
タグの目次項目の下にネストする方法を紹介します。
// 自動目次生成
let tocContainer = document.querySelector('.toc-container'); // 目次を表示するコンテナ
if (!tocContainer) {
tocContainer = document.querySelector('#toc'); // 目次を表示する別のコンテナ
}
if (tocContainer) {
let contentWrapper = document.querySelector('.content-wrapper'); // 記事本文を囲んでいるラッパー
let headings = contentWrapper.querySelectorAll('h2, h3'); // 記事内のH2タグとH3タグを全て取得
if (headings.length > 1) {
let tocList = document.createElement("ol");
let listItems = "";
let currentSubList = null; // h3タグの目次項目を格納するul要素
for (let i = 0; i < headings.length; i++) {
let heading = headings[i];
let headingText = heading.innerHTML.trim(); // h2タグまたはh3タグ内のHTMLを取得
let tempDiv = document.createElement('div');
tempDiv.innerHTML = headingText;
headingText = tempDiv.textContent || tempDiv.innerText || ""; // HTMLタグを削除したテキストを取得
heading.setAttribute('id', "heading_id" + i); // リンクで飛べるようにIDをつける
if (heading.tagName.toLowerCase() === 'h2') {
// h2タグの場合、新しいli要素を作成し、ulを閉じる
if (currentSubList) {
listItems += currentSubList.outerHTML;
currentSubList = null;
}
listItems += '<li><a href="#heading_id' + i + '">' + headingText + '</a></li>';
} else if (heading.tagName.toLowerCase() === 'h3') {
// h3タグの場合、現在のli要素の中にulを作成
if (!currentSubList) {
currentSubList = document.createElement('ul');
}
currentSubList.innerHTML += '<li><a href="#heading_id' + i + '">' + headingText + '</a></li>';
}
}
// 最後に残っているulをリストに追加
if (currentSubList) {
listItems += currentSubList.outerHTML;
}
tocList.innerHTML = listItems;
tocContainer.appendChild(tocList);
} else {
tocContainer.style.display = "none";
}
}
このコードでは、h2
タグとh3
タグの両方を取得し、各見出しにIDを付与します。h3
タグが見つかった場合、それをul
タグで囲んで対応するh2
タグの下にネストします。
まとめ
この記事では、JavaScriptを使って自動的に目次を生成する2つの方法を紹介しました。シンプルにh2
タグのみを対象にする方法と、h2
タグとh3
タグを階層構造で目次に含める方法です。どちらの方法も、読者にとって記事をより読みやすく、ナビゲートしやすくするための有効な手段です。目的や記事の構造に応じて、適切な方法を選んで実装してみてください。