Skip to main content
← back to field notes
One min readDevelopment

How to calculate estimated reading time

jekylljamstackjavascript

When publishing an article it is often a nice touch to let users know roughly how long it will take to read, and what level of investment they can expect to make. While every reader is different, the average reader can ingest about 150 - 200 words per minute, depending on the type of text.

This site uses a simple algorithm to calculate the estimated reading time. It is based on the number of words in the article, and the average reading speed of a reader. I currently use a Jekyll plugin (Github pages safe!) that can be included at the top of a post, but I have also included a simple javascript function that can be used anywhere.

This is not meant to be a perfect solution, but it is a good starting point for your implementation, and it is easy to understand.

The Jekyll Plugin

{% raw %}{% capture words %}
{{ content | number_of_words | minus: 180 }}
{% endcapture %}
{% assign words = words | plus: 0 %}
{% if words > 0 %}
{% assign words = words | plus: 150 | divided_by: 150 %}
{%else%}
{% assign words = 1 %}
{% endif %}

Estimated time to read: {{ words }} {%if words == 1 %}minute.{%else%}minutes.{%endif%}{% endraw %}

The Javascript Function

const article_root = $('article.post'); // upddate with root element of main article.
const wc = wordCount(article_root.text());

console.log(readingSpeed(wc.words));

function readingSpeed(words) {
'use strict';
const avgReadingSpeed = (words / 200.0).toString();
const rawSpeed = avgReadingSpeed.split(/\./, avgReadingSpeed);
const rawSeconds = rawSpeed[0] * 60 + rawSpeed[1] * 0.6;
let d = new Date(null);
d.setSeconds(rawSeconds);
const rawTime = d.toISOString().substr(14, 5).toString();
console.info(`${words} words per minute: ${rawTime}`);
const result = rawTime.split(':');
return {
minutes: result[0],
seconds: result[1],
};
}

function wordCount(val) {
'use strict';
const wom = val.match(/\S+/g);
return {
charactersNoSpaces: val.replace(/\s+/g, '').length,
characters: val.length,
words: wom ? wom.length : 0,
lines: val.split(/\r*\n/).length,
};
}
field notes

you may also enjoy

more from this thread of thought

working with git: archive
Aug 5, 2025

working with git: archive

read more →
Surprise Driven Development
Jul 10, 2025

Surprise Driven Development

read more →
What's in a .git? A Deep Dive into Git's Hidden Engine
Jun 3, 2025

What's in a .git? A Deep Dive into Git's Hidden Engine

read more →
Git Worktrees: Multiple Branches, Zero Context Switching
May 30, 2025

Git Worktrees: Multiple Branches, Zero Context Switching

read more →
Walking Back with Git: HEAD^ vs HEAD~ Demystified
May 29, 2025

Walking Back with Git: HEAD^ vs HEAD~ Demystified

read more →
New Project Release: Pride Flags
May 5, 2025

New Project Release: Pride Flags

read more →
the field notes

recently written