This Pure CSS code snippet helps you to create a circular scroll indicator. It visualizes scrolling progress dynamically. The indicator animates as you scroll down a page, showcasing a timer-like visualization. This is helpful for indicating scrolling progress visually.
You can use this code on websites to add a visual scroll indicator. It helps users track their progress while scrolling, enhancing the overall user experience.
How to Create Circular Scroll Indicator Using Pure CSS
1. First of all, load the Reset CSS by adding the following CDN link into the head tag of your HTML document.
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
2. Set up the basic HTML structure, including a warning for unsupported browsers and the circular scroll indicator container. Place the warning inside a <div>
with the class “warning” and the indicator within a <figure>
with the class “component.”
<h2> Scroll down </h2> <div class="warning"> <p>⚠️ Scroll-driven animations are not supported in this browser. Try this demo in Chrome 115+.</p> </div> <figure class="component" aria-hidden="true" webc:root="override"> <div class="timer-wrapper"> <svg class="timer" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentcolor" viewBox="0 0 256 256"> <rect width="256" height="256" fill="none"></rect> <circle cx="128" cy="128" r="88" fill="var(--color-theme)"></circle> <circle cx="128" cy="128" r="88" fill="none" stroke="currentcolor" stroke-miterlimit="10" stroke-width="16"></circle> <line class="timer-hand" x1="128" y1="128" x2="167.6" y2="88.4" fill="none" stroke="currentcolor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"></line> <line class="timer-switch" x1="104" y1="8" x2="152" y2="8" fill="none" stroke="currentcolor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"></line> </svg> </div> <figcaption class="caption"></figcaption> </figure>
3. Apply styles to create the circular scroll indicator and customize its appearance. Set up root-level CSS variables for background color, text color, and theme colors to customize the indicator’s appearance.
Utilize CSS animations to bring the circular scroll indicator to life. The code includes keyframes for progress, turning upright, and plunging animations.
:root { --color-bg: #fffefd; --color-text: #020617; --color-theme: #ffedd5; --color-theme-accent: #fed7aa; } @property --progress { syntax: "<integer>"; initial-value: 0; inherits: false; } body { color: var(--color-text); background-color: var(--color-bg); font-family: system-ui, sans-serif; } .component { --size: 30vmin; display: grid; grid-template-areas: "timer" "caption"; place-items: center; place-content: center; gap: 0.2em; position: fixed; inset: 0; margin: auto; } .timer-wrapper { grid-area: timer; display: grid; place-items: center; place-content: center; grid-template-areas: "container"; width: var(--size); height: var(--size); border-radius: 50%; background: conic-gradient( from 45deg, var(--color-theme-accent) calc(var(--progress) * 1%), transparent 0 ); } .timer-wrapper > * { grid-area: container; } .timer { width: calc(var(--size) / 1.2); height: calc(var(--size) / 1.2); } .caption { grid-area: caption; } .caption::before, .caption::after { margin-inline: auto; content: counter(progress); font-size: calc(0.6em + var(--size) / 6); font-weight: bold; text-align: center; font-variant-numeric: tabular-nums; } .caption::after { content: "%"; } /* Warning for unsupported browsers */ .warning { color: black; background: papayawhip; padding: 1rem; line-height: 1.3; text-align: center; } @supports (animation-timeline: scroll()) { .warning { display: none; } body { height: 1000vh; } :is(.component, .timer-wrapper, .timer, .timer-hand, .timer-switch) { -webkit-animation-fill-mode: both; animation-fill-mode: both; -webkit-animation-timing-function: linear; animation-timing-function: linear; animation-timeline: scroll(); } .component { --plunge-offset: 10rem; --plunge-start: calc(100% - var(--plunge-offset) * 2); --plunge-end: calc(100% - var(--plunge-offset)); -webkit-animation-name: progress; animation-name: progress; animation-range: 0 var(--plunge-start); counter-reset: progress var(--progress); } .timer-wrapper { -webkit-animation-name: progress, turn-upright; animation-name: progress, turn-upright; animation-range: 0 var(--plunge-start), var(--plunge-start) var(--plunge-end); } .timer { --plunge-depth: 0.25em; transform-origin: 50% 0; -webkit-animation-name: plunge; animation-name: plunge; animation-range: var(--plunge-start) var(--plunge-end); } .timer-switch { --plunge-depth: 1em; transform-origin: 50% 0; -webkit-animation-name: plunge; animation-name: plunge; animation-range: var(--plunge-start) var(--plunge-end); } .timer-hand { transform-origin: 50%; rotate: calc((var(--progress) / 100) * 360deg); -webkit-animation-name: progress; animation-name: progress; animation-range: 0 var(--plunge-start); } @-webkit-keyframes progress { to { --progress: 100; } } @keyframes progress { to { --progress: 100; } } @-webkit-keyframes turn-upright { from { rotate: -10deg; } to { rotate: 0; } } @keyframes turn-upright { from { rotate: -10deg; } to { rotate: 0; } } @-webkit-keyframes plunge { 50% { translate: 0 var(--plunge-depth); } } @keyframes plunge { 50% { translate: 0 var(--plunge-depth); } } @-webkit-keyframes fade-out { from { opacity: 1; } to { opacity: 0; } } @keyframes fade-out { from { opacity: 1; } to { opacity: 0; } } }
Copy and paste the above HTML and CSS code into your project. Adjust the CSS variables to match your site’s color scheme. Test the indicator in a compatible browser, preferably Chrome 115+, for the optimal scrolling experience.
That’s all! hopefully, you have successfully created a Circular Scroll Indicator Using Pure CSS. If you have any questions or suggestions, feel free to comment below.
Similar Code Snippets:
I code and create web elements for amazing people around the world. I like work with new people. New people new Experiences.
I truly enjoy what I’m doing, which makes me more passionate about web development and coding. I am always ready to do challenging tasks whether it is about creating a custom CMS from scratch or customizing an existing system.