015
AI ready Refreshed

Beauty Salon Template

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

Includes the original v1 design as a separate download.

Five-page website template for any business whose product is a colour or a finish: nail studios and salons, hair colour, paint, tile and textiles. A photographed hand is painted coat by coat in the shade you pick, and the shade fills half the page, the whole shades stage and every booking band, then rides into the booking form. Shown as a two-chair Brighton nail studio.

ScrollTrigger Lenis advanced
8 more details
svg-filtersclip-pathtimeline-controlstaggerscroll-revealview-transitionsprogressive-enhancementkeyboard-navigation

Updated

About this template

A five-page site for a studio whose product is a colour, built on a strict idea: the page has no colour of its own. Cream paper, near-black ink and full-ink hairline rules carry the structure, the photographs are black and white, and every coloured surface is the shade the visitor has chosen, at full size. Half the home hero, the whole Shades stage, every booking band and the Book button in the nav all take that shade. The worked example is Fennick, a two-chair nail and hand studio above a frame shop on Sydney Street in Brighton, written in a dry, exact voice.

Read the full template overview

The home page is a split: a photographed hand on one side, the chosen shade as the entire other half, and the full library of fifteen shades as a rail of colour bars along the bottom edge. Pick a bar and the nails are painted coat by coat with a polish sweep while the new colour pours through the field from the bar you pressed. The Shades page lays the hand directly on the colour, beside a library of large swatches, three finishes and a coat-by-coat strip; Treatments is a priced menu that totals your appointment; Studio lets each technician's pick retint the site; Book arrives with the shade, finish and treatment already filled in.

Making it yours is mostly one file: the shade table in assets/shades.js holds every colour on the site, with its name, note, coat count, finishes and the ink that reads on it. Swap the hand photograph for a wall, a sofa or a head of hair, re-run the bake script, and the same structure sells paint, upholstery or hair colour.

Beauty Salon Template - website template preview

What's included

15 items
  • Five plain HTML pages: Home, Shades, Treatments and prices, Studio and Book, sharing one stylesheet, one script and one shade table
  • Live try-on on a photographed hand: picking a shade paints each nail cuticle to tip, in as many coats as that shade needs
  • The page takes the product colour: the chosen shade fills half the home hero, the whole Shades stage and every booking band, poured in from the control that chose it
  • Fifteen shades as a rail of colour bars on the home page and large swatches on the Shades page, all native radio buttons
  • Crème, glitter and chrome finishes; each shade declares which it comes in, and an unavailable finish disables itself with a note
  • Every page closes on a compact shade rail above the footer, so the colour can be changed from anywhere, and the nav's Book cell shows the current shade as a swatch
  • Coat-by-coat strip shows the same nail after each coat of the current shade, starting from a bare nail
  • The choice follows the visitor: shade, finish and treatment carry to every page and into the booking form through the link and the visit's session, set before first paint so no page flashes the default colour
  • Treatment menu that totals minutes and price as you pick a treatment, add-ons and finish
  • Choosing a shade is optional: the booking form opens on "I'll pick on the day" with bare nails and a neutral field unless a shade was carried in
  • Technician picks on the Studio page that retint the whole site in one press
  • Booking request form with validation and an in-place confirmation, plus a real street map of the studio
  • Plain page loads with a short cross-document view transition where the browser supports it
  • Black-and-white bundled photography and two hand photographs prepared for the try-on, under 1MB of images
  • Accessible: native radios and selects throughout, a polite live region for each new shade, full no-JS and reduced-motion pages

Perfect for

5 use cases
  • Nail studios, nail bars and beauty salons
  • Hair colour salons and colour brands with a shade library
  • Paint, tile, upholstery and textile showrooms that sell by colour and finish
  • Cosmetics and lipstick brands launching a range of shades
  • Small appointment-based studios that want a booking request rather than a booking platform

How it works

4 sections

One shade table, five plain pages

Every colour on the site lives in assets/shades.js: id, code, name, hex, the ink that reads on it, coat count, room, finishes and a note. That file runs in the head of every page before the stylesheet, reads the chosen shade from the link or the visit's session and sets it as CSS variables, so each page paints in the visitor's colour from its first frame. The HTML radios carry only each shade's id and printed name.

Painting the photograph, not covering it

Each nail in the hand photograph has a small baked map of its own light and shade and a separate outline mask. The shade is laid down flat and the photograph's gloss, curvature and free edge are added back on top, so a cream stays cream in the shadow and a navy stays dark in the highlight. A bake script finds the nails by their red polish and writes the maps and overlay markup, so a new hand photograph is a re-run rather than hand tracing.

The pour

When the shade changes, each coloured field on screen holds its old colour while a layer of the new one opens over it from the bar, swatch or button you pressed. The page's colour variables switch halfway, so the text flips to its new ink as the colour arrives. Under reduced motion the colour and the nails change instantly.

Carried into the booking

Every Book link is rewritten with the current shade, finish, treatment and add-ons as a query string, and the same choices are kept in session storage for pages reached without one. The treatment menu adds the finish's time and price to its total, and the booking form opens with all of it selected. The form is a front end only and sends nothing.

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 (5 pages, lowest score shown), 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

Which businesses does this design suit besides nail salons?

Anything sold by colour and finish. A hair colour salon swaps the hand for a head of hair; a paint or tile shop swaps it for a wall or a floor; an upholsterer for a sofa. The shade table, the colour fields, the finish control and the booking flow stay as they are. Beauty salons and nail bars can use it almost unchanged.

Can I use my own hand photograph for the try-on?

Yes. Shoot a hand with mid-dark red polish on plain paper, put it in assets/img-src, and run the bake script described in the README: it finds the nails by their red, writes a light map and an outline per nail, rewrites the overlay markup, and can lift the hand off its paper so the page colour shows behind it. Red against skin is what makes the detection reliable.

How do I change the shades, names or prices?

Shades live in one table in assets/shades.js: hex, the ink that reads on it, coat count, finishes and a short note. Change a value there and every field, swatch and readout follows. The radios in the pages carry each shade's id and printed name, so a new shade also needs one line in each picker. Treatment prices and times are plain data attributes on the menu rows.

Does the booking form take real appointments?

No. It is an unwired front end: it collects treatment, add-ons, shade, finish, preferred day and time, name, email, phone and notes, validates them and shows a confirmation in place. Point the form at Formspree, Netlify Forms, your salon software's enquiry endpoint or your CRM to receive requests. It does not hold slots or take deposits.

What happens if a shade does not come in glitter or chrome?

Each shade lists the finishes it is mixed in. Finishes it does not offer are disabled on every picker, and if the visitor had one selected the choice falls back to crème with a written note. The treatment total and the booking form follow the finish, so nobody books a chrome shade you cannot do.

Can I remove a page or change the colour-led look?

Each page is a standalone HTML file, and the script only wires what it finds, so deleting the Studio page means deleting the file and its nav link. The cream, ink and rule colours are three tokens at the top of the stylesheet. The shade fields are the design's point; you can shrink them, but the site is built to let the product colour lead.

Paid template

Purchase to unlock the code.

Buying Beauty Salon 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.

£29 Standard license, unlimited projects

Browse free effects

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

Documentation

Quick Start

  1. Unzip and open index.html in a browser, or serve the folder with any static server (npx serve .).
  2. The pages are plain HTML files: index.html (home), shades.html, treatments.html, studio.html and book.html.
  3. Every page shares assets/style.css, assets/shades.js and assets/script.js. There is no build step.
  4. Deploy the folder as it is to any static host.

Using It With Your Own Design

  • Shades: every colour on the site is in assets/shades.js (see below). Change a shade there and the fields, swatches, try-on, readouts and booking form follow.
  • Structure colours: --paper, --panel and --ink at the top of assets/style.css. Nothing else in the stylesheet holds a colour; the shade fields read --shade and --on-shade, which shades.js sets.
  • Type: Gloock (headings and shade names), Reddit Sans (body) and Reddit Mono (codes, prices and buttons) self-hosted in assets/fonts/. Change the @font-face rules at the top of assets/style.css, the font preloads in each page's head, and --font-display, --font-body and --font-mono.
  • Photographs: supporting photographs are baked to black and white so the shade is the only colour on the page. Keep yours that way, or the shade stops leading.
  • Another product: the hand is the only nail-specific part. Swap it for a photograph of a wall, a sofa or a head of hair with the bake script below, and the same pages sell paint, upholstery or hair colour.

Pages and Configuration

Page Sections Hands-on piece
Home Split hero (hand and shade field) with the shade rail, three house rules, this week's prices, studio photograph, client quote, booking band Shade rail painting the hand and pouring the field
Shades Stage: the hand lying on the shade, the fifteen-shade library, finish and readout; coat by coat; finishes; booking band Library, finishes, coat strip
Treatments Split header, the menu with a running appointment total, aftercare, booking band Treatment, add-ons and finish totalled live
Studio Split header, the two chairs, pick band, standards, photograph Each technician's pick retints the site
Book Booking request form beside the painted hand, map, policies Shade (or "on the day") and finish re-pickable in the form

Every feature looks for its own markup and does nothing when it is missing, so you can delete a section, or a page and its nav links, without editing the script.

The shade table (assets/shades.js)

SHADES is a list of { id, code, name, hex, ink, coats, room, finishes, note }:

  • ink is dark or light, the text colour that reads on the shade. Measure it (4.5:1 for body text) whenever you change a hex. The default fifteen all pass; the closest are FN-01 West Pier with dark ink (4.63:1) and FN-07 Groyne with light ink (4.70:1).
  • coats (1 to 3) sets how sheer the first pass of the try-on is, the coat-by-coat strip and the readout.
  • finishes lists which of creme, glitter and chrome the shade comes in.
  • room groups the shades on the Shades page.

DEFAULT is the shade a first visit opens on. The file runs in each page's <head> before the stylesheet, deliberately: it reads ?shade= and ?finish= from the link, then this visit's sessionStorage, and sets the colour before the page paints.

The pickers in the HTML (input[name="shade"] inside .rail-bar, .tile and .mini labels) carry only the shade's id and printed name, and their swatch colour comes from data-swatch="<id>". Adding a shade means one entry in shades.js and one label in each picker.

Shade rail (every page)

Each page ends with <section class="shade-foot" data-shade-foot> above the footer: the whole library as a band of colour bars (radios named shade-rail, so they never clash with a page's own picker). Picking a bar pours the shade through the page and carries it to every other page, like the rail at the top of the home page. Delete the section from any page and nothing else changes. On Book it starts with "On the day".

"On the day" (Book)

book.html has data-shade-optional on <html>. With no shade carried in (no ?shade= link and nothing chosen this visit) it opens on "I'll pick on the day": a neutral warm-grey field (NONE in shades.js, ink on it 12.8:1), bare nails on the hand, and "Shade: on the day" in the legend and on the submit button. A shade chosen elsewhere is prefilled, and "on the day" stays first in the shade group and the rail. Book links only carry a shade the visitor actually chose.

Nav chip

The Book cell in the nav shows the current shade as a small swatch beside its code, or "On the day" with no swatch. It is an ink cell with paper text, so its contrast does not depend on the shade.

Colour fields

Any element with class="field" data-field is filled with the chosen shade and its text uses the shade's ink. When the shade changes, the script pours the new colour through every field on screen from the control that chose it. Make any section a field by adding those two attributes.

The try-on

Each hand is an <img class="tryon-photo"> and an <svg class="stage-paint"> overlay inside a [data-tryon] box. The overlay is generated: do not edit it by hand.

  • hand-portrait.webp (home hero) and hand-portrait-cut.webp (book) share one set of nail maps (nail-p-*.webp); hand-landscape-cut.webp (Shades) uses nail-l-*.webp. The -cut files are the hand lifted off its paper, with its contact shadow kept, so the shade shows behind it.
  • The overlay's viewBox is the photograph's own size and both crop the same way (object-fit: cover and preserveAspectRatio slice, with matching alignment), so the paint stays in register at every width. If you change a hand's object-position, change its align in the bake config to match.

To use your own hand: photograph it with mid-dark red polish (red against skin is what the detection relies on) on plain grey paper, put the file in assets/img-src/, add it to assets/img-manifest.json, then from the GSAP Vault repo:

Code snippet omitted: it ships with the download.

The second command finds the nails, writes a light map and an outline mask for each, optionally cuts the hand out (cutout), and rewrites every stage-paint and coat-crop SVG in the pages listed for that hand. Its settings (detection thresholds, edge widths, alignment, which nail the coat strip shows) are in nail-maps.json, with each one explained at the top of the script.

Treatment menu (Treatments)

Each row is a radio (name="treatment") or checkbox (name="addon") with data-mins, data-price and data-label. The summary adds the chosen finish's time and price (FINISH_COST in the script) and passes the treatment and add-ons to every Book link. Keep the option values in the Book page's select and add-on checkboxes the same.

Technician picks (Studio)

<button data-pick="fn-09" data-pick-finish="chrome"> sets that shade and finish across the site.

Booking form (Book)

A front end only: it validates and shows a confirmation in place without sending anything. It collects treatment, add-ons, shade, finish, preferred day and time, name, email, phone and notes. Set the form's action to Formspree, Netlify Forms or your salon software's enquiry endpoint, and remove the submit handler in the script, to receive requests.

Map

MapLibre GL on OpenFreeMap's Positron style: OpenStreetMap data, no API key or account. Set the pin with data-lng and data-lat on [data-map]. Wheel and one-finger drag scroll the page; the map pans with Ctrl/Cmd and wheel, or two fingers. Keep the OpenStreetMap attribution. Without JavaScript or WebGL the map is a link to OpenStreetMap.

Palette

Token Value Use
--paper #F4F0E8 Page ground; ink on it 17.0:1
--panel #EBE6DC Form fields and hover
--ink #16130F Text, rules, solid buttons
--ink-dim ink at 0.74 Secondary text, 7.4:1 on paper
--shade from shades.js Colour fields, swatches, the nav's Book cell
--on-shade from shades.js Text and rules on a field

Accessibility and Fallbacks

  • Without JavaScript, or with the GSAP CDN blocked, every page is complete: the default shade fills the fields, the hand shows the photograph as shot, the pickers are ordinary radios, and the forms are ordinary forms.
  • Reduced motion keeps every control but changes instantly: no sweep, no pour, no reveals and no view-transition morph.
  • Shade, finish and treatment pickers are native radios, so arrow keys, grouping and checked state come from the browser; each new shade is announced in a polite live region. Unavailable finishes are disabled, not hidden.
  • Focus rings show for keyboard use only (:focus-visible).

Dependencies

  • GSAP 3.15.0 with ScrollTrigger (works with 3.12+), from jsDelivr.
  • Lenis 1.3.17 for optional smooth scrolling (add ?smooth=off to a URL, or data-smooth="off" on <html>, to turn it off).
  • MapLibre GL 4.7.1 from unpkg on the Book page only, loaded by assets/script.js when the map nears the viewport (the URLs are MAPLIBRE_JS and MAPLIBRE_CSS at the top of the script); tiles from OpenFreeMap.
  • Fonts: Gloock, Reddit Sans and Reddit Mono, self-hosted (see Images and Credits).

Images and Credits

Bundled photographs are WebP derivatives in assets/img/, cropped, resized and (except the hands) baked to black and white, listed in assets/img-manifest.json. Rebuild them with bun scripts/build-template-assets.ts nail-studio-template --force (in the GSAP Vault repo), or replace a file with your own at the same name and size.

  • Studio, technician, swatch and bottle photographs are from Pexels under the Pexels licence; every source URL is in assets/img-manifest.json (page https://www.pexels.com/photo/<id>/). They show a real nail studio, not Brighton, and the people in them are not the fictional technicians they are captioned as.
  • The two hand photographs (assets/img-src/gen/) are AI-generated images made for this template. They depict no real person.
  • Fonts in assets/fonts/ are the latin files of Gloock (Duarte Pires), Reddit Sans and Reddit Mono (Reddit, Inc.), as served by Google Fonts, unmodified. All three are under the SIL Open Font License 1.1; the licence text for each is in assets/fonts/OFL.txt.

Fennick, its people, address, phone number, prices and reviews are fictional. Sydney Street and the map position are real.

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