Skip to the content

Sticky header

The everyday navigation bar of a site, held at the top of the window: a logo, a row of links, one button, in your own markup.

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 bar is a box of your own: its class gives its padding, which is its height at the top of the page and what it gives up as it condenses, and its type. Do not give it a background, a transform or a position: the Embed holds it to the window and builds its ground. Give the first section of the page a padding at the top that clears the bar, and mark each dark section data-sticky-header-tone="dark" in its Settings panel. Nothing above the bar may carry a transform or a filter, or it stops being held to the window.
  3. Add custom JS

  4. Tune it

    Custom attributes
    Select the section 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-sticky-header Goes on the bar, a header as a rule, and takes no value: leave the value field empty. It holds the bar at the top of the window. The settings below go on the same element. Without it on any element of the page, the embed marks the first header of the page itself.
    data-sticky-header-tone="dark" On each section of the page that has a dark ground. While it is behind the bar, the text of the bar takes the colour of the ground and its ground the colour of the ink, cut on the edge of the section. A section with no mark is light; on a site set to base dark, mark the light sections data-sticky-header-tone="light" instead. Without any mark the bar keeps one tone. [ Optional ]
    data-sticky-header-plate On an element of the bar that is filled with the colour of the text, the button for one. It takes no value. Its ground and its text change places with the tone. Without it a filled button keeps its two colours and disappears on a dark section. [ Optional ]
    data-sticky-header-keep On what must keep its own colours in the bar, a logo in colour or a picture. It takes no value. It is left out of the tone and stands over the cut. [ Optional ]
    data-sticky-header-top On an element of the bar that only shows at the top of the page, the line beside the logo in the paste. It takes no value. It fades and lifts away as the bar condenses and keeps its place, so nothing else moves. [ Optional ]
    data-sticky-header-state, data-sticky-header-on, data-sticky-header-hidden, data-sticky-header-ready Written by the engine on the bar: top or scrolled, light or dark, hidden while the bar is away, ready once it is mounted. Never written by hand; the stylesheet reads them, and so can a rule of yours. [ Optional ]
    data-sticky-header-ground, data-sticky-header-cut, data-sticky-header-line, data-sticky-header-fill Written by the engine on the six blocks it adds to the bar: its ground, its hairline, the three plates that cut it in two tones, and the line of the reading progress. data-sticky-header-roll is written the same way on the box it puts around each label. Never written by hand, and removed by destroy(). [ Optional ]
    Settings
    Every setting is a custom attribute too, added the same way and on the same section. An attribute always wins over the defaults written in the code.
    AttributeDefaultWhat it is
    data-sticky-header-ink #15100c Colour of the text of the bar on a light section, and of its ground on a dark one; written on the bar as --sticky-header-ink. Options: any opaque CSS colour; an empty string in the settings block writes nothing and leaves the --sticky-header-ink of your stylesheet.
    data-sticky-header-ground #f4ece0 Colour of the ground of the bar on a light section, and of its text on a dark one; written on the bar as --sticky-header-ground. Give it the colour of your light sections and ink the colour of your dark ones, and the edge of a section runs through the bar with no seam. Options: any opaque CSS colour; an empty string leaves the --sticky-header-ground of your stylesheet.
    data-sticky-header-accent #ffab1a Colour of the line of the reading progress; written on the bar as --sticky-header-accent. Options: any CSS colour; an empty string leaves the --sticky-header-accent of your stylesheet.
    data-sticky-header-base light Tone of the page where no section is marked. Options: light, the bar is in ink unless a section says dark; dark, for a dark site, where the light sections are the ones to mark, data-sticky-header-tone="light".
    data-sticky-header-hide true Whether the bar follows the page away on a scroll down. It always stays near the top and at the foot of the page, while the keyboard is in it, while something in it is open and while one of its links carries the page. Options: true; false, the bar never leaves, and still condenses and takes its tones.
    data-sticky-header-hide-after 120vh How far the page has to be from its top before the bar may leave: a number of px, or a share of the height of the window written with vh. At the default the bar stays for the whole opening screen and for the first change of section, which is where its cut is first seen.
    data-sticky-header-tolerance 8 How far the scroll has to go in one direction, in px, before the bar starts to follow it; a smaller movement, a trembling finger or one notch of a precise wheel, leaves it where it is.
    data-sticky-header-settle 0.6 Time, in seconds, the bar takes to finish a move on its own: when the scroll stops with the bar halfway, when the keyboard calls it back, and for the condensing.
    data-sticky-header-condense 0.5 Share of its own top and bottom padding the bar gives up once the page has left the top, from 0 to 1. The content never touches: only padding goes.
    data-sticky-header-condense-after 16 How far the page has to be from its top, in px, before the bar condenses and takes its ground.
    data-sticky-header-progress true Whether the line under the bar shows the reading progress, and stays at the top of the window while the bar is away. Options: true; false, the hairline alone, and the bar leaves whole.
    data-sticky-header-roll true Whether each label of the bar, the logo, the links, the button, rolls a line when the tone changes, when the bar comes back and under the pointer of a mouse: the words leave upwards and a copy of them comes in from below, one label after the other from the logo to the button. The engine puts each label in a box of its own for it. Options: true; false, the labels are left as they are written and never move.
    data-sticky-header-anchor true Whether the engine writes a scroll-padding-top of the height of the condensed bar on the root, so that a link to an id lands below the bar. A page that already has a scroll padding of its own keeps it. Options: true; false.

What it does

Sticky header is an animated navigation component for Webflow and vanilla JavaScript, with no library. Also called sticky navbar hide on scroll, show navbar on scroll up or header change color on scroll section.

The everyday navigation bar of a site, held at the top of the window: a logo, a row of links, one button, in your own markup. At the top of the page it is tall and has no ground. Once the page has left the top it condenses: it gives up part of its padding, a ground comes behind it and a hairline draws itself under it. On a scroll down it does not snap away, it follows the page, one pixel for one pixel, until only its line is left at the top of the window, the thin line of the reading progress; on a scroll up it comes back the same way, and finishes on its own when the scroll stops halfway. It takes the colours of the section behind it, and not with a fade: where a dark section meets a light one behind the bar, the bar is cut on their edge, at the speed of the scroll, the upper part in one tone and the lower part in the other, letters and button split on the same line, so the edge of the page seems to run straight through the bar. A small scroll does not move it, the keyboard always brings it back, it stays while a link of its own carries the page to a section, and anchors land below it. Everything that moves is a transform; the scroll is read once per frame and the layout only when it changes. On a phone the bar is two lines, the logo and the button, then the links. Under reduced motion the bar leaves and comes back with no travel. Without the script it stays at the top on its ground. It is a bar, not a menu: it opens nothing, and pairs with the curtain menu or the push menu, whose button it can hold. Pattern type sticky header, hide on scroll navbar, header that changes colour by section, reading progress bar.

Updated

Questions

Put data-sticky-header on your header: the stylesheet holds it at the top of the window and the engine does the rest. The bar follows the page away, one pixel for one pixel, once the page is data-sticky-header-hide-after from its top, 120vh by default, and comes back the same way on a scroll up. data-sticky-header-hide="false" keeps it in place.

Mark each dark section data-sticky-header-tone="dark". While it is behind the bar, the text takes the colour of ground and the ground of the bar the colour of ink, and where two sections meet the bar is cut on their edge rather than faded, its labels rolling one after the other. A filled button of the bar carries data-sticky-header-plate so its two colours change places too.

The sticky header ignores a movement shorter than data-sticky-header-tolerance, 8 px by default, in one direction. Past it the bar moves by what the page moved, so there is no threshold to flicker around, and when the scroll stops halfway it finishes in data-sticky-header-settle, 0.6 s by default.

Yes. Past data-sticky-header-condense-after, 16 px by default, the sticky header gives up a share of its own padding, data-sticky-header-condense, 0.5 by default, and a ground and a hairline come. It is done with transforms: the box of the bar never changes size and the page is not laid out again.

They land below it: the engine writes a scroll-padding-top of the height of the condensed bar on the root, unless data-sticky-header-anchor="false". The bar comes back as soon as the Tab key reaches a link in it and stays while the focus is inside, and under reduced motion it leaves and returns with no travel.