012
AI ready Refreshed

Yoga Studio Template

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

Includes the original v1 design as a separate download.

Six-page yoga studio website template for hot yoga, pilates and breathwork studios, saunas, bathhouses and spas. A temperature dial swaps the rooms inside the hero photograph, today's classes sit on the home page, and the timetable lights up one class type across the whole week. Shown as a heated yoga studio with a wood-fired sauna in Margate.

ScrollTrigger Lenis advanced
12 more details
draggablesnapmask-revealscrubparallaxsvg-animationtimeline-controlstaggerscroll-revealcontainer-querieskeyboard-navigationprogressive-enhancement

Updated

About this template

A six-page site for any studio whose visitors come for the timetable: yoga, hot yoga, pilates, breathwork, saunas and bathhouses. It sits on a committed butter-yellow ground with big amber sauna photography, people cut out of their photographs standing on the page, die-cut stickers and studio quotes set on circles, so it reads as a brand rather than another beige wellness site.

Read the full template overview

The home page leads with a large photograph of the kiln and a temperature dial: drag the needle, tap a temperature or use the arrow keys, and the room in the hero frame changes from the heated studio to the sauna to the sea, with its spec sheet and sticker. Today's classes follow straight after as full-width rows with a day strip, the way the best studio sites put the schedule first.

The timetable page draws all seven days as rows on one time axis; point at any class and every other class of that type lights up across the week, or hold a type and filter by teacher. Classes, teachers and pricing each have their own hands-on piece: spec sheets with the next three times, a teacher line-up that shows each person's week, and a calculator that recommends drop-in, ten-pack or membership. Visit has a real street map with walking routes.

The whole week lives in one small data file, so a studio updates its schedule once and every page follows. The worked example is a fictional heated yoga studio and wood-fired sauna in an old pottery kiln yard in Margate.

Yoga Studio Template - website template preview

What's included

12 items
  • Six complete pages: home, timetable, classes, teachers, pricing and visit, on ordinary page loads with a cross-document fade where supported
  • Temperature dial hero: three rooms behind one photograph that opens towards full bleed as you scroll, chosen by dragging the needle, tapping a temperature or the arrow keys
  • Today's classes on the home page as full-width rows with a seven-day strip and a class filter, plus an Up next strip under the hero
  • Full-week timetable as day rows on a time axis, with open sauna hours as a second track and a live now line on today
  • Cross-week highlight: hover or focus any class to light up that type across all seven days, hold a type from the key and filter by teacher
  • One schedule file drives every page: today's rows, the week, each class's next three times and each teacher's week
  • Class pages as spec sheets with stickers, and the 4-7-8 breath guide that opens every Breath class
  • Teacher line-up of cut-out portraits that steps the chosen teacher forward and shows their classes
  • Pricing calculator that recommends drop-in, ten-pack or membership from how often a visitor comes
  • Real street map with three routed walking routes drawn on demand
  • Bundled photography and transparent cut-outs as optimised WebP with responsive sizes: a phone loads about 40 to 540KB of images per page
  • Every page reads without JavaScript, schedules and controls still work if the animation CDN is blocked, and reduced motion gets a complete static site

Perfect for

5 use cases
  • Yoga and hot yoga studios with a weekly timetable
  • Pilates, barre and breathwork studios
  • Saunas, bathhouses and cold-plunge clubs that run sessions on the hour
  • Spas and wellness clubs with more than one room or treatment
  • Small gyms and movement studios that sell drop-ins, packs and memberships

How it works

4 sections

Pages and the schedule file

Each page is a standalone HTML file sharing one stylesheet and one script, so a page or section can be deleted without breaking the rest. Classes, teachers, rooms and sauna hours live in assets/schedule.js; the home rows, the week, the next times on each class and every teacher's week are drawn from it, with a static fallback in the markup for visitors without JavaScript.

The temperature dial

The dial is three native radio buttons with a drag handle on top. Whichever way the room is chosen, the same change updates the photograph, the spec sheet beside it and the sticker. The incoming photograph opens from the dial's corner; under reduced motion it swaps instantly.

The week on one axis

Every day is a row on a shared time axis, and each class is placed by its start time with a bar for its length. Highlighting dims the other classes to a measured, still-readable ink rather than hiding them, and below about 1100px the same markup becomes stacked day lists.

Motion and fallbacks

Reveals, the sauna frame that widens as you scroll, the slowly turning rings of set type and the cut-out parallax all run through GSAP ScrollTrigger with optional Lenis smooth scrolling. Schedules, filters, the line-up and the calculator are plain DOM code, so they keep working if the animation CDN is blocked.

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 (6 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 kinds of studio does this template suit?

Any studio people visit for the timetable: a yoga studio, hot yoga, a pilates studio, barre or breathwork, and saunas, bathhouses and spas that run sessions. The five class types, three rooms and photographs are the worked example; rename them in the schedule file and swap the images, and the dial, week, spec sheets and calculator carry over unchanged.

How do I put my own timetable in?

Edit assets/schedule.js. Each class is one line with a day, start time, class type and teacher, and the types, teachers, rooms and open sauna hours sit above it. The home page rows, the week, each class's next three times and every teacher's week all redraw from that file, so you update the schedule once.

Can visitors book a class through the site?

No. Every Book link points at one bookingUrl in the schedule file, and any class can carry its own link instead. Point them at Momence, Mindbody, TeamUp or whatever platform you already use; the template displays the schedule and sends people to book there.

Does the contact form on the visit page send anything?

Not yet. It is a static front end that checks for a name, a valid email and a message, with a topic menu, then shows a confirmation. Connect it to Formspree, Netlify Forms or your own CRM endpoint by setting the form's action, or replace the small submit handler in the script.

How do I replace the cut-out people with my own teachers?

Photograph each person on a plain background, remove the background to a transparent PNG with any tool, and save it in assets/img-src under the existing name. Re-running the image build bakes transparent WebP files and the round timetable avatars from the same pictures; the manifest's crop boxes set where each avatar sits.

Can the dial show different rooms or treatments?

Yes. Each stop is a radio button with a value and an angle, a matching photograph in the hero frame and a matching spec row. Change the three temperatures to, say, a steam room, a treatment room and the pool, rewrite their rows and swap the images; keep the three angles or set your own.

How do I move the map to my studio?

Set the studio's longitude and latitude and the three starting points at the top of the map section of the script. The routes are real walking routes stored as coordinate lists; the README shows how to fetch new ones from the free OSRM router and update the minutes and distances on the stop buttons to match.

Paid template

Purchase to unlock the code.

Buying Yoga Studio 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. Edit assets/schedule.js with your classes, teachers and rooms. Every schedule on the site redraws from it.
  3. Replace the photographs in assets/img/ (see Images and Credits), the copy in each HTML file, and the colours at the top of assets/style.css.
  4. Point bookingUrl in assets/schedule.js at your booking platform.

There is no build step. Each page is a plain HTML file that loads assets/style.css, the GSAP CDN scripts, assets/schedule.js (on pages with a schedule) and assets/script.js.

Using It With Your Own Design

  • The colours are tokens on :root in assets/style.css. --butter is the ground and the identity; --chalk and --kiln are the second and dark surfaces; --ember, --glaze, --sea and --amber are the five class colours and the stickers. Translucent values resolve from the --*-rgb triples, so repaint both.
  • Type is Besley (display, roman and italic mixed in one line) and Reddit Sans (everything else), self-hosted in assets/fonts/ (see Fonts under Images and Credits). To swap them, replace the @font-face rules at the top of assets/style.css and the Besley preload in each page's <head>, then set --font-display and --font-body.
  • Behaviour hangs off data- attributes (listed below), not class names, so you can restyle freely.
  • Sections are independent. Delete any <section> and the script skips it. Delete a whole page and remove its link from the nav and footer of the others.
  • The cut-out figures are <figure class="cut"> elements positioned in CSS. Delete one and nothing else moves. Figures that rest on a line (the card edge, a rule, the photo's floor) carry the cut--rests class and a --contact value in style.css: the height, as a percentage of the image, of the point that touches the line (a foot, a seat). The figure's box sits on the line and is shifted down by 100% - contact, so the contact stays on the line at every width. If you use your own photograph, measure its contact row and update --contact.

Pages and Configuration

Page What it holds
index.html Temperature dial hero, Up next strip, today's classes, three rooms, sauna band, overheard rings, place photo, first-week offer
timetable.html The whole week on one time axis, class-type key, teacher filter, house rules
classes.html Five class blocks with spec sheets and next times, the 4-7-8 breath guide, first-timer questions
teachers.html Line-up of cut-out teachers, each teacher's panel and week
pricing.html First week, the month calculator, drop-in / ten-pack / membership, small print
visit.html Address and hours, real map with walking routes, facilities, contact form

The schedule (assets/schedule.js)

One object, window.KILN_SCHEDULE:

  • classes: one entry per class, { day, start, type, teacher }. day is 0 for Monday to 6 for Sunday; start is 24-hour "HH:MM". Add room to override the type's room, or url to deep-link one session.
  • types: name, length in minutes, default room and mark (the colour and glyph, defined as .mark--<name> in the stylesheet). Five are styled; add a sixth by adding a .mark-- rule and a .slot[data-type=""] colour.
  • teachers, rooms, days, saunaOpen (open hours per day, drawn as the amber track) and axis (the time range of the week view).
  • bookingUrl: where every Book link goes.

The rows inside [data-today-rows] and [data-week] in the HTML are a no-JavaScript fallback and are replaced when the script runs. If you change the schedule a lot, update or trim them.

Temperature dial ([data-dial-root])

Three radio buttons named room, each with a value and a data-angle (degrees from twelve o'clock, between -80 and 80). For each value there is an <img data-room-photo="value"> inside the frame and a <div data-room-copy="value"> of spec rows. The sticker text comes from the TEMPS map in initDial. The ring of set type is the textPath inside .dial__type.

Today and Up next ([data-today], [data-upnext])

The day strip builds itself for the current week and opens on today. The class menu filters by type. Up next shows the next two classes from now.

The week ([data-week-root])

Key buttons carry data-key="<type>"; the select is [data-week-teacher] with teacher keys as values. Hover or focus a class to light up its type; click a key to hold it. Below 1240px the week becomes stacked day lists from the same markup.

Classes ([data-next-times], [data-breath])

Each class block's [data-next-times="<type>"] list fills with the next three sessions. The breath guide runs the 4-7-8 pattern (four in, seven held, eight out) on one 19-second timeline; it starts on the visitor's command and pauses off screen and in hidden tabs.

Teachers ([data-lineup])

Unselected teachers are drawn as flat silhouettes by a CSS filter chain on the same image (solved for #D8B94A on the butter ground); re-solve it if you change the ground. Each .lineup__person button has data-teacher="<key>", matching a [data-teacher-panel] and a [data-mini-week] that fills from the schedule. teachers.html#teacher-ruth opens that teacher.

Pricing calculator ([data-calc])

Two range inputs (classes and sauna sessions a week). The prices it compares are the P object at the top of initCalc; keep them in step with the cards. The cheapest option gets .is-best on its [data-price] card.

Map ([data-routes])

MapLibre GL on OpenFreeMap tiles, visit.html only. Its script and stylesheet are not in the page: loadMapLibre in assets/script.js adds them when the map comes within a screen of the viewport, so the page paints without them; change MAPLIBRE_JS and MAPLIBRE_CSS there to use another version or a self-hosted copy. Until the map has loaded, and permanently without it, the map area shows a link to the location on openstreetmap.org. In buildRoutes, set STUDIO (your [lng, lat]), the STOPS and the ROUTES. Routes are real walking routes; fetch new ones with

Code snippet omitted: it ships with the download.

and paste routes[0].geometry.coordinates. Update the distances and minutes on the stop buttons from the same response. The OpenStreetMap attribution must stay.

Palette

Token Value Role
--butter #F4DB6E Ground on home, timetable, teachers, pricing
--chalk #FBF4DF Spec sheets, classes and visit ground
--kiln #3B2015 Dark band behind sauna photography
--ink #2A1810 Text, rules, pills
--ember / --ember-deep #E8662E / #A8360F Hot Flow, heat stickers / ember as text
--glaze #2445B8 Slow Yin, links, blue stickers
--sea #9CC9D6 Breath, cold
--amber #F2A23A Sauna Social, open sauna hours

Measured contrast for every pair is in the comment at the top of style.css. --ember, --sea and --amber are fills only; they carry ink text, never sit as text on butter.

Booking

The template does not take bookings. Book links go to bookingUrl (or a class's own url). The contact form on visit.html validates and shows a confirmation; give it an action (Formspree, Netlify Forms or your own endpoint) and it submits there.

Accessibility and Fallbacks

  • Native controls throughout: radio buttons under the dial, a tablist for days, toggle buttons with aria-pressed for the key, a radiogroup for the line-up, range inputs for the calculator. Every hover effect is mirrored on focus.
  • Without JavaScript every page is complete: the schedules show their static fallback, all teacher panels are listed, and the pricing cards stand without the calculator.
  • If the GSAP CDN is blocked, schedules, filters, the dial, the line-up and the calculator still work; only the motion is missing.
  • Under prefers-reduced-motion the reveals, parallax and ring rotation are off, the dial swaps instantly and the breath guide shows its written diagram.
  • Smooth scrolling is off with ?smooth=off in the URL or data-smooth="off" on <html>.

Dependencies

  • GSAP 3.15.0 and ScrollTrigger (jsDelivr), floor 3.12+
  • Lenis 1.3.17 (unpkg), optional
  • MapLibre GL 4.7.1 (unpkg, loaded on demand as the map nears the viewport) and OpenFreeMap tiles, visit.html only, no API key
  • Besley and Reddit Sans, self-hosted (SIL Open Font License 1.1)

Images and Credits

Images in assets/img/ are WebP derivatives baked from assets/img-manifest.json. Replace a file at the same name and size, or edit the manifest and re-run the image build. The cut-outs are transparent WebP baked from transparent PNGs (alpha is kept losslessly); the round avatars are cropped from the same files.

Responsive sizes: every photograph wider than 900px also ships at 800w (and 1200w when the full file is 1600w or wider), and cut-outs wider than 500px also ship at 400w. The pages serve them with srcset and a sizes value measured from each slot, so a phone downloads the small files, including the three dial photos in the hero. Manifest entries with variantOf are those variants; if you replace a photograph, replace or re-bake its variants too. The first-screen image on each page loads eagerly with fetchpriority="high"; everything below the fold is loading="lazy".

Stock photographs (Pexels licence, pexels.com/license):

  • room-sauna: pexels.com/photo/8284381
  • room-sea: pexels.com/photo/14640380
  • door-shed: pexels.com/photo/8436626
  • door-yard: pexels.com/photo/34097643
  • sauna-band: pexels.com/photo/32504784
  • place-margate: pexels.com/photo/20468413
  • tt-mats: pexels.com/photo/8436574
  • class-sculpt: pexels.com/photo/8436686
  • class-yin: pexels.com/photo/8436748
  • class-breath: pexels.com/photo/6648557
  • class-sauna: pexels.com/photo/32504786
  • pricing-steam: pexels.com/photo/8284386
  • visit-stove: pexels.com/photo/19453753
  • visit-woodstore: pexels.com/photo/27972232
  • visit-harbour: pexels.com/photo/25859536

Generated for this template (fictional people and places, not photographs of a real studio): the kiln interiors (room-kiln, door-kiln, class-hot-flow), the yard (visit-yard), every cut-out figure (cut-*) and avatar (av-*).

Fonts

Both families are self-hosted in assets/fonts/ as the latin woff2 files Google Fonts serves, declared by the @font-face rules at the top of assets/style.css, so the pages make no font requests to another site: Besley (display; one variable file for roman 500 and 700, plus the italic 500) and Reddit Sans (body and labels; one variable file for 400, 600 and 700). Besley roman, the face of every page heading, is preloaded in each page's <head>.

Licence: SIL Open Font License 1.1, full text and copyright lines in assets/fonts/OFL.txt (Besley: Copyright 2020 The Besley Project Authors; Reddit Sans: Copyright 2020-23 Reddit, Inc.). Keep that file with the fonts. To use Google Fonts instead, delete the @font-face rules and the font preload and add the Google Fonts <link> to the <head>.

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