軽量な読了プログレスバー(どこまで読んだ?)をWordPressに設置してUX改善してみる

最近、テック系のサイトを中心にあちこちで見かけるのが読了プログレスバー。
特にダークテーマですと、一筋の光が闇を貫くようで格好いい。

なんて厨二心をくすぐるの……

というわけで、自称中学二年生の私は本サイトに実装してみました。
映えるデザインの満足感に浸りきってます。

本記事では、WordPressサイトにおける読了プログレスバーの実装方法を紹介します。
当サイトのテーマはGeneratePressですが、ほぼどのテーマでもいけるはずです。

そしてデザイン以外の、読了プログレスバーを設置する効果について説明します。
実のところその効果こそが、私の設置した本命の理由です。

天満川鈴 WRITTEN BY 天満川鈴
スポンサーリンク

実装図

まずパソコン。
上部のピンクの細長い線がプログレスバーです。

WordPressで読了プログレスバーを設置した画面(PC)

モバイルはこちら。

WordPressで読了プログレスバーを設置した画面(モバイル)

個人的には、

1~3pxくらいでひっそり設置するのがおすすめです

ほんのり静かで、訪問者が記事を読むのを邪魔しないので。

実装コード

CSS

#km-reading-progress {
position: fixed;
top: 0;
left: 0;
z-index: 99999;
width: 100%;
height: 2px;
background: #fa8072;
transform: scaleX(0);
transform-origin: left center;
pointer-events: none;
opacity: 0.9;
will-change: transform;
}

body.admin-bar #km-reading-progress {
top: 32px;
}

@media screen and (max-width: 782px) {
body.admin-bar #km-reading-progress {
top: 46px;
}
}

JS

(function () {
'use strict';

const init = function () {
const bar = document.getElementById('km-reading-progress');

const article =
document.querySelector('.inside-article') ||
document.querySelector('article') ||
document.querySelector('.entry-content') ||
document.querySelector('main');

if (!bar || !article) return;

let ticking = false;

const update = function () {
const rect = article.getBoundingClientRect();
const articleTop = window.scrollY + rect.top;
const articleHeight = article.offsetHeight;
const viewportHeight = window.innerHeight;

const start = articleTop;
const end = articleTop + articleHeight - viewportHeight;
const current = window.scrollY;

let progress = (current - start) / (end - start);
progress = Math.max(0, Math.min(1, progress || 0));

bar.style.transform = 'scaleX(' + progress + ')';
ticking = false;
};

const requestUpdate = function () {
if (!ticking) {
window.requestAnimationFrame(update);
ticking = true;
}
};

window.addEventListener('scroll', requestUpdate, { passive: true });
window.addEventListener('resize', requestUpdate);

requestUpdate();
};

if ('requestIdleCallback' in window) {
requestIdleCallback(init, { timeout: 1500 });
} else {
window.addEventListener('load', init, { once: true });
}
})();

PHP

/**
* 軽量な読了プログレスバーを追加
*/
add_action( 'wp_footer', function() {
if ( ! is_single() ) {
return;
}

echo '<div id="km-reading-progress" aria-hidden="true"></div>' . "\n";
}, 5 );

add_action( 'wp_enqueue_scripts', function() {
if ( ! is_single() ) {
return;
}

$css_path = get_stylesheet_directory() . '/css/km-reading-progress.css';
$js_path = get_stylesheet_directory() . '/js/km-reading-progress.js';

if ( file_exists( $css_path ) ) {
wp_enqueue_style(
'km-reading-progress',
get_stylesheet_directory_uri() . '/css/km-reading-progress.css',
array(),
filemtime( $css_path )
);
}

if ( file_exists( $js_path ) ) {
wp_enqueue_script(
'km-reading-progress',
get_stylesheet_directory_uri() . '/js/km-reading-progress.js',
array(),
filemtime( $js_path ),
true
);
}
}, 20 );

コードのポイント

ファイル配置・記述場所

CSSとJSファイルは、子テーマ直下のCSS・JSフォルダに配置するものとしています。

CSS

/path/to/wp-content/themes/your-child-theme/css/km-reading-progress.css

JS

/path/to/wp-content/themes/your-child-theme/js/km-reading-progress.js

PHPコードは子テーマのfunctions.phpに記します。
CSSもJSもPHPで読み込みますので、別途の記述は不要です。

軽量・高速

できるかぎり軽量・高速に読み込めるように作っています。

  • scrollイベントをそのまま連打せず、requestAnimationFrameで描画更新を間引いています。
  • width変更ではなく、transformベースで動かしています。
  • JSはフッターで読み込んでいます。
  • CSS自体もかなり小さいため、通常読み込みでも大きな影響は出にくいです。

CSSはあえて非同期読み込みにしていません。
私は宗教上の理由により非同期にしていますが、自分以外の方には安定性を重視して同期を推奨しています。
それでも非同期にしたい場合は、自己責任で次のコードを追加してください。

/**
* 読了プログレスバーのCSSを非同期読み込みにする
*/
add_filter( 'style_loader_tag', function( $tag, $handle ) {

if ( 'km-reading-progress' !== $handle ) {
return $tag;
}

return str_replace(
" media='all'",
" media='print' onload=\"this.media='all'\"",
$tag
);

}, 10, 2 );

ただCSSが小さいので、レンダリングブロックを気にするならインライン化も一つの手です。

テーマをほとんど選ばない

こちらでコンテンツ部分のクラスを監視しています。

const article = document.querySelector('.inside-article') || document.querySelector('article') || document.querySelector('.entry-content') || document.querySelector('main');

主だったテーマの多くは、これでカバーできるはず。
もしテーマが対応していない場合は、お使いのテーマに合わせて書き換えてください。

色と太さを変更したいとき

こちらの箇所を変更してください。

#km-reading-progress {
height: 2px;
 background: #fa8072;
}

デフォルトは当サイトのブランドカラーのサーモンピンクです。
このままお使いいただいても嬉しいですが。
できればサイトのキーカラー・ブランドカラーにあわせるのを推奨します。

たった1~3pxなのに、サイトの世界観が跳ね上がりますよ!

太さはお好みで。
私的な目安として、ダークテーマなら1~2px、ライトテーマなら2~3pxをおすすめします。
ライトテーマは明るくて上端が視界に溶けやすくなりますから、若干太めにした方が読者は気づきやすくなります。

読了プログレスバーの効果「読者の心理的な闇を照らす」

冒頭で、読了プログレスバーにはデザイン以外の効果があると書きました。
それは、サイトの闇を照らすだけではありません。

読者の心理的な闇を照らしてくれます

具体的には、

読者の「この記事どこまで続くの?」という不安を解消することでUXの改善に繋がります。

特にモバイル。
パソコンの場合はブラウザのバーがありますし、2カラム構成ならサイトバーで読了目安を案内できます。

下画像は当サイトの例です。
サイドバー部分の6に「<<」のアニメーションをつけています。

サイドバーの目次(TOC)ウィジェットによる読了目安のガイド

しかしモバイルはそうもいきません。
何の目印もありませんから、読者はいつまでスクロールしなくてはいけないのか不安になりがち。
プログレスバーがあれば「あとこれくらい読めばいい」とわかりますので安心できます。

すなわち、

読了プログレスバーの設置はUXの改善に繋がるということです

設置における注意点

前項の観点を踏まえた場合、一つ注意した方がいいことがあります。

どこまでをコンテンツと考えるか?

監視するクラスによっては記事本文の終わりでプログレスバーがぴったり終わらない場合もあります。
たとえば当サイトですと記事本文→アドセンス→SNSシェアボタン→著者情報→CTAまで来てプログレスバーが終わります。
カスタマイズの関係でそうなってしまいました。

ただ、直そうと思えば直せるのですが、あえてこのままにしています。
理由は2つあります。

1つは、プログレスバーが終わったのに記事が終わってないならまずいですけど。
逆の場合は予定より早く終わるわけですから構わないと思われること。

もう1つは、記事が終わった後のセクションも「私にとってはコンテンツ」なんです。
SNSでシェアしてほしいですし、私を知ってもらいたいですし、ConoHaと契約してもらいたいですし。

最後まで読んでもらえたら嬉しいなっ!

本音を隠すつもりはありません。
この記事もプログレスバーが終わるまでお読みいただけると嬉しいです。

まとめ

読了プログレスバーはたった1~3pxの線でデザイン的にもUX的にも素晴らしい効果をあげられます。
サイトの闇に、読者の心の闇に、

読了プログレスバーの光を照らしてみませんか?

 

スポンサーリンク
天満川 鈴のプロフィール画像
WRITTEN BY

天満川 鈴

未経験からWEB業界に入り、現在はWEBディレクターとして実務に従事。 要件整理・導線設計・コンテンツ構成などを学びながら、日々改善を重ねています。 AIを活用したコンテンツ制作・効率化を強みとし、プロンプト設計を含めた制作フローの最適化にも取り組んでいます。
本サイトでは、WordPressやサイト制作に関する試行錯誤・検証内容を中心に発信。 技術検証の一環として、KUSANAGI公式サイトにて記事を2回紹介いただきました。

RECOMMENDED INFRASTRUCTURE

私はConoHa以外を勧めない。

2016年からずっとConoHaを使い倒してきました。知人に「一番いいサーバーは?」と聞かれたら、迷わずここを教えます。

レンタルサーバーナンバーワンを誇る高速環境であることはもちろん。私が「黒い画面って何?」というド素人からサイト制作のプロになれたのは、傍らにずっとこのはちゃんがいてくれたから。
私がConoHaを使い続ける、嘘偽りない理由です。

※ConoHaに初めて入会の方限定。
本CTAの画像もしくはボタンを押してWINGパック12か月以上を契約すると、最大5000円割引してもらえます。

公式サイトで詳細を見る
× 閉じる