A sticky Bootstrap 6 navbar for one-page sites and long product pages. Its pill links highlight the section currently in view with the Bootstrap 6 ScrollSpy plugin, scroll smoothly to a section on click and show a thin reading progress line. The demo sits inside a browser-style frame so the sticky behavior works inside the preview.
How it works
.ssn-frame is the scroll container. It carries data-bs-spy="scroll", data-bs-target="#ssn-links", data-bs-top-margin="96px" and data-bs-smooth-scroll="true". The Bootstrap 6 bundle initialises ScrollSpy from these attributes with no extra code. ScrollSpy uses an IntersectionObserver with an activation line 96px below the top of the frame, just under the navbar. It adds .active to the link whose section has crossed that line. At the very top the first link stays active, and at the bottom the last one is activated.
The .navbar.sticky-top sits inside the frame, so it stays pinned while the sections scroll beneath it. Links are a .nav.nav-pills list. Each href points to a section id, such as #ssn-pricing.
script.js listens for activate.bs.scrollspy and moves aria-current to the newly active link. On narrow screens it scrolls that link into view, because the link row becomes a horizontally scrollable strip. A passive scroll listener writes --ssn-progress on .ssn-root, which scales .ssn-progress-bar.
Customization
--ssn-accenton.ssn-root: changes the active pill, the progress line, the brand mark and the section labels.data-bs-top-marginon.ssn-frame: moves the activation line, for example120pxfor a taller navbar.--ssn-frame-heighton.ssn-root: sets the height of the demo frame.- To spy on the whole page, delete the
.ssn-chromebar and movedata-bs-spy,data-bs-targetand the otherdata-bs-*options from.ssn-frameto<body>. Then remove theheightandoverflow-yrules of.ssn-frame. - Swap
nav-pillson.ssn-linksfornav-underlineto get an underlined active link instead of a filled pill. @container ssn (width >= 760px)instyle.css: changes the width at which the links move between the brand and the button.- Delete
.ssn-progressfrom the navbar and the scroll listener inscript.jsif you do not want the progress line.
Use cases
- One-page sites: pill links highlight the section currently in view and scroll smoothly on click
- Long product pages: a thin progress line shows how far the visitor has read
- Mobile readers: the link row becomes a swipeable strip that keeps the active link in view
- Documentation-style pages: the sticky bar stays pinned while sections scroll beneath it
Accessibility
The navbar is a <nav> labelled "Page sections". The active link gets aria-current="true". The frame is focusable (tabindex="0") with a visible focus outline, so keyboard users can scroll it with the arrow keys. Every section is labelled by its heading. The FAQ uses native <details> elements, which work without JavaScript. Smooth scrolling is turned off under prefers-reduced-motion: reduce.
Bootstrap 6 notes
ScrollSpy keeps the BS5 data-bs-spy="scroll" API, but now sets its activation line with data-bs-top-margin, and rootMargin is an advanced override. .nav-pills gains --bs-nav-pills-* variables. The badge uses .badge-subtle.theme-success instead of text-bg-*, and the FAQ is the new <details class="accordion-item"> accordion. Built on Bootstrap 6.0.0-alpha.1, so APIs may still change. Icons come from Bootstrap Icons.