Tiny Back to Top Button with Smooth Scroll

November 29, 2025

Tiny Back to Top Button with Smooth Scroll

This snippet adds a small “Back to top” button to your pages. When a visitor scrolls down, the button quietly appears in the corner. Clicking it scrolls the page back to the top in a smooth, built-in way, without opening extra windows or overlays, and without any extra libraries.

What this snippet does

The script watches how far the user has scrolled. Once they pass a certain distance, it shows a compact button in the lower corner of the screen with an arrow and a “Top” label. If the visitor scrolls back up near the top, the button hides itself again.

When the button is clicked, it scrolls the page back to the top. Modern browsers get a smooth scrolling effect. Older browsers fall back to a simple jump to the top, so nothing breaks. There are no network requests, no tracking, and no external dependencies.

Why you might want this

  • Long articles or docs where scrolling back up is annoying.
  • Mobile pages where the browser chrome hides the native scroll bar.
  • Layouts with fixed headers where you want a clear “go back up” action.
  • Any site that wants a small, unobtrusive UX helper instead of a big widget.

Because it is so small and it only scrolls within your own page, this helper plays nicely with display ads and other content. It does not open new windows, does not cover ads, and does not alter ad behavior.

The snippet (CSS + JavaScript)

Drop the CSS and JavaScript from this post into your theme or layout where you normally keep site-wide styling and scripts. A common place is near the end of the <body> so the button is created after the page structure is ready.

<style>
  /* Back-to-top button container */
  #vs-back-to-top {
    position: fixed;
    right: 16px;
    bottom: 16px;
    z-index: 9999;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 8px 12px;
    border-radius: 999px;
    border: 1px solid #C4C6F5;
    background: #F9FAFF;
    color: #000;
    font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    font-size: 13px;
    cursor: pointer;
    box-shadow: 0 2px 6px rgba(0,0,0,0.10);
    opacity: 0;
    pointer-events: none;
    transition:
      opacity 0.2s ease-out,
      transform 0.2s ease-out,
      box-shadow 0.2s ease-out;
    transform: translateY(6px);
  }

  #vs-back-to-top span {
    margin-left: 4px;
  }

  #vs-back-to-top.vs-visible {
    opacity: 1;
    pointer-events: auto;
    transform: translateY(0);
  }

  #vs-back-to-top:hover {
    box-shadow: 0 3px 10px rgba(0,0,0,0.16);
  }

  /* Small screens: tuck a bit closer to the edge */
  @media (max-width: 600px) {
    #vs-back-to-top {
      right: 10px;
      bottom: 10px;
      padding: 7px 10px;
      font-size: 12px;
    }
  }
</style>

<script>
  (function () {
    var BUTTON_ID = 'vs-back-to-top';
    var SCROLL_TRIGGER = 400; // px from top before showing button

    // If someone already has a button with this ID, don't create another
    if (document.getElementById(BUTTON_ID)) {
      return;
    }

    var btn = document.createElement('button');
    btn.id = BUTTON_ID;
    btn.type = 'button';
    btn.setAttribute('aria-label', 'Back to top');
    btn.innerHTML = '↑<span>Top</span>';

    document.addEventListener('DOMContentLoaded', function () {
      document.body.appendChild(btn);
    });

    function onScroll() {
      var y = window.scrollY || window.pageYOffset || 0;
      if (y > SCROLL_TRIGGER) {
        btn.classList.add('vs-visible');
      } else {
        btn.classList.remove('vs-visible');
      }
    }

    function prefersReducedMotion() {
      try {
        return window.matchMedia &&
               window.matchMedia('(prefers-reduced-motion: reduce)').matches;
      } catch (e) {
        return false;
      }
    }

    function scrollToTop() {
      if (prefersReducedMotion()) {
        window.scrollTo(0, 0);
      } else if ('scrollBehavior' in document.documentElement.style) {
        window.scrollTo({ top: 0, behavior: 'smooth' });
      } else {
        // Simple fallback without smooth behavior
        window.scrollTo(0, 0);
      }
    }

    window.addEventListener('scroll', onScroll, { passive: true });
    btn.addEventListener('click', function () {
      scrollToTop();
    });
  })();
</script>

How to integrate it

  1. Copy the CSS and JS snippet from this page.
  2. Paste it into your base template, layout file, or global footer include.
  3. Deploy and visit any page that uses that layout.
  4. Scroll down and watch the “Top” button fade in and out.

The script runs on any page that includes it, so if you only want the button on certain sections (for example, long blog posts or docs), include the snippet only in those templates.

Customizing the button

You can adjust a few simple values to match your site:

  • Label: change btn.innerHTML = '↑<span>Top</span>'; if you prefer different text or an icon.
  • Trigger distance: update SCROLL_TRIGGER to control how far down the user must scroll before the button appears.
  • Position & size: edit the CSS for #vs-back-to-top to move the button or tweak padding, font size, and spacing.

Accessibility and reduced motion

This snippet checks the visitor’s prefers-reduced-motion setting. If a user has requested reduced motion at the system level, the script uses an instant jump instead of smooth scrolling. That keeps the behavior friendly for people who are sensitive to animation.

You can also customize the button’s label to something more descriptive, such as “Back to top of page”, and adjust the aria-label attribute if needed. This helps screen reader users understand exactly what the button does.

Overall, it’s a small, focused helper: no tracking, no advertising logic, and no unexpected behavior—just a tiny button that helps visitors get back to the top of your content quickly.

Comments (0)

No comments yet — be the first.

← Back to all scripts