Imaginaryのインデックスページ、つまりトップページとアーカイブページとラベルページとブログ内の検索結果ページではスクロールが画面下に達すると次のページを自動的に読む込むという無限スクロールが搭載されています。
本稿では画面スクロールによる動作を停止して読み込みボタンで無限スクロールを手動的に行うように変更するカスタマイズの方法を紹介します。
見た目は通常のリンクと同じですが、ボタンを押すと次のページへ移動するのではなく、次のページを読み込んで同じページで表示します。
カスタマイズはテンプレートのソースコードを編集しますので、Bloggerの管理画面のテーマのHTMLを編集かバックアップと元に戻すで、行って下さい。
読み込みボタン/無限スクロールの手動化へのの四つの手順

無限スクロールのソースコードを画面スクロールから読み込みボタンに書き換えます。
そのままではフッターとスマホやタブレットなどでサイドバーがブログの下段に表示されませんので、元に戻すためにそれぞれを表示するカスタマイズをさらに追加して下さい。
以前の画面スクロールのためのソースコードが少し不要になります。残しておいてもたぶん動作に支障はないでしょうが、なるべく削除した方が良いと思います。
追記:Imaginaryの2022年5月15日以降のバージョンには削除のみの部分はありません。手順①読み込みボタンを設置する
テンプレートのソースコードの下段のscriptタグの無限スクロールに相当する「/* Infinite scroll */」の部分を書き換えます。
不要になる部分
<b:if cond='data:view.isMultipleItems';>
/* Infinite scroll */
const bpct = Blog1.firstElementChild;
if (bpct.classList.contains("hfeed")) {
(中略)
lsch(); }); }, {
rootMargin: bthg + "px"});
nextIndexObserver.observe(sub_main); }
<b:else/>
打ち消し線のソースコードを削除して下さい。
引用は途中を省略しているので、実際はもっと長いです。
Imaginaryのヴァージョンによって内容は異なる場合がありますが、編集するのは「/* Infinite scroll */」を含む<b:if cond='data:view.isMultipleItems'>
から<b:else/>
までのプログラムで、全て共通です。
必要になる部分
/* Load button */
const bpct = Blog1.firstElementChild;
if (bpct.classList.contains("hfeed")) {
const bpg = bpct.querySelector("nav.blog-pager");
let npl = bpg ? bpg.querySelector("a.older-link") : "";
if (npl) {
const orit = npl.innerText;
sidebar_wrapper.classList.add("swcn"); bpct.after(bpg);
function scrollStop(event) {
event.preventDefault(); }
function isac() {
new Promise ((resolve, reject) => {
if (~npl.innerText.indexOf(orit)) {
bpg.firstElementChild.style.color = getComputedStyle(bpg.parentElement).color; bpg.firstElementChild.innerText = "読み込み中\u2026"; document.addEventListener("mousewheel", scrollStop, {passive: false}); document.addEventListener("touchmove", scrollStop, {passive: false}); bpct.ariaBusy = "true"; resolve(); } else {
reject('Too fast'); }}).then(async () => {
const response = await fetch(npl.href);
if (!response.ok) throw "Connection failed";
const text = await response.text(), file = new DOMParser().parseFromString(text, "text/html"), bats = file.querySelectorAll("article.post");
npl = file.querySelector("a.older-link");
if (npl) npl.parentElement.remove(); else if (!bats[0]) bpg.remove(); else {
bats[bats.length - 1].lastElementChild.remove(); bpg.remove(); }
Promise.all([...bats].map(bat => {
const nbat = document.adoptNode(bat), pssc = nbat.querySelector("p.summary>script");
if (pssc) pssc.parentElement.insertAdjacentHTML("afterbegin", /`([^]+)`/.exec(pssc.textContent)[1].replace(/(<([^>]+)>)/g, '')); return nbat; })).then(results => results.forEach(result => bpct.appendChild(result))); }).catch(error => {
switch (error) {
case 'Too fast': throw '';
default: if (npl) npl.removeEventListener("click", adsn); }}).then(() => {
document.removeEventListener("mousewheel", scrollStop, {passive: false}); document.removeEventListener("touchmove", scrollStop, {passive: false}); bpct.ariaBusy = "false"; bpg.firstElementChild.style.color = getComputedStyle(npl).color; bpg.firstElementChild.innerText = orit; }); }
function adsn(event) {
event.preventDefault(); isac(); }
npl.addEventListener("click", adsn); } else {
bpg.remove(); }
const loadButtonObserver = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting && sidebar_wrapper.classList.contains("swcn")) sidebar_wrapper.classList.remove("swcn"); }); }, {
rootMargin: "240px"});
loadButtonObserver.observe(sub_main); }
不要になる部分のところ、script内の<b:if cond='data:view.isMultipleItems'>
から<b:else/>
までの間のプログラムを書き換えて下さい。
細部の修正について
- 次のページの読み込み中(押した後のボタン)の表示
bpg.firstElementChild.innerText = "読み込み中\u2026";
- 初期値の「読み込み中\u2026」(ユニコードの「\u2026」はブログで「…」と表示される)を変更すると好きな表示を使えます。
- Bloggerの設定の言語が反映しないので、日本語以外の場合、自分で書き換えないと他のボタンの言語と合わなくなります。
- 読み込み中の表示の文字色
bpg.firstElementChild.style.color = getComputedStyle(bpg.parentElement).color;
- 初期値の「getComputedStyle(bpg.parentElement).color」はスニペット(記事の抜粋)の文字色で、その他の色を指定することもできます。
- 文字色(色キーワード)や色コードで指定する場合、半角二重引用符を付けて下さい。
- 例_bpg.firstElementChild.style.color = "red";
ボタンの基本的なデザインに関してはCSSを編集して下さい。
ページャーのCSSのソースコード
/* ページャー */
.blog-pager {display:flex;justify-content:space-around}
.feed-view .blog-pager {margin-top:20px}
.blog-pager>a {color:$(posts.navigation.link.color)}
.blog-pager>a:visited {color:$(posts.navigation.link.visited.color)}
.blog-pager>a:hover {color:$(posts.navigation.link.hover.color)}
全ページのボタンは「.blog-pager」、インデックスページのボタンは「.feed-view .blog-pager」、記事/追加ページのボタンは「.item-view .blog-pager」を指定先にするとカスタマイズできます。
参考:CSSはどう使えば良いのか|タグ自体とidとclassの指定先とstyleタグとインラインの記述法
手順②フッターを表示する
テンプレートのソースコードのCSSの一部を削除します。
不要になる部分
追記:Imaginaryの2023年1月25日以降のバージョンには削除する部分はありません。/* バランサー */
.hidden, :not(.feed-view>#sub_main).section.no-items, .feed-view>#sub_main>.widget, .feed-view>#attribution {display:none}
.invisible {visibility:hidden}
.hfeed, .hentry {contain:content}
#PopularPosts1, .item-view>#sub_main, .item-view>#attribution {content-visibility:auto;contain-intrinsic-size:100%}
打ち消し線のところを削除します。
フッターが適切に表示されます。
手順③モバイルのサイドバーを下段に表示する
テンプレートのソースコードの下段のscriptタグのモバイルのサイドバーの開閉に関与する「/* Sub content observer */」の部分を書き換えます。
編集する部分
/* Sub content observer */
(中略)
sbct.classList.remove("slider"); sbct.classList.remove("sidebar-invisible"); hamburger_menu.style.transform = "rotateZ(90deg)"; sbct.ariaHidden = "false"; }} else if (entry.rootBounds.bottom < entry.boundingClientRect.bottom || entry.boundingClientRect.bottom === 0 || Blog1.firstElementChild.className.indexOf("message") {
<b:if cond='data:view.isMultipleItems'>sidebar_wrapper.classList.add("swcn"); </b:if>sbct.classList.add("slider"); sbct.classList.add("sidebar-invisible"); hamburger_menu.style.transform = "rotateZ(0)"; sbct.ariaHidden = "true"; }}</b:if>}); }, {
rootMargin: "240px"});
太字のコードを追加します。
モバイルのサイドバーがブログの下段に適切に表示されます。
Imaginaryのモバイルのサイドバーはブログの上段はスライド、下段は通常という二通りの仕方で表示されますが、一部のブラウザがそれぞれに出し分けるコーディングに対応してない可能性があり、少しでも多くのブラウザで安定してサイドバーを表示するために下段の表示を停止して、常時、スライドを使う方法も紹介しておきます。
新しく追加するプログラムの「/* Load button */」とテンプレートのソースコードの下段のscriptタグのモバイルのサイドバーの開閉に関与する「/* Sub content observer */」の一部を削除して「/* Sidebar for mobile */」の全てを書き換えます。
不要になる部分①Load button
/* Load button */
const bpct = Blog1.querySelector("div.hfeed"), bpg = Blog1.querySelector("nav.blog-pager"), orit = bpg.firstElementChild.innerText;
let npl = bpg.querySelector("a.older-link");
if (bpct.clientHeight === 0) bpct.style.marginTop = "0";
bpct.after(bpg); sidebar_wrapper.style.transform = "translateY(-1em)";
function scrollStop(event) {
event.preventDefault(); }
打ち消し線のところを削除します。
不要になる部分②Sub content observer
/* Sub content observer */
(中略)
if (commentForm !== document.activeElement) {
back_button.classList.remove("invisible");</b:if>}});
subContentObserver.unobserve(comments); }}</b:if>
<b:if cond='data:skin.vars.sidebar_width or data:skin.vars.content_margin'>
if (entry.target.id === "sidebar_wrapper") {
if (entry.isIntersecting) {
if (sbct.classList.contains("slider")) {
sbct.classList.remove("slider"); sbct.classList.remove("sidebar-invisible"); hamburger_menu.style.transform = "rotateZ(90deg)"; sbct.ariaHidden = "false"; }} else if (entry.rootBounds.bottom < entry.boundingClientRect.bottom || entry.boundingClientRect.bottom === 0) {
sbct.classList.add("slider"); sbct.classList.add("sidebar-invisible"); hamburger_menu.style.transform = "rotateZ(0)"; sbct.ariaHidden = "true"; }}</b:if>}); }, {
rootMargin: "240px"});
打ち消し線のところを削除します。
編集する部分/書き換え前
/* Sidebar for mobile */
subContentObserver.observe(sidebar_wrapper);
編集する部分/書き換え後
/* Sidebar for mobile */
sbct.classList.add("slider");
打ち消し線のところを新しいコードに書き換えます。
三つの変更によってモバイルのサイドバーがスライドでの表示だけになります。
手順④デスクトップのサイドバーを外した後に下段に表示する
2023年2月7日以降のバージョンが対象となり、それ以前のものは必要ありません。
テンプレートのソースコードの下段のscriptタグのデスクトップ版のサイドバーに関与する「/* Sidebar for desktop */」の部分を書き換えます。
不要になる部分
/* Sidebar for desktop */
<b:if cond='data:view.isMultipleItems'>if (bdis.classList.contains("no-sidebar")) sbct.style.display = "none";</b:if>
function schb(event) {
bdis.animate([{opacity:0}, {opacity:1}], {duration: 300}); bdis.classList.toggle("no-sidebar");
switch (event.currentTarget.id) {
case "sdbtn": <b:if cond='data:view.isMultipleItems'>sbct.style.display = "none"; </b:if>localStorage.setItem("content", "no-sidebar"); break;
case "subtn": <b:if cond='data:view.isMultipleItems'>sbct.style.display = "flex"; </b:if>localStorage.setItem("content", ""); }}
(中略)
打ち消し線のところを削除します。
残しておくとサイドバーを外したときにインデックスページで読み込みボタンの下に移動したサイドバーが表示されません。
手順⑤不要なコードを削除する
追記:Imaginaryの2022年5月15日以降のバージョンには削除のみの部分はありません。テンプレートのソースコードのPopularPost1のwidgetの次/Profile1のwidgetの前(初期状態)の一つのコードを挙げます。
不要になる部分
<div id='sidebar_wrapper'>
<b:class cond='data:view.isMultipleItems' name='swcn'/>
<aside aria-hidden='false' class='sidebar-container sidebar-invisible'>
打ち消し線のところを削除します。
画面スクロールと共にモバイルのサイドバーを下段に表示するためのコード、ボタンに変えるとプログラムで重複しますから削除して構いません。
コメント
Nice theme.
返信削除こちらのカスタマイズですが、Chromeだと読み込みボタンを2回押さないと記事が読み込めません。
返信削除お時間がアレば検証して頂きたいです。
またグリットタイプテーマを手動読み込みに対応させた場合、最後のページまで行くと空のボタンが"article.post"内に表示されますが非表示にするか、フッターの直上に移動してホームボタンを表示するなど出来ないでしょうか?
個別記事のページャーとも共有されているようで、自分ではカスタマイズ不可能でした;;
記事の【読み込みボタンを設置する】の「必要になる部分」のプログラムのエラーが出そうなところを修正したので、もう一度、やり直してみて下さい。
削除二回、押すと読み込むというのは同じページにスニペットを新しく追加するのではなく、次のページへ普通に移動してしまうエラーかも知れません。
その他に追加されたカスタマイズが干渉して正常に動作しなくなる場合もありますので、注意して下さい。
最初のページで見えない読み込みボタンの位置に隙間が付いてしまうデザインの崩れも修正しました。