# Holiday Let Template

> A complete one-page site for a single holiday cottage or cabin, built around a draggable date-range availability calendar that refuses to span nights already taken and prices every night on its own season.

Canonical: https://gsapvault.com/templates/holiday-let-template
Live demo: https://gsapvault.com/demos/holiday-let-template/index.html

| Property | Value |
|----------|-------|
| Type | template |
| Tier | paid |
| Price | £5 |
| Difficulty | advanced |
| Plugins | ScrollTrigger |
| Techniques | draggable, scroll-reveal, stagger, text-animation, parallax, scrub, click-toggle |
| Uses Lenis | Yes |

## Overview

A production-ready site for one owner-run holiday let, laid out as an almanac rather than a brochure. The availability calendar sits directly under the hero, because the only question a visitor actually has is whether their weekend is free, and everything about the property unfolds beneath the answer. The signature is that calendar: a real month grid you drag a date range across, where nights already booked are walls the drag will not cross, and where the nightly rate, the number of nights, the minimum-stay and changeover-day rules and a running total all update while you are still holding the mouse down. Rates are read per night from a season table, so a stay that crosses a month boundary is genuinely a sum rather than a multiplication. The whole thing is driven by two editable arrays at the top of the script. The art direction runs on a mid-tone moss ground with oat paper and one rust accent, set in Petrona and Roboto Mono, and the photography is bundled as art-directed WebP derivatives baked to a muted warm grade.

## Features

- Complete deployable one-page site: nav, hero, availability almanac, the property, a month-by-month year table, a full-bleed landscape band, practical details and footer
- Signature availability calendar: drag from the first night to the last and the range paints live, with prev and next month navigation across a rolling twelve months
- Booked nights are structurally impossible to span - the range walks out from your first night and stops at the wall, rather than being validated and rejected afterwards
- Per-night pricing from a season table, so a stay crossing a month boundary is charged correctly and the quote shows the range of rates it spans
- Live quote panel: arrival, departure, nights, rate band, nights total, cleaning fee and grand total, all updating during the drag
- Minimum-stay and changeover-day rules validated live, with a plain-English explanation and the enquiry button disabled until the dates are valid
- Full keyboard mirror of the drag: arrow keys move focus and repaint the same range, Enter sets the first and last night, Escape clears, and the clamp against a booked night is announced through a live region
- Touch support by design rather than by accident: tap the first night then the last, with vertical page scrolling left to the browser
- Availability and rates are two plainly commented arrays at the top of the script - no backend, no booking platform, no build step
- Degrades to a readable static month table with the taken nights marked when JavaScript is unavailable, and stays fully interactive under reduced motion
- Bundled cabin and landscape photography baked to a muted warm grade, around 675KB total
- Three-colour token block: change moss, oat and rust and the whole site reskins
- Lenis smooth scrolling wired in and fully optional

## Use Cases

- Single-property holiday lets, cabins, cottages and shepherd's huts
- Owner-run bed and breakfasts and guest annexes taking direct bookings
- Glamping pitches, lodges and treehouses that want to escape platform commission
- Studio, workshop, darkroom or rehearsal-room hire booked by the night or the day
- Any small business that needs to show what is free and what a stay would cost before a visitor gets in touch

## How It Works

One script initialises each section inside a single gsap.context with gsap.matchMedia, keyed only on reduced motion so exactly one branch runs on every device, and every section is guarded so a buyer can delete any of them. The calendar's booked ranges are expanded once into a Set of date keys, and every date in the module is a Date anchored at local noon, which puts twelve hours of slack either side of every clock change so adding a day across a DST boundary can never land back on the same date. The refusal to span a booked night is not a validation step: reachFrom walks out from the anchor one night at a time and stops the moment the next night is taken, in the past or off the end of the diary, so an illegal range is never allowed to form in the first place. Pointer and keyboard both drive the same three functions - beginAt, previewTo and commitTo - so a mouse drag, a tap and a tap, and arrow keys with Enter cannot drift apart in behaviour; the keyboard additionally narrates the running range through a polite live region, and calls out the blocking night only the first time it is reached. Cells are keyed entirely by data attributes rather than class names, because the demo build's class mangler can only rewrite a single plain class per quoted string and a calendar built from concatenated class names would ship dead. The markup already contains the first two months as a plain table, so the page is a readable calendar with JavaScript off, and the script re-renders that same container rather than creating it. Under reduced motion the calendar stays fully interactive and only the movement around it is dropped, because it is a control and not decoration.

## Integration Preview

How this effect integrates into a page. The full documentation (examples, events, programmatic API, customization guide) ships with the download.

### Quick Start

1. Copy the whole folder onto your host. It is plain HTML, CSS, JS and WebP — anything that serves static files will do.
2. Open `assets/script.js` and edit the block at the top marked **`YOUR DIARY`**. That is your availability and your rates. See below.
3. Replace the copy in `index.html` and the photos in `assets/img/`.
4. Change three colours in `assets/style.css` if you want a different palette.

There is nothing to install and nothing to compile.

---

### Accessibility

- Each month is a real `<table>` with a `<caption>` and `<th scope="col">` weekday headers, so it reads correctly as a calendar.
- Day cells are `<button>`s carrying a full `aria-label` — weekday, date, price, and whether the night is taken or part of your stay.
- Booked and past nights use `aria-disabled` rather than `disabled`, so arrowing across a month never skips a hole.
- Roving tabindex: one cell is in the tab order at a time, which is the expected pattern for a grid.
- A polite live region announces the running range, the reason a range was clamped, and any validation problem.
- With **JavaScript off**, the markup already contains two months as a plain table with the taken nights hatched and struck through, plus a note explaining that the price has to be worked out by email.
- Under **reduced motion**, the calendar stays fully interactive — it is a control, not decoration, and removing it would remove the only way to see a price. Only the movement around it is dropped. Every state, including the refusal, is carried by an attribute and therefore still visible with nothing animating.

---

### Dependencies

| | |
|---|---|
| GSAP 3.14.2 | Core + ScrollTrigger, from CDN |
| Lenis 1.3.17 | Smooth scroll, **optional** — delete the script tag and nothing else changes |

No framework, no bundler, no package manager.

## What You Get

- `index.html`: working demo page
- `assets/script.js`: commented, readable source
- `assets/style.css`: effect styles
- `README.md`: full documentation with examples and framework integration notes
- `LICENSE.txt`: standard license terms
- Lifetime updates: re-download anytime from your library

## Get the Code

This is a premium template. The standard license costs £5 one-time and covers unlimited personal and commercial projects with no attribution required. The only restrictions: no redistribution of the code itself and no competing effect libraries.

- [Buy Holiday Let Template](https://gsapvault.com/templates/holiday-let-template)
- [All-Access Bundle (£29 one-time, best value): every current and future effect and template](https://gsapvault.com/effects)

---

From [GSAP Vault](https://gsapvault.com): production-ready GSAP animation effects. Full catalog for agents: https://gsapvault.com/llms-full.txt
