Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Scroll Progress Button

Dependency-free SVG scroll progress button with smooth scroll-to-top behavior.

It is useful for blogs, landing pages, documentation pages, and long article layouts.

The button shows page scroll progress by drawing an SVG path. When clicked, it scrolls the page back to the top.

Created as part of the development effort for Unboxed.sk.

Features

  • Pure JavaScript.
  • No runtime dependencies.
  • Works with plain CSS, Tailwind CSS, Bootstrap, and React.
  • Shared stylesheet with CSS-variable fallbacks.
  • Uses SVG path stroke progress.
  • Smooth scroll-to-top on click.
  • Configurable activation threshold.
  • Default activation threshold: 60px.
  • Supports multiple progress buttons on the same page.
  • Safe when no matching element exists.
  • SPA-friendly destroy() method.

Basic HTML

<link rel="stylesheet" href="src/scroll-progress.css">

<button class="progress-wrap" aria-label="Scroll back to top">
  <svg class="progress-circle" viewBox="-1 -1 102 102" aria-hidden="true">
    <path d="M50,1 a49,49 0 0,1 0,98 a49,49 0 0,1 0,-98"></path>
  </svg>
  <svg class="progress-icon" viewBox="0 0 24 24" aria-hidden="true">
    <path d="M12 5l-6 6h4v6h4v-6h4z"></path>
  </svg>
</button>

<script src="src/scroll-progress.js"></script>

Custom activation offset

By default, the button becomes active after the page is scrolled 60px.

Override this with data-active-offset:

<button class="progress-wrap" data-active-offset="120" aria-label="Scroll back to top">
  ...
</button>

The active-progress class then appears after 120px of scrolling. Missing, empty, or invalid values fall back to 60.

Styling and CSS variables

Use the provided stylesheet:

<link rel="stylesheet" href="src/scroll-progress.css">

All values have fallbacks. Override only what a design needs:

<button
  class="progress-wrap"
  style="
    --progress-size: 56px;
    --progress-color: #2563eb;
    --progress-background: #eff6ff;
    --progress-stroke-width: 5;
    --progress-icon-size: 26px;
  "
>
  ...
</button>

Available variables:

Variable Fallback Controls
--progress-size 48px Button width and height
--progress-circle-size Button size minus 4px Progress SVG size
--progress-icon-size 24px Arrow icon size
--progress-color #0f172a Default circle and icon color
--progress-stroke-color currentColor Circle color only
--progress-icon-color currentColor Icon color only
--progress-background #fff Button background
--progress-stroke-width 4 SVG progress stroke width
--progress-stroke-linecap round SVG stroke ends
--progress-bottom 24px Bottom position
--progress-right 24px Right position
--progress-left 24px Left position with .progress-wrap--left
--progress-z-index 50 Stacking order
--progress-radius 999px Corner radius
--progress-border 0 Button border
--progress-shadow Included soft shadow Box shadow
--progress-hidden-translate 12px Hidden-state vertical movement
--progress-transition-duration 180ms Visibility transition
--progress-focus-color #38bdf8 Keyboard focus outline

The stylesheet disables its visibility transition when the user prefers reduced motion.

React

The optional React component is exported from scroll-progress-button/react. Import the shared stylesheet once:

import ScrollProgressButton from 'scroll-progress-button/react';
import 'scroll-progress-button/styles.css';

export default function Page() {
  return (
    <ScrollProgressButton
      activeOffset={120}
      size={56}
      iconSize={26}
      strokeWidth={5}
      color="#2563eb"
      backgroundColor="#eff6ff"
      sideOffset={32}
      style={{
        '--progress-bottom': '32px',
        '--progress-shadow': '0 16px 40px rgb(37 99 235 / 20%)'
      }}
    />
  );
}

Common React props:

Prop Default Description
activeOffset 60 Activation distance in pixels
alwaysVisible false Keeps the button visible at the page top
smooth true Enables smooth scroll unless reduced motion is preferred
position "right" Use "left" or "right"
sideOffset CSS fallback Distance from the selected side
size CSS fallback Number in pixels or any CSS length
iconSize CSS fallback Number in pixels or any CSS length
strokeWidth CSS fallback Progress stroke width
color CSS fallback Default foreground color
backgroundColor CSS fallback Button background
icon Included arrow Any React node used as the icon
className "" Additional button classes
style {} Inline styles and arbitrary CSS variables
ariaLabel "Scroll back to top" Accessible button name
onClick — Additional click handler; call preventDefault() to cancel scrolling

Other native button props are passed through to the underlying semantic <button>.

How the SVG progress works

The script measures the path with:

path.getTotalLength()

It then initializes the stroke:

path.style.strokeDasharray = `${length} ${length}`;
path.style.strokeDashoffset = length;

At the top of the page, the stroke is fully hidden. At the bottom, strokeDashoffset becomes 0, making the complete stroke visible.

API

Auto init

The script automatically initializes every element matching .progress-wrap.

Manual init

const instances = initScrollProgress('.progress-wrap');

Destroy

Useful in SPA environments:

instances.forEach(instance => instance.destroy());

Data attributes

Attribute Default Description
data-active-offset 60 Scroll distance in pixels before .active-progress is added.

Examples

  • examples/vanilla.html
  • examples/tailwind.html (uses the Tailwind CDN)
  • examples/bootstrap.html (uses the Bootstrap CDN)
  • examples/react.html (uses React from a CDN)

The Vanilla, Tailwind, and Bootstrap examples can be opened directly. Serve the project for the React module example:

npm start

Browser support

Modern browsers that support:

  • querySelectorAll
  • classList
  • dataset
  • window.scrollTo({ behavior: 'smooth' })
  • SVG getTotalLength()

For older browsers, smooth scrolling may degrade to instant scrolling depending on support.

Accessibility

Use a real <button> element where possible:

<button class="progress-wrap" aria-label="Scroll back to top">

Avoid using only a decorative <div> unless you also add keyboard behavior and proper ARIA attributes.

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages