Skip to the content

Pill nav

A navigation bar whose highlight is alive.

Become a member to unlock the full effect today.

Join now

Already a member? Sign in

Documentation

  1. Copy to Webflow

    Add Geist and Geist Mono to your site's fonts (Site settings, Fonts, Google Fonts) before pasting: Webflow removes any font your site has not installed.

  2. Add custom CSS

    The pill is laid over the links and the text it covers is a copy drawn over the pill, so the box that holds the links must not clip (overflow: hidden) when the pill reaches past its edge, and its last link is no longer its :last-child.
  3. Add custom JS

  4. Use it on your own elements

    Custom attributes
    Select the element on the canvas and open the Settings panel. Under Custom attributes, add a pair: the name on the left, the value on the right.
    Custom attributeWhat it does
    data-pill-nav Marks the box that holds the links. It takes no value: leave the value field empty. That box is what the pill travels in, what the effect is mounted on and what carries the settings. Without it on any box of the page, the embed marks the parent of the first link it finds next to itself, and says so in the console when there is none.
    data-pill-nav-link Marks one link the pill can sit on, inside that box. It takes no value. Without it on any link, every link, button and tab of the box is taken. [ Optional ]
    aria-current="page" Marks the current link, the one the pill rests on and comes back to. Webflow writes it by itself on a link to the page being shown. Without it on any link the pill is hidden at rest and shows under the pointer; a click then moves it to the clicked link. [ Optional ]
    data-pill-nav-state Written by the engine on the box: live while the pill travels, idle at rest, empty when no link is current and none is under the pointer. Never written by hand. [ Optional ]
    Settings
    Every setting is a custom attribute too, added the same way and on the same element. An attribute always wins over the defaults written in the code.
    AttributeDefaultWhat it is
    data-pill-nav-color #ffab1a Colour of the pill, the amber #ffab1a by default. Options: any CSS colour; taken out of this block, --pill-nav-color on the bar takes over.
    data-pill-nav-ink #15100c Colour of the text where the pill covers it, the ink #15100c by default. Options: any CSS colour that reads on color; taken out of this block, --pill-nav-ink on the bar takes over.
    data-pill-nav-radius 100vmax Corner radius of the pill, any CSS unit; a radius larger than half the pill is brought back to a full capsule.
    data-pill-nav-pad 0em How far the pill reaches past the box of a link, any CSS unit, one value for the four sides or two, vertical then horizontal.
    data-pill-nav-stiffness 260 Pull of the spring that carries the leading edge of the pill.
    data-pill-nav-damping 22 Friction of the spring.
    data-pill-nav-stretch 0.5 How much softer the trailing edge is than the leading one, 0 to 1, and how much the pill thins while it is long.
    data-pill-nav-orientation auto Axis the pill stretches along. Options: auto reads it from each move, the longer way between the two links; horizontal and vertical hold it to one axis whatever the move.
    data-pill-nav-spy 0 Scroll spy: the link whose section is on screen becomes the current one while the page scrolls. Options: 0 off, the current link is the one marked in the markup or clicked; 1 on, for links to anchors of the same page.

What it does

Pill nav is an animated navigation component for Webflow and vanilla JavaScript, with no library. Also called sliding pill navigation, sliding nav indicator or navbar sliding highlight.

A navigation bar whose highlight is alive. One pill sits on the current link. When the pointer moves over another link, the pill travels to it: the edge that leads leaves first and the edge that trails follows on a softer spring, so the pill stretches the way it goes, thins a little while it is long, then gathers itself and squashes lightly as it lands. The text takes a second colour exactly where the pill covers it, so a letter half under the pill is half in each colour, all the way through the travel. Leaving the bar sends the pill back to the current link, a click makes the clicked link the current one, and the keyboard focus moves the pill the same way. It works on a row of links and on a column, the axis of the stretch chosen from the move itself, and follows a resize, a late font or a link the page rewrites: every position is measured, none is kept. By a setting it marks the section on screen while a one-page site scrolls. No library: two boxes the script adds to the bar, a spring stepped by hand, a clip path. On touch a tap sends the pill to the tapped link; under reduced motion the pill jumps.

Updated

Questions

Give the box that holds the links the custom attribute data-pill-nav and each link data-pill-nav-link, in the Settings panel. Webflow already writes aria-current="page" on a link to the page being shown, and that is the link the pill rests on. Settings are more attributes on the bar, for instance data-pill-nav-color="#d4ff3f".

No. The script adds two boxes to the bar, steps a spring by hand and clips a copy of the links with clip-path, with no library and no build step. When the pill has landed the loop stops: no frame and no timer run at rest.

data-pill-nav-stiffness is the pull of the spring, 260 by default: lower gives a slow, heavy pill, and past 600 it snaps to the link almost at once. data-pill-nav-damping is the friction, 22 by default: under 14 the pill bounces several times before it rests, past 32 it glides in with no bounce.

Yes, with data-pill-nav-spy="1", which is off by default. Every link whose href names an anchor of the page watches that section, and the section that crosses a line 40% down the window becomes the current link, marked aria-current="location". A section that never crosses that line, the last one of a short page for instance, never becomes current by scrolling alone.

Yes. The keyboard focus moves the pill the same way the pointer does, and on touch a tap sends the pill to the tapped link. The copy of the links that carries the second text colour is inert and aria-hidden, and under prefers-reduced-motion the pill jumps to its link with no travel.