Shopifyのデフォルトでは目次の機能がない
アプリをインストールすれば目次の機能がつけれたりしますが
無料の範囲だとブランド名が表示されたりしてちょっとイマイチですよね。。
無料でオリジナルデザインの目次を使いたいと思い今回作ってみました。
動作については実際に上にある目次を触っていただければと思います。
今回書いたコードはこちら
// 目次制作
{
document.addEventListener('DOMContentLoaded', function() {
//目次を設置する場所を作る
const articleContent = document.querySelector('.article-template__content');
articleContent.insertAdjacentHTML('afterbegin', `
<div class="tableContent-wrapper">
<div id="tableContent" class="tableContent">
<div class="tableContent-title">
目次
</div>
</div>
</div> `
);
const article = document.querySelector('.article-template');
const blogIndex = article.querySelector('#tableContent'); //目次の出力場所
const headingArray = article.querySelectorAll('h2,h3');
let h2Number = 1;
let h3Number = 1;
let h3Id = 1;
headingArray.forEach((heading) => {
let tag = heading.tagName;
let headingText = heading.textContent;
heading.className = 'blog-heading';
if (tag == 'H2') {
heading.id = 'id2-' + h2Number;
let p = document.createElement('p');
let a = document.createElement('a');
p.insertAdjacentHTML('afterbegin', `<span class="indexNumber">${h2Number}. </span>`);
p.append(a);
a.append(headingText);
a.href = '#' + 'id2-' + h2Number;
p.className = 'tableContent-h2';
blogIndex.append(p);
h2Number++;
if (h3Number != 1) {
h3Number = 1;
}
} else if (tag == 'H3') {
heading.id = 'id3-' + h3Id;
let p = document.createElement('p');
let a = document.createElement('a');
p.insertAdjacentHTML('afterbegin', `<span class="indexNumber">${h3Number}. </span>`);
p.append(a);
a.append(headingText);
a.href = '#' + 'id3-' + h3Id;
p.className = 'tableContent-h3';
blogIndex.append(p);
h3Number++;
h3Id++;
}
})
//スムーススクロール
// ページ内のリンクがクリックされたときに呼び出される関数
function smoothScroll(target) {
const element = document.querySelector(target);
const elementPosition = element.getBoundingClientRect().top + window.pageYOffset - 50;
// スクロール位置を計算して設定
window.scrollTo({
top: elementPosition,
behavior: 'smooth'
});
}
// リンクをクリックしたときの処理
const links = document.querySelectorAll('.tableContent-h2 , .tableContent-h3');
links.forEach((link) => {
link.addEventListener('click', (event) => {
event.preventDefault(); // リンクのデフォルト動作をキャンセル
const target = link.querySelector('a').hash;
smoothScroll(target);
});
})
});
コードの説明
目次を挿入する用のHTMLを作成
//目次を設置する場所を作る
const articleContent = document.querySelector('.article-template__content');
articleContent.insertAdjacentHTML('afterbegin', `
<div class="tableContent-wrapper">
<div id="tableContent" class="tableContent">
<div class="tableContent-title">
目次
</div>
</div>
</div> `
);
目次はコンテンツの前に設置したいのでコンテンツは
「insertAdjacentHTML」を使って設置しています。
直接コードを記事を書く際に管理画面から貼り付けてもいいのですが毎回面倒なのでJavaScriptを使って自動で設置しています。
h2とh3の要素を取得
const headingArray = article.querySelectorAll('h2,h3');
「querySelectorAll」を使って要素を取得します
○ ('h2,h3')
×('h2','h3')
「' '」位置に注意です!私はここでつまづきましたw
取得した要素をもとに目次用のHTMLを生成
詳しい説明は省きますが
①h2.h3タグに個別のidを連番でつける
↓
②目次用のHTMLを生成する
↓
③はじめに生成した設置場所に目次用のHTMLを設置する
if文だったり条件分岐が入っていますが
①〜③の手順で下のコードを書いています。
headingArray.forEach((heading) => {
let tag = heading.tagName;
let headingText = heading.textContent;
heading.className = 'blog-heading';
if (tag == 'H2') {
heading.id = 'id2-' + h2Number;
let p = document.createElement('p');
let a = document.createElement('a');
p.insertAdjacentHTML('afterbegin', `<span class="indexNumber">${h2Number}. </span>`);
p.append(a);
a.append(headingText);
a.href = '#' + 'id2-' + h2Number;
p.className = 'tableContent-h2';
blogIndex.append(p);
h2Number++;
if (h3Number != 1) {
h3Number = 1;
}
} else if (tag == 'H3') {
heading.id = 'id3-' + h3Id;
let p = document.createElement('p');
let a = document.createElement('a');
p.insertAdjacentHTML('afterbegin', `<span class="indexNumber">${h3Number}. </span>`);
p.append(a);
a.append(headingText);
a.href = '#' + 'id3-' + h3Id;
p.className = 'tableContent-h3';
blogIndex.append(p);
h3Number++;
h3Id++;
}
})
スムーススクロールのコード
サイト内で遷移するときにスムーススクロールで動くようにコードを書いています。
//スムーススクロール
// ページ内のリンクがクリックされたときに呼び出される関数
function smoothScroll(target) {
const element = document.querySelector(target);
const elementPosition = element.getBoundingClientRect().top + window.pageYOffset - 50;
// スクロール位置を計算して設定
window.scrollTo({
top: elementPosition,
behavior: 'smooth'
});
}
// リンクをクリックしたときの処理
const links = document.querySelectorAll('.tableContent-h2 , .tableContent-h3');
links.forEach((link) => {
link.addEventListener('click', (event) => {
event.preventDefault(); // リンクのデフォルト動作をキャンセル
const target = link.querySelector('a').hash;
smoothScroll(target);
});
})
デフォルトだと画面の左上にリンク先が来てしまうので−50px上にずらしています
目次があるとブログは見やすい
やっぱり目次があるとブログは見やすいですね!
Shopifyでブログを書いていくにあたってまずは目次を作ろう!
と思ってたのでいい感じにできて満足です!
目次を実装したいけどうまくコードが書けないという方の参考になれば嬉しいです^^