Travel & Tour Template

£10

A complete one-page site for a boutique small-group tour operator, built on a lagoon-teal ground with a coral accent, and an interactive itinerary map whose route line draws itself in as its signature.

ScrollTrigger Lenis advanced
4 more details
svg-line-drawscroll-revealclick-togglestagger
Travel & Tour Template - website template preview

This template reads better at your own screen size than in the frame below:

About this template

A production-ready site for a small-group walking-holiday operator, built for the one thing a tour company has to sell before anything else: the shape of the journey. It runs on a saturated lagoon teal with cream type and a single coral accent, and carries warm, sunny, people-first photography, bundled as optimised WebP with the brand's grade baked into the pixels, so it looks finished the moment it opens.

Read the full template overview

The centrepiece is an interactive itinerary map. A stylised coastline is drawn in SVG rather than pulled from a map tile, seven numbered day-pins sit along it, and a coral route line draws itself in as the section scrolls into view. Choosing a day, either on the map or in the rail beside it, lights that pin and swaps in the day's card: where you walk, what you do, and where you sleep that night.

The rest of the page is disciplined around it: a hero framing walkers on the coast path, poster-tile cards carrying the wider collection on real trip photography, a plain what's-included and dates-and-prices block, one traveller's quote over a dinner shot, and an enquiry form. Every photograph sits under a teal scrim tuned so the cream text over it clears 4.5:1, and the copy, written for a fictional Portuguese coast operator in a warm, grounded voice, stays live text so the page is complete with images off. Every colour and price is yours to change in one token block.

What's included

12 items
  • Complete deployable one-page site: nav, hero, featured trips, the itinerary map, what's included, dates and prices, a testimonial, an enquiry form and footer
  • Signature interactive itinerary map: a stylised SVG coast, not a map tile, with a coral route line that draws itself in, no DrawSVG plugin needed
  • Seven numbered day-pins are real buttons, wired to the same day cards as the list beside them, so a day is one click or one tab-stop away on any device
  • Arrow keys, Home and End move between days with a roving tabindex, and every pin carries a full screen-reader label naming its day and village
  • Poster-tile trip cards carrying real, warm, sunny trip photography under a teal scrim tuned against the baked pixels, so the cream label and price clear 4.5:1 over any part of the image
  • Dates and prices as sand cards with per-departure availability, including a fully-booked waitlist state
  • A framed hero photo of walkers on the coast path beside a masked-line headline reveal, with the headline kept on the solid teal ground so its cream never drops below the contrast floor
  • Three-plus-one colour system: change teal, cream, coral and the sand surface and the whole site reskins, with every translucent value resolving from an RGB triple
  • Lenis smooth scrolling wired in and fully optional
  • Accessible by construction: the itinerary reads as a plain ordered list with JavaScript off, the map degrades to a decorative aside, reduced motion shows the route already drawn with day one open, and contrast is measured as used
  • Testimonials in a horizontal slider: several walker quotes on a native scroll-snap track with arrow buttons, keyboard and touch, readable as a plain list with JavaScript off
  • Photographs on three of the seven itinerary days (arrival, a clifftop stage, the final beach), so the day-by-day reads as a list broken up by the occasional view rather than a wall of images

Perfect for

5 use cases
  • Small-group tour, trek and walking-holiday operators
  • Cycling, sailing, river and expedition trips sold as a fixed multi-day route
  • Retreats, pilgrimages and food or wine tours with a day-by-day itinerary
  • Any single hero trip that needs its route and stops shown before the booking ask
  • Travel agents and DMCs presenting one signature journey per landing page

How it works

4 sections

Structure

One script initialises each section with a single setup and teardown path and one motion branch, keyed only on reduced motion so exactly one branch runs on every device. Every section is looked up behind a guard and skipped if absent, so a buyer can delete the hero, the trip grid or the whole map and the rest still runs. Event listeners are held in a Map and torn down, with the route and cards cleared, whenever the media query flips.

The itinerary map

The coast is a hand-drawn SVG shape, and the day-pins are HTML buttons positioned over it in percentages that match the route's own coordinates, so pins and line stay in register at every width. Each day groups its pin, its rail button and its card by day number rather than by list index, so the pairing survives a deleted day. Selecting a day lights its pin, marks its rail button, and fades its card in; pins and buttons share one activate() path, so pointer, touch and keyboard all land in the same place.

Drawing the route

The route line draws itself without a DrawSVG dependency: ScrollTrigger runs the draw once the section is in view, and the pins pop in behind it. The path's length is read defensively and the whole draw is skipped if it comes back zero, so swapping the path for a simpler line can never leave an empty corridor.

Reduced motion and without JavaScript

With reduced motion the route is painted in full, day one is the open card, and nothing scrubs or scrubs on scroll. With JavaScript disabled the seven days render as a plain ordered list, each with its title, activities and where you sleep, and the map becomes a decorative aside; the interactive card and pins only ever appear once a JS-added class upgrades the page, so no content is ever hidden behind a control that cannot work.

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

Questions about this template

Is the itinerary map a real map?

No, it is a stylised SVG coast rather than map tiles, so there is no maps API, no key and no usage billing. The coral route line draws itself in and needs no DrawSVG plugin. Redrawing it for your own route is illustration work.

Can visitors book a departure?

No. Dates and prices show per-departure availability including a fully-booked waitlist state, but the enquiry form is unwired and takes no payment. Small-group operators almost always want an enquiry and a conversation before a deposit anyway.

How many days can the itinerary hold?

Seven ship as numbered pins wired to matching day cards. Pins are real buttons with roving tabindex, arrow keys, Home and End, so extending means adding a pin and a card rather than rewiring navigation. A fourteen-day route would crowd the coast illustration.

Do I need a photograph for every day?

No, and deliberately not. Three of the seven days carry photographs (arrival, a clifftop stage, the final beach) so the day-by-day reads as a list broken by the occasional view rather than a wall of images. Trip cards carry poster photography under a scrim tuned so the price still clears 4.5:1.

What happens to the itinerary with JavaScript off?

It reads as a plain ordered list and the map degrades to a decorative aside, so the actual trip information is never trapped behind the interaction. Under reduced motion the route shows already drawn with day one open.

Paid template

Purchase to unlock the code.

Buying Travel & Tour 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.

£10 Standard license, unlimited projects

Browse free effects

Documentation

Quick Start

  1. Upload the folder. index.html, assets/style.css, and assets/script.js (or assets/script.min.js) are all you need. It is static: no bundler, no framework.

  2. Keep the three script tags just before </body> and leave them as plain tags (no integrity attribute, so a version bump never breaks your deployed copy):

Code snippet omitted: it ships with the download.

  1. Make it yours. Change the palette in the :root block of style.css (see Palette), rewrite the copy in index.html, and edit the itinerary (see The itinerary map). Point the enquiry form at your own inbox or booking system.

Sections & options

Every section is initialised behind a guard, so you can delete any section in index.html and the rest keeps working. No script edit needed.

Section What it is To change
Nav Fixed, blurred bar with a compass-diamond mark Edit links in .nav-links; the mark is .brand-mark (pure CSS)
Hero Trip name, masked-line headline, key facts, framed trip photo Headline lines are .line inside .mask; the photo is .hero-img (swap in Images)
Trail strip Row of village names Plain text in .trail-inner
Featured trips Three poster tiles, each a real trip photo under a teal scrim Add/remove .trip cards; swap .trip-img sources (see Images)
Itinerary map The signature (see below) Edit the day list and pins
Included + dates What's covered and departures Edit .included and .date-card blocks; .date-card--full is the waitlist state
Testimonial A dinner photo over one quote on a sand card Photo is .voice-photo; text in .voice-quote / .voice-by
Enquiry Styled form Set the <form action>; it is inert until you wire it
Footer Four-column Standard links

The itinerary map (signature)

The map lives in the #route section. Two things must stay in sync: the route path and the day-pins.

  • The coast and route are hand-drawn SVG <path>s in .map-svg (viewBox="0 0 820 620"). The route is the <path data-route>. Draw whatever coastline you like; the route just needs a real length.
  • Each day-pin is a <button class="pin"> positioned with two custom properties in its style:

Code snippet omitted: it ships with the download.

--x and --y are percentages of the map box. To place a pin on the route, take a point (x, y) on your path and set --x: x/820 * 100%, --y: y/620 * 100%.

  • Each day is one <li> in .days holding a .day-tab button and a .day article. They are tied together by number: data-pin, data-day-tab and data-day-panel sharing the same value, plus matching id/aria-controls. Add or remove a whole day by adding/removing its pin and its <li> with a new matching number — the script pairs them by number, not by position, so nothing shifts out of step.

Selecting a day (click a pin, click a rail button, or arrow-key between rail buttons) lights the pin, marks the button and fades in that day's card. The route line draws once when the section scrolls into view.

Palette

The whole system is four painted colours plus two supporting inks. Change these in :root and the site reskins; every translucent value resolves from a --*-rgb triple, so no rgba() literal is left mixed from the old hue.

Code snippet omitted: it ships with the download.

Measured contrast (as used, not as declared)

Pair Ratio Verdict
Cream on teal ground 4.49:1 AA for text, at the floor — see note
Ink #0C2523 on sand card 12.7:1 AAA
Ink-soft #3A5F5A on sand 5.58:1 AA, secondary text
Ink on a coral fill (buttons, pin numerals) 4.9:1 AA
Ink focus ring on teal 3.13:1 Passes 3:1 for non-text UI
Sand surface vs teal ground 4.06:1 Passes 3:1 for a UI boundary

Two rules hold this palette together, and a reskin must keep them:

  1. Cream on teal is at the AA floor (4.49:1), so it is never dimmed. Hierarchy on the teal ground comes from size and weight, not opacity: a muted cream drops below the floor. Sustained reading lives on the sand cards, where ink is 12.7:1. Darkening the teal or lightening the cream buys headroom if you want a dim variant on the ground.
  2. Coral is never text. It measures 1.57:1 on teal, 2.59:1 on sand and 2.87:1 on cream — all failing. It is used only as fills, the route line, the day-pins, rules and marks. The route line is decorative: the full itinerary is carried by the numbered day list and the pins' screen-reader labels, so nothing depends on seeing the coral line.

Images

The five photographs in assets/img/ are bundled, optimised WebP derivatives, not stock files passed through. Each has the template's art direction baked into the pixels: saturation pulled to 0.9, a +4° hue rotation that warms the greens towards olive, a slight gamma lift to open the shadows, and a per-image brightness so a bright vineyard and a warm evening dinner read as one sunny campaign against the teal ground. Total weight is about 800KB across five images, largest (the hero) 314KB.

  • Hero (hero-walkers.webp) — walkers on the coast path, framed beside the headline. The headline itself stays on the solid teal ground, so its cream keeps 4.49:1; only the small caption sits over the photo, held above 4.5:1 by a bottom scrim.
  • Trip posters (trip-alentejo, trip-douro, trip-azores) — one real photo per tile, under a teal-deep scrim tuned against the baked pixels so the cream tag (top) and name/price (bottom) clear 4.5:1 even over a bright sky, with a clear window in the middle where the subject reads.
  • Testimonial (voice-dinner.webp) — sits above the quote, never behind it, so the quote keeps its 12.7:1 on the sand card.

Every image has real alt, intrinsic width/height (no layout shift), loading="lazy" (the hero is fetchpriority="high" instead), and a background-color fallback on its container for the load/decode gap. With images off, every section is still complete: all copy is live text, nothing is baked into a picture.

Regenerating

assets/img-manifest.json lists every image: source URL, output name, width, WebP quality and grade. To re-bake after editing it:

Code snippet omitted: it ships with the download.

The script downloads each source, bakes the grade into the pixels, and writes assets/img/*.webp. Shipped files are altered, art-directed derivatives, never redistributed originals.

Swapping in your own photographs

  1. Drop your files in assets/img/ and repoint the <img src> in index.html, or
  2. Edit the src values in img-manifest.json (a remote URL or a local path), tune each image's brightness so they look equally bright rather than being nominally equal, and re-run the command above. This is what keeps a mixed set looking like one campaign.

Then update the alt text in index.html: it is written for the photographs that ship. If you change how bright a trip photo is, re-check that the cream tag and price still clear 4.5:1 over it (the scrim is on .trip::after).

Credits

Original photographs from Unsplash, used under the Unsplash licence and shipped here as altered, art-directed derivatives:

(The three day photos are credited by source URL; look each up on unsplash.com for the photographer, or replace them with your own trip photos before launch.)

Accessibility

  • Keyboard: day-pins and rail buttons are real <button>s. The rail is a roving-tabindex group: Tab reaches the active day, then arrow keys, Home and End move between days and shift focus. Every pin carries a visually-hidden label naming its day and village.
  • Without JavaScript: the seven days render as a complete ordered list (title, activities, where you sleep), and the map is a decorative aside. The interactive card, the rail buttons and the pin behaviour only appear once JavaScript adds the has-js class, so no content is ever hidden behind a control that cannot run.
  • Reduced motion: via both the CSS media query and a matchMedia branch, the page is fully static — the route is painted in full, day one is the open card, the headline is settled, and nothing scrubs.
  • Touch: pins are 2.1rem tap targets and the whole interaction is tap/click driven; there is no hover-only behaviour.

Customising further

  • Add a trip tile: copy a .trip block, point its .trip-img at another photo (add it to img-manifest.json and re-bake, see Images) and edit the label. Cards reveal on scroll automatically.
  • Change the hero image: it is .hero-img inside .hero-motif; swap the source in the manifest and re-bake. The .hero-motif box keeps a teal-deep fill as the load fallback.
  • Lenis: smooth scroll is optional. Delete the lenis block in script.js and its CDN tag to drop it.

Dependencies

  • GSAP 3.15.0 + ScrollTrigger
  • Lenis 1.3.17 (optional smooth scroll)
  • Google Fonts: DM Serif Display (headings) and Sen (body/UI)

No DrawSVG plugin: the route line uses the stroke-dasharray / stroke-dashoffset technique.

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

Your cart

Your cart is empty

The Vault £99

Everything in the catalogue, plus everything we release next.