How I put the scroll percentage in the title bar

· Knut Melvær

Scroll down!

 

 

 

I mean it! Just scroll!

 

 

 

 

 

 

And then look up. A bit further. Yes, to the area of your tab bar where the <title> content ends up. And then scroll again.

There's a percentage there. And it changes when you are scrolling. Kinda cool isn‘t it? Now you can tab away from this site and still have a sense of how far you have read. That surely makes your existence a tad more pleasant, doesn‘t it?

The idea to put the scroll percentage in the title bar came from this tweet by @round.

[@portabletext/react] Unknown block type "twitter", specify a component for it in the `components.types` prop

I didn’t make a browser extension, rather, I just put the mechanics into my own blog post template. Since I’m on Gatsby and React, it was not that hard. Here’s how to do it:

First I installed the react-scroll-percentage package. That takes care of most of the heavy lifting. Then, and I’m honestly feel a bit out of depth here, I thought it made sense to put the actual mechanics into useEffect. It may be that it would have been possible to make Gatsby and React rerender the <title> part in another way, but I was just following my gut here (tell me on Twitter if there‘s a better way). So I ended up with something like this (actual code here):

jsx
import React, {useEffect} from 'react'
import {useScrollPercentage} from 'react-scroll-percentage'
import Container from '../components/container'
import BlogPost from '../components/blog-post'
import SEO from '../components/seo'
import Layout from '../containers/layout'
import {toPlainText} from '../lib/helpers'

const BlogPost = ({post}) => {
  const {title, _rawExcerpt} = post
  const [ref, percentage] = useScrollPercentage()
  
  useEffect(() => {
    if (post) {
      const percent = Math.round(percentage * 100)
      document.title = `${percent}% ${post.title}`
    }
  }, [percentage])
  
  return (
    <Layout>
      {post && <SEO title={` ${title}` || 'Untitled'} description={toPlainText(_rawExcerpt || [])} />}

      <div ref={ref}>
        {post && <BlogPost {...post} />}
      </div>
    </Layout>
  )
}

export default BlogPost

Since react-scoll-percentage uses Intersection Observer, which is a relatively new browser API, we also need a polyfill for browsers that doesn’t support it yet. First install it as a dependency.

sh
npm i intersection-observer

Then we want Gatsby only to use the polyfill in the browser, and import it dynamically when it‘s needed. We’ll do that by inserting this into gatsby-browser.js:

javascript
// gatsby-browser.js

export const onClientEntry = async () => {
  if (typeof IntersectionObserver === `undefined`) {
    await import(`intersection-observer`);
  }
}

And that’s it! Now, marvel at your new updating reading lenght!

Screen grab of scrolling a page while the percentage in the title updates
Most fun on long posts