HTML
<!-- Pages -->
<div class="page" id="page-0">
<div class="bg-word">STUDIO</div>
<div class="hero-grid">
<div>
<div class="hero-eyebrow">Creative Studio · Est. 2019</div>
<h1 class="hero-title">WE BUILD<br><span>BOLD</span><br>FUTURES</h1>
<p class="hero-body">A multi-disciplinary studio pushing the boundaries of brand, motion, and digital experience design.</p>
<button class="btn-hero" onclick="goTo(1)">View Work →</button>
</div>
<div class="hero-side">
<div class="hero-stat">
<div class="hero-stat-num">142</div>
<div class="hero-stat-label">Projects</div>
</div>
<div class="hero-stat">
<div class="hero-stat-num">8yr</div>
<div class="hero-stat-label">Experience</div>
</div>
<div class="hero-stat">
<div class="hero-stat-num">4.9</div>
<div class="hero-stat-label">Avg Rating</div>
</div>
</div>
</div>
</div>
<div class="page page-incoming" id="page-1">
<div class="page-header">
<h1>SELECTED<br>WORK</h1>
</div>
<div class="proj-grid">
<div class="proj-card"><div class="proj-num">01</div><div class="proj-cat">Brand Identity</div><div class="proj-title">Luminary<br>Financial</div><div class="proj-arrow">→</div></div>
<div class="proj-card"><div class="proj-num">02</div><div class="proj-cat">Digital Experience</div><div class="proj-title">Atlas<br>Platform</div><div class="proj-arrow">→</div></div>
<div class="proj-card"><div class="proj-num">03</div><div class="proj-cat">Motion & Film</div><div class="proj-title">Epoch<br>Campaign</div><div class="proj-arrow">→</div></div>
<div class="proj-card"><div class="proj-num">04</div><div class="proj-cat">Product Design</div><div class="proj-title">Nova<br>Wearables</div><div class="proj-arrow">→</div></div>
</div>
</div>
<div class="page page-incoming" id="page-2">
<div class="about-grid">
<div>
<h1>WE ARE<br><em>FORM</em><br>STUDIO</h1>
</div>
<div>
<p class="about-body">A tight team of designers, developers, and strategists who believe that great work comes from obsessing over every pixel, every word, and every interaction.</p>
<p class="about-body">We've partnered with everyone from pre-seed startups to Fortune 500s — always bringing the same level of care.</p>
<div class="skill-row">
<div class="skill-item">
<div class="skill-name"><span>Brand Design</span><span>97%</span></div>
<div class="skill-bar"><div class="skill-fill" style="width:97%"></div></div>
</div>
<div class="skill-item">
<div class="skill-name"><span>Web Development</span><span>92%</span></div>
<div class="skill-bar"><div class="skill-fill" style="width:92%"></div></div>
</div>
<div class="skill-item">
<div class="skill-name"><span>Motion Design</span><span>88%</span></div>
<div class="skill-bar"><div class="skill-fill" style="width:88%"></div></div>
</div>
</div>
</div>
</div>
</div>
<!-- Nav -->
<nav class="site-nav">
<div class="nav-logo">FORM</div>
<div class="nav-links">
<button class="nav-link active" data-idx="0" onclick="goTo(0)">Home</button>
<button class="nav-link" data-idx="1" onclick="goTo(1)">Work</button>
<button class="nav-link" data-idx="2" onclick="goTo(2)">About</button>
</div>
</nav>
<!-- Page dots -->
<div class="page-indicator">
<button class="ind-dot active" data-idx="0" onclick="goTo(0)"></button>
<button class="ind-dot" data-idx="1" onclick="goTo(1)"></button>
<button class="ind-dot" data-idx="2" onclick="goTo(2)"></button>
</div> CSS
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--dur: 800ms;
--ease: cubic-bezier(0.76, 0, 0.24, 1);
}
html, body {
height: 100%;
overflow: hidden;
font-family: 'Space Grotesk', sans-serif;
}
/* Pages */
.page {
position: absolute;
inset: 0;
display: flex;
flex-direction: column;
}
/* Base state: clipped to nothing (right side) */
.page-incoming {
clip-path: polygon(100% 0%, 100% 0%, 100% 100%, 100% 100%);
transition: clip-path var(--dur) var(--ease);
pointer-events: none;
z-index: 2;
}
/* Fully revealed */
.page-incoming.reveal {
clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%);
}
/* Exiting page stays visible beneath */
.page-outgoing {
z-index: 1;
}
/* Page 0 — Hero */
#page-0 {
background: #0e0e14;
justify-content: flex-end;
padding: 80px;
color: white;
}
#page-0 .bg-word {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-family: 'Bebas Neue', sans-serif;
font-size: min(25vw, 240px);
line-height: 1;
color: rgba(255,255,255,0.04);
white-space: nowrap;
pointer-events: none;
letter-spacing: -0.02em;
}
#page-0 .hero-grid {
display: grid;
grid-template-columns: 1fr auto;
align-items: end;
gap: 40px;
width: 100%;
max-width: 1100px;
}
#page-0 .hero-eyebrow {
font-size: 11px;
letter-spacing: 0.25em;
text-transform: uppercase;
color: #8888aa;
margin-bottom: 24px;
}
#page-0 .hero-title {
font-family: 'Bebas Neue', sans-serif;
font-size: clamp(52px, 9vw, 120px);
line-height: 0.92;
letter-spacing: -0.01em;
color: white;
margin-bottom: 32px;
}
#page-0 .hero-title span { color: #c8ff00; }
#page-0 .hero-body {
font-size: 15px;
line-height: 1.75;
color: #8888aa;
max-width: 420px;
margin-bottom: 48px;
}
.btn-hero {
display: inline-flex;
align-items: center;
gap: 12px;
background: #c8ff00;
color: #0e0e14;
border: none;
padding: 18px 36px;
font-family: 'Space Grotesk', sans-serif;
font-size: 14px;
font-weight: 700;
letter-spacing: 0.06em;
text-transform: uppercase;
cursor: pointer;
border-radius: 2px;
transition: transform 0.2s, background 0.2s;
}
.btn-hero:hover { background: #d4ff33; transform: translateX(3px); }
.hero-side {
display: flex;
flex-direction: column;
gap: 12px;
align-items: flex-end;
}
.hero-stat {
text-align: right;
border-right: 2px solid #c8ff00;
padding-right: 20px;
}
.hero-stat-num {
font-family: 'Bebas Neue', sans-serif;
font-size: 40px;
color: white;
line-height: 1;
}
.hero-stat-label {
font-size: 10px;
letter-spacing: 0.15em;
text-transform: uppercase;
color: #555570;
}
/* Page 1 — Projects */
#page-1 {
background: #c8ff00;
overflow-y: auto;
padding: 80px;
color: #0e0e14;
}
#page-1 .page-header {
display: flex;
align-items: flex-start;
justify-content: space-between;
margin-bottom: 64px;
}
#page-1 h1 {
font-family: 'Bebas Neue', sans-serif;
font-size: clamp(52px, 9vw, 112px);
line-height: 0.9;
letter-spacing: -0.01em;
color: #0e0e14;
}
.proj-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 3px;
}
.proj-card {
background: #0e0e14;
padding: 36px;
color: white;
display: flex;
flex-direction: column;
min-height: 220px;
position: relative;
overflow: hidden;
cursor: pointer;
transition: background 0.3s;
}
.proj-card:nth-child(even) { background: #1a1a24; }
.proj-card:hover { background: #2a2a3a; }
.proj-num {
font-family: 'Bebas Neue', sans-serif;
font-size: 64px;
color: rgba(200,255,0,0.15);
line-height: 1;
position: absolute;
top: 16px;
right: 24px;
letter-spacing: -0.04em;
}
.proj-cat {
font-size: 9px;
letter-spacing: 0.2em;
text-transform: uppercase;
color: #555570;
margin-bottom: 12px;
}
.proj-title {
font-family: 'Bebas Neue', sans-serif;
font-size: 36px;
letter-spacing: 0.01em;
line-height: 1.1;
color: white;
margin-bottom: auto;
}
.proj-arrow {
margin-top: 32px;
font-size: 20px;
color: #c8ff00;
}
/* Page 2 — About */
#page-2 {
background: #1a0a2e;
color: white;
padding: 80px;
display: flex;
align-items: center;
}
#page-2 .about-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 80px;
align-items: center;
max-width: 1000px;
margin: 0 auto;
width: 100%;
}
#page-2 h1 {
font-family: 'Bebas Neue', sans-serif;
font-size: clamp(52px, 8vw, 100px);
line-height: 0.9;
letter-spacing: -0.01em;
}
#page-2 h1 em {
color: #c8ff00;
font-style: italic;
font-family: inherit;
}
#page-2 .about-body {
font-size: 15px;
line-height: 1.8;
color: #8888aa;
margin-bottom: 32px;
}
.skill-row { margin-top: 32px; }
.skill-item { margin-bottom: 16px; }
.skill-name {
display: flex;
justify-content: space-between;
font-size: 12px;
font-weight: 500;
letter-spacing: 0.08em;
text-transform: uppercase;
margin-bottom: 6px;
color: #aaaacc;
}
.skill-bar {
height: 2px;
background: rgba(255,255,255,0.1);
border-radius: 1px;
overflow: hidden;
}
.skill-fill {
height: 100%;
background: #c8ff00;
border-radius: 1px;
}
/* Nav */
.site-nav {
position: fixed;
top: 0; left: 0; right: 0;
z-index: 50;
padding: 28px 48px;
display: flex;
align-items: center;
justify-content: space-between;
mix-blend-mode: difference;
}
.nav-logo {
font-family: 'Bebas Neue', sans-serif;
font-size: 24px;
letter-spacing: 0.05em;
color: white;
cursor: pointer;
}
.nav-links {
display: flex;
gap: 32px;
}
.nav-link {
font-size: 12px;
font-weight: 500;
letter-spacing: 0.12em;
text-transform: uppercase;
color: white;
cursor: pointer;
border: none;
background: none;
position: relative;
padding-bottom: 4px;
transition: opacity 0.2s;
}
.nav-link::after {
content: '';
position: absolute;
bottom: 0; left: 0;
width: 0%; height: 1px;
background: white;
transition: width 0.3s;
}
.nav-link:hover::after,
.nav-link.active::after { width: 100%; }
/* Page indicator */
.page-indicator {
position: fixed;
right: 32px;
top: 50%;
transform: translateY(-50%);
z-index: 50;
display: flex;
flex-direction: column;
gap: 8px;
mix-blend-mode: difference;
}
.ind-dot {
width: 4px; height: 4px;
background: rgba(255,255,255,0.3);
border-radius: 2px;
transition: height 0.3s, background 0.3s;
cursor: pointer;
border: none;
}
.ind-dot.active {
height: 24px;
background: white;
}
@media (max-width: 640px) {
#page-0, #page-1, #page-2 { padding: 80px 24px 40px; }
#page-0 .hero-grid { grid-template-columns: 1fr; }
.hero-side { display: none; }
.proj-grid { grid-template-columns: 1fr; }
#page-2 .about-grid { grid-template-columns: 1fr; gap: 32px; }
.site-nav { padding: 20px 24px; }
.nav-links { gap: 16px; }
} JS
const pages = document.querySelectorAll('.page');
const navLinks = document.querySelectorAll('.nav-link');
const indDots = document.querySelectorAll('.ind-dot');
let current = 0;
let transitioning = false;
function goTo(idx) {
if (idx === current || transitioning) return;
transitioning = true;
const prev = current;
current = idx;
// Update nav & dots
navLinks.forEach(l => l.classList.toggle('active', +l.dataset.idx === current));
indDots.forEach(d => d.classList.toggle('active', +d.dataset.idx === current));
// Set the incoming page visible but clipped
const incoming = pages[current];
incoming.classList.add('page-incoming');
incoming.classList.remove('reveal');
incoming.style.zIndex = 2;
// Trigger reflow then animate
requestAnimationFrame(() => {
requestAnimationFrame(() => {
incoming.classList.add('reveal');
});
});
// After animation, clean up old page
setTimeout(() => {
pages[prev].style.zIndex = 1;
incoming.style.zIndex = 1;
// Reset all other pages to hidden state
pages.forEach((p, i) => {
if (i !== current) {
p.classList.add('page-incoming');
p.classList.remove('reveal');
p.style.zIndex = '';
} else {
p.classList.remove('page-incoming');
p.classList.remove('reveal');
p.style.zIndex = '';
}
});
transitioning = false;
}, 850);
}
// Initialize: show first page, hide rest
pages.forEach((p, i) => {
if (i === 0) {
p.classList.remove('page-incoming');
} else {
p.classList.add('page-incoming');
}
});
// Keyboard
document.addEventListener('keydown', e => {
if (e.key === 'ArrowRight' || e.key === 'ArrowDown') goTo(Math.min(current + 1, pages.length - 1));
if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') goTo(Math.max(current - 1, 0));
});
// Wheel
let lastWheel = 0;
document.addEventListener('wheel', e => {
const now = Date.now();
if (now - lastWheel < 900) return;
lastWheel = now;
if (e.deltaY > 0) goTo(Math.min(current + 1, pages.length - 1));
if (e.deltaY < 0) goTo(Math.max(current - 1, 0));
});