Developer docs

Show reading time & progress

In this tutorial we’ll discover how to add reading duration to all of your posts, as well as more advanced techniques for showing reading progress within posts.

Reading time

When writing long form content it’s often beneficial to let your readers know how long it might take to read a post. In Ghost handlebars themes, the reading_time helper calculates the reading time of your content and outputs it as a number of minutes with a label:

<p>{{reading_time}}</p>

Example of reading time on a blog post, circled in blue

The reading_time helper comes with optional parameters to customise the wording. If I wanted to change the wording of when an article takes a minute to read and when it takes multiple minutes to read I can set it like so:

{{reading_time minute="Only a minute" minutes="Takes % minutes"}}

This can be dropped directly into your post.hbs template, ensuring it’s within the {{#post}}...{{/post}} scope. To read more about this helper and how it calculates the duration check out our reading_time helper theme documentation.

Show reading progress

If you want to provide a live representation of reading progress to the reader then you can take advantage of Ghost theming even more by adding custom HTML, CSS and JavaScript. The following steps run through adding a reading progress bar to a Ghost site.

Download your existing theme

Before you get started you’ll need to have downloaded your Ghost theme and have the post.hbs template file open in a code editor.

Add the progress bar to post.hbs

In your post.hbs file locate the place in which you would like your reading progress bar to appear and add the following HTML:

<progress class="reading-progress-bar"></progress>
How the progress bar element looks without CSS

Progress bar without styling

Customise your styling

By default the <progress> element will be styled by whatever the browser decides to and the existing CSS in your theme. However the style can be customised by adding your own CSS to the theme. Here are some fairly simple styles to help you get started:

progress.reading-progress-bar {
    appearance: none;
    position: fixed;
    width: 100%;
    height: 2px;
}

progress.reading-progress-bar[value]::-webkit-progress-bar {
    background-color: rgba(0,0,0,0.5);
}

progress.reading-progress-bar[value]::-webkit-progress-value {
    background-color: #3eb0ef;
}

Refer to the original documentation for your theme to find out how to build on top of their code. For example Casper by Ghost has an asset pipeline that will help you to compile theme assets.

Progress bar with CSS applied

Progress bar with styling

Add the JavaScript

The final part to this is the JavaScript, which will capture the reader scrolling and tell the progress bar to update it’s completion level. The script is as follows:

const readingProgress = (contentArea, progressBar) => {
    const content = document.querySelector(contentArea);
    const progress = document.querySelector(progressBar);

    const frameListening = () => {
        const contentBox = content.getBoundingClientRect();
        const midPoint = window.innerHeight / 2;
        const minsRemaining = Math.round(progress.max - progress.value);

        if (contentBox.top > midPoint) {
            progress.value = 0;
        }

        if (contentBox.top < midPoint) {
            progress.value = progress.max;
        }

        if (contentBox.top <= midPoint && contentBox.bottom >= midPoint) {
            progress.value =
                (progress.max * Math.abs(contentBox.top - midPoint)) /
                contentBox.height;
        }

        window.requestAnimationFrame(frameListening);
    };

    window.requestAnimationFrame(frameListening);
};

readingProgress(".post-full-content", ".reading-progress-bar");

The last line of the script states the class selectors for the main content area and the progress bar itself. To ensure you are using the right selector for the main content, locate the {{content}} helper in your post.hbs template and copy the class attribute value from the surrounding element.

In the same fashion as the CSS, you may need to refer to documentation from your theme developer to ensure the script is being placed in the right file.

To see a live demo as well as more information on how the above code functions and can be extended upon check out this CodePen demo:

Embedded CodePen demo

Summary

Woohoo! You’re becoming an expert Ghost theme developer

As you gain more experience in building sites with Ghost and the Handlebars theme layer you’ll open up many more possibilities with Ghost. If you ever need more help than just the Handlebars theme documentation there’s always the official Ghost forum, where you can chat with like-minded people who are building sites in Ghost.