061

Horizontal Scroll Template

£15 View live demo or the whole Vault, £79.20

A horizontal scroll website template written as a furniture workshop's showroom: a headline at display scale running into a photograph, then six plates on one pinned rail that vertical scroll pans sideways, with a timber picker that recolours its plate and a table whose sizes draw over the photograph. Re-points to a furniture maker, a lighting studio, a ceramicist, an interiors shop, a product designer's portfolio or a gallery.

ScrollTrigger Lenis advanced
12 more details
horizontal-scrollpinningscrubcontainer-animationparallaxmask-revealsvg-line-drawcount-upclick-statepointer-effectskeyboard-navigationscroll-reveal

Released

About this template

Foundry & Form is a complete one-page site for a furniture workshop in Hebden Bridge, and the whole site is one horizontal showroom. The hero sets two lines of Baskervville at display scale with the first piece's photograph bled off the right edge. Then six plates sit on one rail, and scrolling down walks you along it: a chair full bleed with its name and price, a sideboard beside its three-line sizes, two views of a fluted oak table with one bled off the top, a plate that is only type and three timbers, a long table whose dimensions draw themselves over the photograph, and a bench with an invitation to visit the workshop. The bar under the rail shows which piece you are beside and what it costs, with six marks to jump to and arrows either side.

Read the full template overview

The fiction is a workshop that makes furniture to order in three timbers, with prices, sizes and lead times on every piece. The page reads the same with the pieces swapped for lamps, pots, ceramics, a designer's projects or a gallery's works: each plate is a photograph, a name, a price and a line, and the rail adjusts to however many there are. Under the showroom a dark section holds one photograph of the workshop, the figures, and an enquiry form.

Everything is static HTML, CSS and one script: no build step, no framework, two typefaces from Google Fonts. Repaint the five values in the token block to reskin it, drop your own photographs into assets/img, and rewrite the copy. Each section is independent, so any of them can be deleted without touching the JavaScript, and without JavaScript, on a phone, or under reduced motion the six plates stack as six full-width panels.

Horizontal Scroll Template - website template preview

What's included

11 items
  • Pinned horizontal showroom: six variable-width plates on one rail, panned by vertical scroll, with a bar underneath that names the piece you are beside, counts its price, marks the six positions and offers arrows and arrow keys
  • Six plate shapes, not one: full bleed with name and price; photograph beside a three-line spec; two views of one piece with one bled off the top; a type-only plate; a photograph bled off the bottom with its sizes drawn over it; a wide photograph with the invitation to visit
  • Timber picker: three timbers on a type-only plate, and choosing one recolours the whole plate to that timber and counts two prices to the new figures
  • Dimensions drawn on the photograph: three measured lines and their figures draw themselves over the long table as the pointer arrives and undraw as it leaves, with a button that pins them for touch and keyboard
  • Hero as type-as-image: two lines of Baskervville at up to 12rem running into a photograph bled off the right edge, masked in on load
  • Ghost words drift against the rail on two plates, and the arriving photographs settle from a slight zoom, both driven by the same scrub
  • Seven baked WebP photographs, graded as one set, 0.8MB in total, with a manifest to regenerate them from your own
  • Warm oat ground, near-black ink and one marking-out blue, every translucent value mixed from RGB triples, so a reskin is a five-value edit
  • Designed reduced-motion and phone page: the plates stack as six full-width panels, the timber picker and the sizes button still work with their changes applied instantly
  • Readable with JavaScript disabled or the CDN blocked, every plate, price and size included
  • Lenis smooth scroll wired on the shared GSAP clock, opt-out per page or per URL

Perfect for

6 use cases
  • Furniture makers and joinery workshops selling pieces made to order
  • Lighting studios, ceramicists and makers with a short run of products and prices
  • Interiors and homeware shops presenting a small, considered range
  • Product designers and industrial designers showing a portfolio of objects
  • Galleries and dealers presenting a collection or an exhibition piece by piece
  • Any site where the content is a sequence of things best walked along in a row

How it works

5 sections

Structure

One script, one setup and teardown path, one init per section, each returning early when its markup is absent, so any section can be deleted. A synchronous head script adds a class before first paint so the reveal states apply without a flash, and the main script removes it again if the CDN is blocked. The header is fixed and every plate is padded to clear it and the bar at the foot. In-page links are scrolled by the script rather than the browser, because a native hash jump to a pinned section lands wherever the pinned element currently is rather than at the section's start.

The showroom rail

The six plates are flex children of one track. On a wide screen with motion allowed, ScrollTrigger pins the stage and scrubs the track sideways by exactly its overflow, so the plates can be any width and any number. On every update the script finds the plate nearest the left edge and, when it changes, slides the old name out of the bar and the new one in while a counter tweens the price. The ghost words and the arriving photographs run on secondary scrub tweens tied to the same pan through containerAnimation. Everywhere else the stage takes a stacked class and the plates become full-width panels.

The timber picker

The plate's ground and ink are two custom properties. Each timber button carries its tint and its ink and a price factor; choosing one tweens the two properties on the plate, so the whole plate takes the timber's colour, and tweens a counter object whose two values are written into the readout as pounds. Arrow keys move between the buttons as a radio group.

The sizes on the long table

Three dimension lines and their labels live in an SVG laid over the photograph, in the photograph's own coordinates and cropped the same way, so they stay on the table at any viewport. A paused timeline draws each line from nothing to its full length and fades the labels in, played as the pointer arrives and reversed faster as it leaves. The button plays the same timeline and holds it, for touch and keyboard, and under reduced motion it toggles a class that shows the lines instantly.

Without JavaScript or motion

Without the script the page is a plain document: the six plates stack, the sizes on the long table are drawn, and the bar is hidden. Under prefers-reduced-motion the CSS restores every gated element, the stage stacks, and the same init functions run without tweens, so the timber picker and the sizes button still work.

Plugins ScrollTrigger
Difficulty Advanced
Smooth scroll Lenis integration
Includes HTML + JS + CSS source, documentation, AI setup prompt, lifetime updates

Lighthouse, as measured

Google Lighthouse on this template's demo, from the latest scan. A measurement of the demo as shipped, not a promise for your page.

Accessibility
100
Best practices
100

No performance score, on purpose. That figure depends on how you deploy: your server's compression and caching, your CDN, the connection and the device doing the test, none of which the code controls. The same page can score very differently on two consecutive runs, so measure it where it will live.

Questions about this template

It's a furniture workshop in the demo. What else does this design suit?

Anything sold as a short row of things with a price: a furniture maker, a lighting studio, a ceramicist, an interiors shop, a product designer's portfolio, a gallery's collection. Each plate is a photograph, a name, a price and a line, and the rail, the bar and the marks adjust to however many plates there are. Nothing in the layout says furniture except the words and the pictures.

Can I use my own photographs, and what happens to the seven included?

Yes. The seven are graded WebP derivatives of Pexels photographs, bundled for the demo, and you can ship them or replace them. Drop your own files into assets/img with the same names, or edit assets/img-manifest.json with your sources and run the bake script to get matched, optimised WebP with one grade across the set. Full-bleed plates want about 1920 pixels wide; the paired views 1200 to 1400.

How do I add pieces, or have four instead of six?

Each plate is one article in index.html with a name and a price on it. Copy one of the six shapes or delete one, and add or remove its mark in the bar. The rail measures its own width, so the scroll distance, the progress bar and the arrows adjust without any numbers to retune. Four plates is the fewest that still reads as a showroom; ten is the most before the scroll gets long.

Do the sizes on the long table match my table?

No, they are drawn for the photograph in the demo. The three lines and their labels are in an SVG over the image, in a 1000 by 562 coordinate space that crops exactly as the photograph does. Replace the photograph, then move the line coordinates in index.html to where your table's edges are and change the three figures. Delete the SVG and the button if you do not want sizes at all.

How does it behave on a phone?

Under 900 pixels wide the rail is not pinned: the six plates stack as full-width panels in the same order, the bar under the showroom is hidden, and the page scrolls normally. The timber picker works by tap and the sizes on the long table appear from the button rather than on hover. The same stacked layout is what visitors with reduced motion turned on get at any width.

Does the enquiry form send anything?

No. It collects a name, an email, a piece, a timber and a note, and submitting it shows a line saying nothing was sent. This is a static front end with no server behind it, so point the form's action at Formspree, Netlify Forms or your own inbox and it becomes a real enquiry. The prices in the select are the demo's; change them with the copy.

How do I recolour it?

Five values in the token block at the top of style.css: the oat ground, the ink, the blue, the dark ground and the paper that sits on it, each with its RGB triple beside it. Every rule, scrim, dimmed label and focus ring is mixed from those, so nothing is left in the old colour. The timber plate has its own three colours on the buttons themselves, one per timber, and the contrast figure for each pair is written in the same comment.

Paid template

Purchase to unlock the code.

Buying Horizontal Scroll Template opens the HTML, CSS and JavaScript source, the full documentation, an AI setup prompt for your editor, and every update we ship to it. Standard license: unlimited personal and commercial projects. Every paid product is tested for desktop and mobile layouts, reduced-motion handling, animation cleanup and keyboard controls wherever there is something to operate.

£15 Standard license, unlimited projects

Browse free effects

Or the whole library: the Vault, £79.20, one payment.

Documentation

Quick start

No build step, no framework. Static HTML, CSS and one script.

  1. Unzip.
  2. Open index.html in a browser, or serve the folder with any static server (npx serve, python3 -m http.server).
  3. Deploy the folder as-is to Netlify, Vercel, Cloudflare Pages, GitHub Pages or your own host.

GSAP, ScrollTrigger and Lenis load from the CDN tags at the foot of index.html.

The sections

Section Hook What to edit
Hero [data-hero] The two lines of the h1, the paragraph, the photograph in .hero-photo. The photograph is bled off the right edge and fades into the ground on its left so the second line can run into it.
Showroom [data-showroom-rail] Six article.plate blocks on one track. Each carries data-name and data-price, which the bar reads. Copy or delete a plate and add or remove its mark in the bar; the rail measures its own width.
The bar [data-showroom-bar] The marks (data-piece-index, zero-based) and the arrows. Fixed while the rail is pinned; hidden on phones.
Workshop #workshop One photograph with a caption, the copy, the four figures.
Enquiry [data-enquire] The form. Static front end, see below.

The six plate shapes

Each plate is a different composition, and you can use any shape for any piece:

  • plate-bleed: a full-bleed photograph with the name and price over its foot.
  • plate-split: a photograph beside a three-line spec (dl.spec).
  • plate-pair: two views of one piece, the first bled off the top of the plate.
  • plate-timber: type only. Three timber buttons, each carrying data-tint, data-ink and data-factor; choosing one recolours the plate and multiplies the two prices in the readout. The base prices are in script.js (initTimbers).
  • plate-measure: a photograph bled off the bottom with its sizes drawn over it. The lines are an SVG in the photograph's own 1000 by 562 coordinates and crop exactly as the photograph does. Move the coordinates to your table's edges and change the three figures.
  • plate-close: a wide photograph, then the name and price beside an invitation to visit.

Plate widths are set per shape in style.css (100vw, 92vw, 84vw, 74vw). Any width works.

Navigation

Scrolling down pans the rail. The marks in the bar, the arrows, the progress track (click, or arrow keys when it has focus) and the left and right arrow keys while the rail is pinned all move between plates. Any link or button with data-jump-plate="n" jumps to plate n.

Palette

Five values in the token block at the top of assets/style.css, each with its RGB triple: the oat ground, the ink, the blue, the dark ground and the paper on it. Every rule, scrim, dimmed label and focus ring is mixed from those. The contrast of each pair as used is written in the same comment. The three timber colours live on the buttons themselves.

Photography

The seven images are graded WebP derivatives, bundled so the template renders as demonstrated. To use your own:

  • Drop files into assets/img/ with the same names, or
  • edit assets/img-manifest.json with your sources (local paths or URLs), sizes and grade, and run bun scripts/build-template-assets.ts horizontal-scroll-template to bake matched WebP with one grade across the set.

Full-bleed plates want about 1920 pixels wide; the paired views 1200 to 1400.

Credits. The originals are Pexels photographs, licensed under the Pexels licence, which permits modification and redistribution without attribution. The credits are given anyway:

File Pexels photo
chair.webp https://www.pexels.com/photo/2079294/
sideboard.webp https://www.pexels.com/photo/12277217/
table-top.webp https://www.pexels.com/photo/7607461/
table-side.webp https://www.pexels.com/photo/7607327/
dining.webp https://www.pexels.com/photo/20548025/
bench.webp https://www.pexels.com/photo/12233290/
workshop.webp https://www.pexels.com/photo/37358114/

The form

The enquiry form is a static front end and sends nowhere. Submitting it shows a line saying so. Point its action at Formspree, Netlify Forms or your own inbox:

Code snippet omitted: it ships with the download.

and remove the submit handler in initEnquire if you want a normal post.

Accessibility and fallbacks

  • Without JavaScript, or with the CDN blocked, the page is a plain document: the six plates stack, the sizes on the long table are drawn, and the bar is hidden.
  • Reduced motion: the plates stack, nothing is pinned, and the timber picker and the sizes button work with their changes applied instantly.
  • Phones (under 900px): the same stacked layout, with the sizes shown from the button rather than on hover.
  • The timber buttons are a radio group with arrow keys; the progress track is a slider with arrow keys; every button and link has a visible focus ring.

Smooth scroll

Lenis runs on GSAP's clock. Turn it off for one visit with ?smooth=off in the URL, or for the site with data-smooth="off" on <html>. It is off automatically under reduced motion.

Worked examples, the events and programmatic API, and the class reference ship with the download, alongside the full source.