Skip to the content

Scroll chapters

A table of contents for a long page, built by itself from the titles of the page: every h2 of the marked block opens a chapter, and the list follows when a title is added, removed or reworded.

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 look of the preview is the scroll-chapters-* classes of the paste: the size of the number, the type of the list, the two columns. The Embed holds what moves, and reads these variables: --scroll-chapters-accent (the small square beside the line being read, and the number of the strip), --scroll-chapters-quiet (the strength of the ink of what is not being read, 42%), --scroll-chapters-pin, --scroll-chapters-shift, --scroll-chapters-top, and for the strip of a narrow window --scroll-chapters-strip, --scroll-chapters-strip-ink, --scroll-chapters-bar and --scroll-chapters-gutter. Set them on the block, or on anything above it, in a rule of your own. No parent of the table may cut its overflow with overflow: hidden, or it stops being held beside the text.
  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-scroll-chapters Marks the block that holds the text and its table of contents. It takes no value: leave the value field empty. Every title in it that matches the setting headings, every h2 by default, opens a chapter. The settings below go on the same element.
    data-scroll-chapters-nav On the table of contents, inside the block. It takes no value. It is the part held beside the text on a wide window, and the sheet at the foot of a narrow one. Name it for screen readers with aria-label, "Chapters" in the paste. Without it the block is left alone and the engine says so in the console. [ Required ]
    data-scroll-chapters-list On the box that holds the lines of the list and nothing else, inside the table. It takes no value. The engine writes one line in it for each title it finds; the lines written by hand are what shows on the canvas and without JavaScript. [ Required ]
    data-scroll-chapters-item On the lines of the list: a link, or a block that holds one. It takes no value. The first one is the model of every line the engine writes: style that one line and every line follows. The other lines written by hand may carry the mark too, as they do in the preview; the engine replaces them all. Without it the engine writes plain links. [ Optional ]
    data-scroll-chapters-item-number In the model line, on the element that receives the number of the chapter, 01. It takes no value. [ Optional ]
    data-scroll-chapters-item-title In the model line, on the element that receives the title of the chapter. It takes no value. Without it the title goes in the link itself. [ Optional ]
    data-scroll-chapters-number On an element that receives the number of the chapter being read, on wheels that turn with the scroll. It takes no value. Its class gives the size of the figures. [ Optional ]
    data-scroll-chapters-total On an element that receives how many chapters there are, 06. It takes no value. [ Optional ]
    data-scroll-chapters-left On an element that receives the minutes of reading left, a figure alone: the words around it, min left, are yours. It takes no value. [ Optional ]
    data-scroll-chapters-title="Short name" On a title of the page: the wording the list uses for it, when the title itself is too long for the list. [ Optional ]
    data-scroll-chapters-skip On a title of the page that must not open a chapter. It takes no value. [ Optional ]
    data-scroll-chapters-state Written by the engine on a line of the list: current on the chapter being read, read on the ones before it. The block carries data-scroll-chapters-mode (side or strip) and data-scroll-chapters-ready, the table data-scroll-chapters-in while the block is on screen and data-scroll-chapters-open while its sheet is up. Never written by hand; the stylesheet reads them, and so can a rule of yours. [ 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-scroll-chapters-headings h2 The titles that open a chapter, as a CSS selector read inside the block. Options: h2, the default; h2, h3 to list two levels; .chapter-title or [data-chapter] for titles of your own.
    data-scroll-chapters-line 0.4 The height in the window where a chapter becomes the one being read, as a share of the window: 0 its top, 1 its foot.
    data-scroll-chapters-offset clamp(72px, 14vh, 140px) Where the title of a chosen chapter lands, measured from the top of the window, in any CSS length.
    data-scroll-chapters-roll 0.3 The stretch of scroll over which the number turns before the next title, as a share of the window height.
    data-scroll-chapters-speed 230 The reading speed the minutes left are worked out from, in words a minute.
    data-scroll-chapters-duration 1.1 The time of the travel to a chosen chapter, in seconds: the page, the square of the list and the number move together over it.
    data-scroll-chapters-strip 900 The width of the window, in px, under which the table of contents leaves the side of the text and docks as a strip at the foot of the window.
    data-scroll-chapters-hash on Whether the chosen chapter is written in the address of the page. Options: on, a line chosen by the visitor writes the id of its title after the #, without adding a step to the history; off, the address is left alone.

What it does

Scroll chapters is an animated navigation component for Webflow and vanilla JavaScript, with no library. Also called table of contents, scrollspy table of contents or sticky table of contents with reading progress.

A table of contents for a long page, built by itself from the titles of the page: every h2 of the marked block opens a chapter, and the list follows when a title is added, removed or reworded. Beside the text, on a wide window, it holds a large number that is geared to the scroll: it stands still while a chapter is read and turns to the next figure, like the wheel of a counter, over the last stretch before the next title. In the list every title is quiet but the one being read, which has a small square of the accent hung beside it and takes its full ink from its first letter to as far as the chapter has been read, line after line for a long title. A chapter chosen in the list is reached in one move: the page travels, the square goes from one line to the other, the number rolls straight from the figure it shows to the one it reaches, and nothing between the two lights up on the way; a page that rushes by changes nothing in the list until it slows down. A small counter gives the minutes of reading left, from the words of the page. A click or Enter on a line travels to its chapter, eased, and the reader takes the page back at any time. On a narrow window the table docks as a strip at the foot of the window, with the number and the title being read rolling on the same wheel, and rises as a sheet with the whole list when it is pressed. Titles short or long, three chapters or fifteen, pictures that load late: the places are measured again whenever the block changes size. Without JavaScript the list written in the page is a plain list of links. Reduced motion respected. No library. Pattern type table of contents, reading progress, scrollspy, chapter navigation.

Updated

Questions

Paste the block, or mark the block that holds your text data-scroll-chapters and put inside it a table marked data-scroll-chapters-nav with a list marked data-scroll-chapters-list. Every Heading 2 of the block becomes a line of the table of contents, also inside a Rich Text element, and the list follows when a heading is added, removed or reworded.

Yes. The title of the chapter being read takes its full ink from its first letter to as far as the chapter has been read, a small square of the accent hangs beside it, and its link carries aria-current="location". A large number marked data-scroll-chapters-number turns to the next figure like a counter wheel as the next heading arrives.

Yes. An element marked data-scroll-chapters-left receives the minutes of reading left, worked out from the words of the page that are still below the reading line. The reading speed is the setting speed, 230 words a minute by default: data-scroll-chapters-speed="200" for a denser text.

Under the width given by data-scroll-chapters-strip, 900 px by default, the table of contents leaves the side of the text and docks as a strip at the foot of the window, with the number and the title being read. Pressing the strip raises a sheet with the whole list; a line, Escape or a touch outside lowers it.

Set data-scroll-chapters-offset on the block to at least the height of the header, in any CSS length: it is where the title of a chosen chapter lands, measured from the top of the window. The travel takes duration seconds, and the list goes straight to the chosen chapter without lighting the ones in between.