Tell your users the remaining reading time, in CSS
Note: this demo must be tested in Chrome Canary 90+ with the --enable-experimental-web-platform-features flag
enabled;
Recently, thanks to the new @scroll-timeline
property available on Chrome Canary, I have seen an interesting demo by @bramus where the user is aware of the time needed to read a page with a sticky progress bar that stretches horizontally, where its width is dependant on the current scrolling position of the root element.
I've extended this idea a little bit by showing an animated countdown of the exact time needed to read the page. All you need to do is to just set the time in minutes and the CSS animations will do the work for you.
Demo (scroll the page until the end):
How does it work?
Here is a step-by-step explanation
The variables
Basically, two variables --ss
and --mm
hold the values of seconds and minutes and two distinct animations change them. In order to make the interpolation of the values in the keyframes work, these variables have been registered as integers
properties through the Houdini's API integrated on Chrome.
So the --ss
variable is declared in the CSS like this:
@property --ss { syntax: "<integer>"; initial-value: 0; inherits: true;}
while the --mm
is declared instead in a <style>
block, inside the markup because here is where you are going to set the minutes needed (e.g. 7
):
<style> @property --mm { syntax: "<integer>"; initial-value: 7; inherits: true; }</style>
Since it's not (still) possibile to print out the value of a variable using the content
property I've set two counters and print their values through the counter()
function with a leading 0
when necessary
counter-reset: ss var(--ss);...content: counter(ss, decimal-leading-zero);
and
counter-reset: mm var(--mm);...content: counter(mm, decimal-leading-zero);
The scroll-timeline
I've set the scroll-timeline animation in this way
@scroll-timeline scroll { time-range: 60s; start: 200px; end : calc(100% - 150px);}
The time-range
has been set to 60
seconds in order to make the calculations of the animations easier (at least for my brain) .
To give a meaningful example let's say that we want to start the countdown after 200px
of scroll to exclude the title or maybe a hero image, but you could even set it to 0
or to another value of course and we want to also stop it before a hypothetical footer 150px
tall.
The animations
This is the most intriguing part due to the tricky computations. Here is the animation of the minutes
@keyframes mins { to { --mm: 0; }}...animation: mins /* duration */ 60s /* timing */ steps(var(--mm), start) /* delay */ calc(calc(60s / (calc(var(--mm)) - 1)) / 60 / var(--mm)) /* repetition */ 1 /* fill mode */ forwards;
The @keyframes
start from the value we have previously set and should decrease until 0
, so the definition of the last keyframe is enough.
The animation should takes 60s
which is the same amount of time we defined for the @scroll-timeline
. The delay
expression is calculated so that the value of the minutes decreases immediately after 1s
(e.g. switching from 7:00
to 6:59
).
The animation of seconds is quite similar but in this case we need to specify the starting value
@keyframes secs { from { --ss: 59; } to { --ss: 0; }}...animation: secs /* duration */ calc(60s / calc(var(--mm))) /* timing */ linear /* delay */ calc(calc(60s / (calc(var(--mm)) - 1)) / 60 / var(--mm)) /* repetition */ var(--mm) /* fill-mode */ forwards;
The only difference here is the duration: seconds need to be updated faster than minutes, running --mm
times from 59
to 0
with a repetition
of --mm
. Here the purpose of the delay
is just to wait the first update of the minutes.
Always respect user preferences
The update of the seconds is amazing but it can be annoying for users who don't like continuous animations and that prefer a reduced motion.
We may use a simple mediaquery:
@media (prefers-reduced-motion: reduce) { .countdown__display--ss { display: none; }}
and hide the element with the seconds.
Ta-da!
Wall-E
Final words & thoughts
Feel free to follow me on Codepen or Twitter where I usually talk about frontend and trees.
Note: This is a carbon free article so I pledge to plant 25 trees with Ecologi plus 1 tree for each retweet of the announcement below in the next 12 days
New article published on dev.to
dev.to/fcalderan/tell
Tell your users the remaining reading time, in #CSS
This is #carbonfree article: I'll plant 1 tree with @Ecologi_hq for each retweet (see the article for the notes)09:16 AM - 19 Jul 2021
(up to 75 trees, retweets from human accounts with 20+ followers)
Original Link: https://dev.to/fcalderan/tell-your-users-the-remaining-reading-time-in-css-1mik
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To