Wedding Template

£10

A wedding one-pager with one job, getting guests to RSVP, built as a stationery suite on champagne and card stock, with a reply card that writes itself in typewriter text and posts itself in an envelope on submit.

ScrollTrigger Lenis intermediate
7 more details
scroll-revealstaggertext-animationtypewriter3d-transformsscrub 4 colour palettes
Wedding Template - website template preview

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

About this template

A complete one-page wedding site whose every section funnels guests toward one act: the reply. No script lettering, no wall of stock photography: the page is a stationery suite, a champagne envelope lining as the ground, near-white card stock for the invitation plate and the reply card, espresso ink and one antique gold in wax-seal territory. Photography is held to a single black-and-white print of the couple, laid over the corner of the invitation plate with a pencil-note caption, ready to be swapped for your own. It looks designed and full on first open, and three more complete palettes (powder blue, blush, sage) ship in the stylesheet as a one-attribute swap; the print's baked monochrome grade sits with all of them.

Read the full template overview

The signature is the reply card that writes itself. The RSVP form sits beside a styled reply card, and as a guest answers each question (names, accepting or declining, a choice of three mains, dietary notes, a song request) the card fills in live, line by line, in typewriter text. On submit the card folds into an envelope, takes a stamp and a postmark, and posts off the page, followed by a plain confirmation.

Everything else is deliberately quiet: a letter-spaced reveal on the names, a timeline of the day whose spine draws as it is read, travel notes, three suggested hotels as place cards, a short Q&A and a modest gifts note. Swap the names, date, venue and menu, point the form at Formspree or any endpoint, and deploy it as static files.

What's included

12 items
  • Complete deployable one-pager: invitation-plate hero, timeline of the day, travel and stay, Q&A and gifts, RSVP, footer
  • Signature reply card that mirrors the form live, typing each changed answer in character by character, never retyping the whole card
  • On submit the card folds into an envelope, takes a stamp and a postmark, and posts off the page before a plain confirmation
  • The form is a real, working plain form: point its action at Formspree, Netlify Forms or any endpoint and it submits with or without JavaScript
  • Formal centered invitation plate with double-rule frame, letter-spaced engraved caps, a reply-by chip and a button straight to the RSVP
  • Timeline of the day with a spine that draws down the page as it is read, times set in typewriter mono
  • One photograph by design: a black-and-white print of the couple, mounted and captioned, its baked monochrome grade at home in every palette; the rest is art-directed CSS and SVG stationery (card, envelope, stamp, postmark, botanical rule, line-art barn)
  • Declining folds the supper, dietary and song questions away and disables them, so a decline never posts a main course; accepting brings them back, answers intact
  • Reply card stays in view while the form is filled, sticky beside it on desktop and compact above it on phones
  • Four ready palettes (champagne gold, powder blue, blush, sage) swapped with one attribute, every pair measured to WCAG AA; the RGB-triple token block makes a custom reskin a four-value edit
  • Lenis smooth scrolling wired in and fully optional
  • Accessible: the decorative card is aria-hidden, the confirmation lands in an aria-live region and takes focus, validation is native, and reduced motion gets instant card updates with a static confirmation swap

Perfect for

5 use cases
  • Wedding websites whose main job is collecting RSVPs
  • Civil partnerships, vow renewals and anniversary parties
  • Any invitation-and-reply event: christenings, milestone birthdays, retirement parties
  • Save-the-date pages that will grow into the full invitation
  • Learning how to mirror a form into a live, animated preview with GSAP

How it works

5 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 querySelector is guarded, so any section (the timeline, the hotels, the whole RSVP) can be deleted and the rest keeps working. Reveal start states are double-gated behind a has-js class and the motion media query, so a blocked CDN or a reduced-motion preference both leave a complete static page.

The reply card

The form is the real interface and the card is an aria-hidden mirror. Each input names the card line it feeds through a data attribute; radios update on change and text inputs wait 350ms for a pause. Only the changed line is retyped: a small tween counts an index up the new string's length and slices it into the line's textContent, with a blinking caret while it runs, so the card reads as being typed rather than re-rendered. Declining folds the accept-only questions (supper, dietary, song) away in a height tween and disables their inputs, so a decline never posts a main course; accepting unfolds them with their answers intact.

Posting the envelope

Submit builds one timeline: the card scales down, the envelope rises to meet it, the card slips inside, the flap sweeps closed, the stamp thumps on with a little jolt of the envelope, the postmark cancels it, and it posts off the page. The envelope's CSS centring is restated in the animation itself, so no two transform properties fight each other. If the form's action points at a real endpoint, the reply is POSTed first and the send only plays once it has actually sent; a failure re-enables the button and shows a written error instead.

Accessibility and reduced motion

The fold never hides the outcome: the form column is made inert during the animation, the confirmation lands in an aria-live region and receives focus, and validation is the browser's own. Under reduced motion the card updates instantly with no type-on, and submitting swaps straight to the confirmation: no fold, no envelope.

Without JavaScript

The page renders complete: every section readable, the card sitting as static printed stationery with empty ruled lines, and the form a plain working form that submits to whatever its action attribute points at. The envelope never appears at all. The README documents wiring the form to Formspree, Netlify Forms or a mailto fallback, and where to change the names, date, venue and menu.

Plugins ScrollTrigger
Difficulty Intermediate
Smooth scroll Lenis integration
Colour palettes 4 ready-made palettes, each measured for AA contrast. Switch with one attribute, or copy the values you want into :root. Try them in the preview above.
Includes HTML + JS + CSS source, documentation, AI setup prompt, lifetime updates

Questions about this template

Will the RSVP form actually collect replies?

It is a real, working plain form, which is unusual here. Point its action at Formspree, Netlify Forms or any endpoint and it submits with or without JavaScript. The envelope animation is a layer on top, not a replacement for the submit, so replies do not depend on the animation running.

What happens if a guest declines?

The supper, dietary and song questions fold away and are disabled, so a decline can never post a main course choice. Accepting brings them back with the answers intact. That is a data-quality decision as much as a design one: it saves you reconciling nonsense replies later.

We do not have professional photos yet. Is that a problem?

No. The template uses exactly one photograph by design, a black-and-white print of the couple, mounted and captioned. Everything else is art-directed CSS and SVG stationery. The monochrome grade means almost any decent photo sits comfortably in any of the palettes.

Can we match our stationery colours?

Four palettes ship (champagne gold, powder blue, blush, sage), swapped with a single attribute and each measured to WCAG AA. For something custom, the token block is RGB triples, so a bespoke reskin is a four-value edit rather than a hunt through the stylesheet.

Can we use it as a save-the-date first and add detail later?

Yes. Sections are independent, so you can ship the invitation plate, a date and the RSVP, then add the timeline, travel, Q&A and gifts as they are decided. That is a common path and nothing about the layout assumes all sections are present.

Paid template

Purchase to unlock the code.

Buying Wedding 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

What's Included

  • index.html — the whole site: nav, invitation-plate hero, the photograph, The Day (timeline), Travel & Stay, Questions & gifts, RSVP, footer
  • assets/style.css — all styles, responsive, print of the palette rationale at the top
  • assets/script.js — all behaviour, documented
  • assets/script.min.js — the same, minified for production
  • assets/img/couple.webp — the photo print, an optimised black-and-white placeholder you replace with your own photo

No build step. Deploy the folder as static files anywhere.

Quick Start

  1. Open index.html and change the obvious things: the names (hero, nav monogram, footer, the reply card's M & E headers, the envelope address), the date, the venue, and the reply-by date. Search for Martha, Elliot, Foxhill, 12 September and 31 July — those five searches find every instance.
  2. Replace assets/img/couple.webp with a photo of you two, and rewrite the print's caption in index.html — see The photograph below.
  3. Rewrite the copy in your own voice: the timeline of your day, your travel notes and hotels, your Q&A. Delete whole sections freely — the script skips anything it can't find.
  4. Point the form somewhere real — see Wiring the form below. Until you do, submitting plays the animation but records nothing.
  5. Swap script.js for script.min.js before you go live:

Code snippet omitted: it ships with the download.

The signature: the reply card

The form is the real, accessible interface. The card beside it is decoration (aria-hidden) that mirrors the form live:

  • Each form control carries data-card-input="key", and the card has a matching [data-card-field="key"] line. Text inputs update after a 350ms pause in typing; radios update on change. Only the changed line is retyped, character by character, with a blinking caret while it runs.
  • The accept/decline radios carry data-card-key="accepts" / data-card-key="declines" instead, and put a typed X in the matching box on the card.
  • Menu radios can carry data-card-text for what the card should type (e.g. the value posted to your endpoint is Baked river trout, while the card types baked river trout).
  • Declining folds the rest away. The supper, dietary and song questions live in a [data-attend-extras] wrapper; picking "regretfully declines" folds the wrapper closed, disables its inputs (so a decline never posts a main course) and wipes their card lines. Picking "joyfully accepts" brings it all back, answers intact. Any field you add inside the wrapper gets this behaviour for free; without JavaScript the wrapper simply stays visible, and nothing in it is required.

Adding a field: add the input with data-card-input="mykey", add a card line containing <span data-card-field="mykey"></span>, done. Removing a field: delete both halves; nothing else references them.

Changing the menu

The three mains live in the Supper — choose your main fieldset. Change the value (what gets submitted), the visible <span> (what guests read), and data-card-text (what the card types). Add or remove choices freely — the card only ever shows the one that is picked.

Posting the envelope

On submit, one GSAP timeline scrolls the section into view, shrinks the card, raises the envelope to meet it, drops the card inside, closes the flap, thumps the stamp on, rolls the postmark over it, and posts the envelope off-page. Then a plain confirmation appears where the card was. The confirmation copy lives on the form as data-done-message, and the failure copy as data-error-message — edit both in the HTML, not in the script.

The envelope's address block, the stamp monogram and the postmark text are all in index.html inside [data-envelope] — change them along with the names. The postmark's date is yours to set too (guests will see it for under a second, but it's the details that get screenshotted).

Wiring the form

The form is a plain <form method="post">, so it works with any form backend, with or without JavaScript.

Formspree — create a form at formspree.io, then:

Code snippet omitted: it ships with the download.

That's the whole job. With JavaScript on, the script sees a real action, POSTs the reply with fetch first, and only plays the envelope once the submission has actually succeeded; a failure shows the written error and re-enables the button instead. With JavaScript off, the form submits normally to Formspree's hosted thank-you page.

Netlify Forms — if you deploy on Netlify, add the attributes and a form name, and keep action="#"... but note that Netlify intercepts the native POST, so with JavaScript on you should give the form its page path as action (e.g. action="/") so the fetch posts somewhere Netlify records:

Code snippet omitted: it ships with the download.

Mailto (last resort)action="mailto:you@example.com" method="post" enctype="text/plain" opens the guest's mail client with the answers in the body. It's clunky and depends on a configured mail app; use a form service if you can. With a mailto: action the script skips the fetch and just plays the send after the mail window opens.

No backend yet — leave action="#". Submitting plays the animation and shows the confirmation, but nothing is recorded; don't send the link to guests like this.

Sections

Every section is independent: delete any of them (or the nav, or the footer) and the rest keeps working.

  • Hero — the invitation plate. Names, date, venue, reply-by chip, button to #rsvp, and the photo print riding the plate's top corner (in the flow at the plate's foot on phones). The plate's double rule is two borders in .plate / .plate::before; the print is a <figure> inside the plate — swap the image and caption (see The photograph below), or delete the figure to keep the plate all type.
  • The Day (#day) — the timeline. Each <li class="tl-row"> is a time (typewriter mono), a dot and a body; add or remove rows freely. The spine draws down as it is read (scrubbed ScrollTrigger).
  • Travel & Stay (#travel) — getting there and the hotel place cards. The barn line-art is inline SVG; replace or delete it.
  • Questions (#questions) — a <dl> of Q&A pairs plus the gifts note.
  • RSVP (#rsvp) — the form and the card. On desktop the card sits sticky beside the form; on phones it rides compact under the nav while the form is filled, so every answer is seen landing on it.

The photograph

The one photo on the page is a placeholder for your own. assets/img/couple.webp is a bundled, optimised black-and-white WebP derivative of an Unsplash photo (free to use commercially), not the original: the grade is baked into the pixels so the print sits with every palette, including any you mix yourself.

To use your own photo: export it around 1000×1250 (a 4:5 portrait), ideally black and white to keep the print palette-proof, save it over assets/img/couple.webp (any WebP/JPEG exporter works — keep the filename, or update the <img> src), then rewrite the caption and the alt text in index.html. The print's white mount, tilt, shadow and corner position are CSS on .photo-print (with its phone placement in the 760px media block); a different aspect ratio just needs the width/height attributes on the <img> updated to match.

Original photo: Vadim Paripa on Unsplash. From a GSAP Vault checkout the derivative regenerates with bun scripts/build-template-assets.ts wedding-template --force.

Palettes

Four ready palettes ship in assets/style.css. The default is champagne — a champagne lining, near-white card stock, espresso ink and one antique gold. Three alternates live in the ALTERNATE PALETTES block at the end of the file:

  • powder — powder-blue lining, midnight ink, a wax-seal bordeaux
  • blush — dusty-rose lining, warm near-black ink, the same bordeaux
  • sage — eucalyptus lining, forest ink, a deep botanical green

To use one, set the attribute on the <html> tag:

Code snippet omitted: it ships with the download.

Or, once you've settled, copy that block's values into :root and delete the alternates block entirely — the tidier end state. Every pair of colours in all four palettes is measured to WCAG AA composited as used; each block notes its worst pair.

To mix your own instead: the four colours are declared once at the top of assets/style.css with matching RGB triples. Every translucent value on the page derives from the triples, so a reskin is editing four hexes and four triples — there are no stray rgba() literals to hunt.

Code snippet omitted: it ships with the download.

Three derived values to keep in step: --ground-deep (the alternate section ground, a slightly deeper lining), --accent-deep (button hover) and --card-shade (the envelope flap). The header comment above :root records every measured contrast pair; if you change a colour, re-measure the pairs listed there — especially the dimmed ink (--dim) on --ground-deep, the accent on --ground-deep, and the placeholder colour. The accent fails on ink in every shipped palette (~2:1), which is why the footer carries no accent; keep that rule if you keep a dark footer.

Smooth scrolling

Lenis is wired in and fully optional — delete its <script> tag and everything still works (the envelope scroll-into-view falls back to native smooth scrolling). The instance is exposed as window.lenis so your own code can drive the same scroll rather than fight it.

Accessibility

  • The reply card and envelope are aria-hidden decoration; the form is a standard labelled form with native validation (required on name and attendance).
  • The confirmation is an aria-live="polite" region and receives focus when it appears, so the fold never hides the outcome from a screen reader or strands the keyboard; the form column is made inert during the animation.
  • Reduced motion (both the CSS media query and the GSAP matchMedia branch): no reveals, no type-on — card lines update instantly — and submitting swaps straight to the confirmation with no envelope.
  • Without JavaScript the page renders complete and static, and the form submits natively to its action.
  • All type meets WCAG AA on every surface it appears on, measured composited; the table is in the stylesheet header.

Browser Support

Modern browsers (ES5 syntax, but clip-path, inset and :focus-visible assume evergreen). Not compatible with IE11.

Dependencies

  • GSAP 3.12+ (core)
  • ScrollTrigger plugin
  • Lenis (optional — smooth scrolling; the page works without it)

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

Every effect, template and UI element: 165 today, plus everything we release next.