The Salon Co.
A 14-page marketing website for a fictional luxury hair salon — built from scratch with vanilla HTML, CSS, and JavaScript. This is the salon vertical of the CH Studios white-label SaaS platform, designed to work as either a real business deployment or a standalone portfolio piece demonstrating production-level thinking.
Tech Stack
Project Snapshot
- Type: Frontend learning project, polished into a portfolio piece
- Stack: HTML · CSS · JavaScript — no build tools, no frameworks, no dependencies
- Status: Core pages live; services, gallery, contact, and booking pages in progress
- Team: Solo
- Role: Design and frontend development — layout, design system, interactions
Pages Built
index.html
Hero, services preview, reviews carousel, CTA
about.html
Founder story, timeline, principles, image gallery
stylists.html
Four full profiles, alternating layouts, booking badges
services.html
Service overview with accordion
blowout-style.html
Service detail page
precision-cut.html
Service detail page
color-highlights.html
Service detail page
keratin-treatment.html
Service detail page
gallery.html
Portfolio gallery with JS category filters
book.html
Booking page
contact.html
Contact page
location-hours.html
Location and hours
employment.html
Careers page
apprenticeship-program.html
Apprenticeship program details
Design System
The entire site's visual language is defined once in CSS custom properties and referenced everywhere — no hardcoded colors or font stacks scattered through the stylesheet.
Typography
Cormorant Garamond for headings — elegant, editorial, appropriate for a luxury brand. Jost for body text — clean and legible at small sizes. Both loaded from Google Fonts with font-display: swap to avoid invisible text on slow connections.
Color Palette
--color-primary #1A2E2A--color-surface #313E3A--color-secondary #F5F0E8--color-accent #C9A96E--color-white #FAFAF7--color-muted #6A746DLayout
CSS Grid for page-level structure and multi-column layouts. Flexbox for component-level alignment — navigation, cards, and inline elements. Both used where each makes the most sense rather than picking one for everything.
JavaScript Features
Everything in ~120 lines of vanilla JS — no libraries, no framework.
Scroll-Based Sticky Header
Adds a .scrolled class after 10px of scroll, swapping the header from dark green to a cream background. The header always stays visible without being visually heavy on page load.
Auto-Rotating Review Carousel
Testimonials rotate every 3 seconds automatically. Clickable progress bar indicators let users jump to any slide. Interval resets on manual navigation so a user click doesn't immediately get overridden by the auto-rotate.
Mobile Hamburger Menu
Toggles .nav-open on the nav element. Closes on any nav link click or an outside click — so users aren't trapped in an open menu. The hamburger icon is CSS-drawn, no image or icon font needed.
FAQ Accordion
Click to expand or collapse. The first item opens by default. Only one item is ever open at a time — opening a new one closes the previous. Toggles aria-expanded alongside the visual state for screen reader support.
Gallery Category Filters
Data-attribute–based show/hide. Filter buttons toggle an .active class for styling. No DOM elements are created or destroyed — cards are shown or hidden with CSS. This keeps filtering instant with no layout recalculation.
Service Detail Pages
Each service has its own dedicated page rather than a shared template with JS routing. No build step, no configuration — just HTML files. The tradeoff: less DRY, but the site works without JavaScript and loads immediately.
Technical Decisions
Single Shared Stylesheet
All 14 pages share one style.css (~3,300 lines). A component styled once looks the same everywhere. The cost is that every page loads styles it doesn't use — a framework would tree-shake these, but for a static site of this size the simplicity is worth it.
Static Header and Footer
Nav and footer are duplicated HTML across pages rather than JS-injected. The site works without JavaScript, there's no render delay waiting for a script, and no flash of unstyled navigation. The cost: a nav change requires editing every file.
CSS Custom Properties First
Every color is defined once on :root and referenced everywhere. Swapping the entire color palette is three line edits. This was a day-one decision, not a refactor — choosing the architecture before writing component styles.
Challenges
Breakpoint Overlap: 1024px Desktop vs. 1000px Hamburger Trigger
The desktop layout switches at 1024px, but the mobile hamburger menu activates at 1000px. In the 24px range between those two breakpoints, both the desktop nav and the mobile hamburger are present at the same time. This is a real bug: a viewport at 1010px gets hamburger behavior inside a desktop layout. The fix is to align both breakpoints to the same value — the desktop layout and the nav behavior need to change at the same moment.
Dead Font Weights: Lobster and Lobster Two
Both Lobster and Lobster Two are loaded in the <head> via Google Fonts but never referenced anywhere in the stylesheet. Every page load fetches these font files for no reason — added latency with zero visual output. The fix is to remove both <link> tags from every page's <head>.
Large Fixed Padding at Desktop Widths
Major sections use padding-left: 12rem on desktop. This works on wide screens but the responsive overrides at 1024px and 1000px leave a gap — narrower viewports get too much horizontal padding before the breakpoint fires. This is the kind of issue that appears between breakpoints rather than at them, and requires testing at every width in between rather than just at the defined breakpoints.
What I Learned
- CSS custom properties as a design system — defining all values in
:rootand referencing them throughout the stylesheet is the web equivalent of a centralized style guide. It makes changes trivial and enforces consistency without a preprocessor. - When to use Grid vs. Flexbox — Grid for two-dimensional layout (the page itself, the gallery, the stylists grid). Flexbox for one-dimensional alignment (nav items, card content, inline elements). Using both for their actual purpose instead of forcing one to do everything.
- Accessible accordion patterns — toggling
aria-expandedalongside the visual state so the interaction is meaningful to assistive technology, not just to sighted users. - Multi-page architecture tradeoffs — the simplicity of plain HTML files versus the maintenance cost of duplicated nav and footer across 14 pages. This project makes the cost of that tradeoff concrete in a way that reading about it doesn't.
- Typography for luxury brands — pairing a serif display face with a geometric sans-serif body, and understanding why that combination works for the brand voice being designed here.
Still In Progress
- Mobile responsiveness across all pages — breakpoints exist but need refinement on the stylists and gallery layouts
- Form functionality on the contact and booking pages — currently static HTML, needs either a form service (Formspree) or a backend endpoint
- Gallery images — placeholder layout is in place, real photography assets needed
Outcome
The Salon Co. is where I moved from following tutorials to making real design decisions. Building 14 pages with a shared design system — and no framework to enforce consistency for me — required thinking about CSS architecture from the start rather than cleaning it up at the end. The gallery filters, accordion, and mobile nav are all written in plain JavaScript against the DOM, which built a clearer mental model of how the browser actually works before reaching for abstractions.