Apple Vision Pro UHD Product Page
An ultra-high-definition product showcase inspired by Apple's Vision Pro landing page. Features immersive scroll-based reveals, kinetic typography, depth-mapping shadows, and high-fidelity motion sequences using GSAP and Lenis.
Open in Lab
MCP
gsap scrolltrigger lenis css vanilla-js
Targets: JS HTML
Code
@import url("https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;600;700;800&display=swap");
:root {
--blue-primary: #0071e3;
--blue-glow: rgba(0, 113, 227, 0.4);
--glass-bg: rgba(22, 22, 23, 0.7);
--glass-border: rgba(255, 255, 255, 0.1);
--text-primary: #f5f5f7;
--text-secondary: #86868b;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: "Outfit", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background-color: #000;
color: var(--text-primary);
-webkit-font-smoothing: antialiased;
overflow-x: hidden;
}
/* --- Gradient Blobs --- */
.bg-blobs {
position: fixed;
inset: 0;
z-index: -1;
overflow: hidden;
}
.blob {
position: absolute;
border-radius: 50%;
filter: blur(120px);
opacity: 0.15;
pointer-events: none;
}
.blob-1 {
width: 800px;
height: 800px;
background: var(--blue-primary);
top: -200px;
left: -200px;
}
.blob-2 {
width: 600px;
height: 600px;
background: #bf40bf;
bottom: -100px;
right: -100px;
}
/* --- Hero Section --- */
.hero-section {
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: relative;
}
.hero-content {
text-align: center;
}
.hero-title {
font-size: clamp(4rem, 15vw, 12rem);
font-weight: 800;
letter-spacing: -0.05em;
background: linear-gradient(180deg, #fff 0%, #a1a1a6 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
opacity: 0;
}
.hero-subtitle {
font-size: 1.5rem;
color: var(--text-secondary);
font-weight: 300;
margin-top: 1rem;
letter-spacing: 0.02em;
opacity: 0;
}
/* --- Sections --- */
section {
padding: 120px 1.5rem;
position: relative;
}
.section-container {
max-width: 72rem;
margin: 0 auto;
}
.section-title {
font-size: clamp(2.5rem, 8vw, 5rem);
font-weight: 700;
line-height: 1.1;
margin-bottom: 2rem;
letter-spacing: -0.03em;
}
.section-desc {
font-size: 1.25rem;
color: var(--text-secondary);
max-width: 600px;
line-height: 1.5;
}
.section-header {
margin-bottom: 3rem;
}
.text-gradient {
background: linear-gradient(90deg, #fff, #86868b);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
.text-secondary {
color: var(--text-secondary);
}
.text-sm {
font-size: 0.875rem;
}
/* --- Intro Section --- */
.intro-section {
padding: 120px 1.5rem;
}
.intro-grid {
max-width: 72rem;
margin: 0 auto;
display: flex;
flex-direction: column;
align-items: center;
gap: 4rem;
}
@media (min-width: 768px) {
.intro-grid {
flex-direction: row;
gap: 4rem;
}
}
.intro-text {
flex: 1;
}
.intro-cta {
margin-top: 3rem;
}
/* --- CSS-only Vision Pro Headset --- */
.device-container {
flex: 1;
perspective: 1000px;
display: flex;
justify-content: center;
}
.device-card {
position: relative;
transform-style: preserve-3d;
}
.device-visual {
position: relative;
width: 320px;
height: 200px;
display: flex;
align-items: center;
justify-content: center;
}
.headset {
position: relative;
width: 280px;
height: 100px;
}
.headset-glass {
position: absolute;
inset: 0;
background: linear-gradient(135deg, #2a2a2e 0%, #1a1a1e 40%, #0a0a0e 100%);
border-radius: 50px;
border: 1px solid rgba(255, 255, 255, 0.12);
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.05), inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 20px
60px rgba(0, 0, 0, 0.6);
overflow: hidden;
}
.headset-glass::before {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(
105deg,
transparent 30%,
rgba(255, 255, 255, 0.04) 45%,
rgba(255, 255, 255, 0.08) 50%,
rgba(255, 255, 255, 0.04) 55%,
transparent 70%
);
}
.headset-lens {
position: absolute;
width: 50px;
height: 50px;
top: 50%;
transform: translateY(-50%);
border-radius: 50%;
background: radial-gradient(
circle at 40% 40%,
rgba(80, 80, 100, 0.6) 0%,
rgba(30, 30, 45, 0.8) 60%,
rgba(10, 10, 20, 0.95) 100%
);
border: 1px solid rgba(255, 255, 255, 0.08);
box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.4);
}
.headset-lens-l {
left: 55px;
}
.headset-lens-r {
right: 55px;
}
.headset-eyesight {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 180px;
height: 40px;
background: linear-gradient(
90deg,
transparent 0%,
rgba(100, 120, 255, 0.08) 20%,
rgba(120, 140, 255, 0.15) 50%,
rgba(100, 120, 255, 0.08) 80%,
transparent 100%
);
border-radius: 20px;
animation: eyesight-pulse 4s ease-in-out infinite;
}
@keyframes eyesight-pulse {
0%,
100% {
opacity: 0.4;
}
50% {
opacity: 1;
}
}
.headset-band {
position: absolute;
top: 15px;
right: -30px;
width: 50px;
height: 70px;
border-right: 3px solid rgba(200, 200, 210, 0.3);
border-radius: 0 30px 30px 0;
}
.headset-knob {
position: absolute;
top: 8px;
right: 8px;
width: 16px;
height: 16px;
border-radius: 50%;
background: linear-gradient(135deg, #444 0%, #222 100%);
border: 1px solid rgba(255, 255, 255, 0.15);
}
.device-glow {
position: absolute;
inset: -40px;
border-radius: 50%;
background: radial-gradient(circle, rgba(0, 113, 227, 0.15) 0%, transparent 70%);
pointer-events: none;
animation: device-glow-pulse 6s ease-in-out infinite;
}
@keyframes device-glow-pulse {
0%,
100% {
opacity: 0.5;
transform: scale(1);
}
50% {
opacity: 1;
transform: scale(1.1);
}
}
/* --- Glass Card --- */
.glass-card {
background: var(--glass-bg);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
border: 1px solid var(--glass-border);
border-radius: 40px;
padding: 60px;
transition: all 0.5s cubic-bezier(0.23, 1, 0.32, 1);
}
.glass-card:hover {
border-color: rgba(255, 255, 255, 0.2);
}
/* --- Feature Grid --- */
.feature-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 30px;
width: 100%;
}
.feature-box {
background: rgba(255, 255, 255, 0.03);
border: 1px solid var(--glass-border);
border-radius: 30px;
padding: 40px;
transition: all 0.4s ease;
}
.feature-box:hover {
background: rgba(255, 255, 255, 0.05);
transform: translateY(-10px);
}
.feature-icon {
width: 56px;
height: 56px;
border-radius: 16px;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 20px;
color: #fff;
}
.feature-icon-prod {
background: rgba(37, 99, 235, 0.2);
}
.feature-icon-ent {
background: rgba(124, 58, 237, 0.2);
}
.feature-icon-photo {
background: rgba(20, 184, 166, 0.2);
}
.feature-title {
font-size: 1.5rem;
font-weight: 700;
margin-bottom: 1rem;
}
.tag {
display: inline-block;
padding: 6px 16px;
background: var(--blue-primary);
color: white;
border-radius: 20px;
font-size: 12px;
font-weight: 600;
margin-bottom: 20px;
text-transform: uppercase;
letter-spacing: 0.1em;
}
.tag-blue {
background: #2563eb;
}
.tag-purple {
background: #7c3aed;
}
.tag-teal {
background: #0d9488;
}
/* --- Tech / Spec Section --- */
.tech-header {
text-align: center;
margin-bottom: 3rem;
}
.tech-title {
font-size: clamp(2rem, 5vw, 3.5rem);
font-weight: 700;
margin-bottom: 1rem;
}
.tech-desc {
max-width: 40rem;
margin: 0 auto;
}
.spec-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 30px;
margin-top: 3rem;
}
.spec-item {
text-align: center;
}
.spec-number {
font-size: 3rem;
font-weight: 800;
background: linear-gradient(180deg, #fff, var(--blue-primary));
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
margin-bottom: 0.5rem;
}
.spec-label {
font-weight: 700;
font-size: 1.1rem;
margin-bottom: 0.5rem;
}
/* --- CTA Section --- */
.cta-section {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
min-height: 80vh;
overflow: hidden;
}
.cta-title {
position: relative;
z-index: 2;
}
.cta-rings {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
pointer-events: none;
}
.ring {
position: absolute;
border-radius: 50%;
border: 1px solid rgba(255, 255, 255, 0.04);
}
.ring-1 {
width: 300px;
height: 300px;
}
.ring-2 {
width: 500px;
height: 500px;
}
.ring-3 {
width: 700px;
height: 700px;
}
.btn-primary {
display: inline-block;
padding: 16px 32px;
background: #fff;
color: #000;
border-radius: 30px;
font-weight: 600;
text-decoration: none;
transition: all 0.3s ease;
border: none;
cursor: pointer;
font-size: 1rem;
position: relative;
z-index: 2;
}
.btn-primary:hover {
transform: scale(1.05);
box-shadow: 0 10px 20px rgba(255, 255, 255, 0.1);
}
.btn-glow {
box-shadow: 0 0 30px rgba(0, 113, 227, 0.3);
}
/* --- Animations --- */
.reveal {
opacity: 0;
transform: translateY(30px);
}
.scroll-indicator {
position: absolute;
bottom: 40px;
left: 50%;
transform: translateX(-50%);
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
color: var(--text-secondary);
font-size: 10px;
text-transform: uppercase;
letter-spacing: 0.3em;
font-weight: 700;
}
.line {
width: 1px;
height: 60px;
background: linear-gradient(to bottom, var(--blue-primary), transparent);
}
/* --- Responsive --- */
@media (max-width: 768px) {
.glass-card {
padding: 30px;
border-radius: 24px;
}
.feature-box {
padding: 24px;
border-radius: 20px;
}
.device-visual {
width: 240px;
height: 160px;
}
.headset {
width: 210px;
height: 75px;
}
.headset-lens {
width: 38px;
height: 38px;
}
.headset-lens-l {
left: 40px;
}
.headset-lens-r {
right: 40px;
}
.headset-band {
width: 35px;
height: 50px;
right: -20px;
}
}// Initialize Lenis for smooth scrolling (driven by GSAP ticker)
const lenis = new Lenis({
duration: 1.2,
easing: (t) => Math.min(1, 1.001 - 2 ** (-10 * t)),
smoothWheel: true,
autoRaf: false,
});
// GSAP Animations
gsap.registerPlugin(ScrollTrigger);
// Single raf loop via GSAP ticker — avoids double-calling lenis.raf
lenis.on("scroll", ScrollTrigger.update);
gsap.ticker.add((time) => {
lenis.raf(time * 1000);
});
gsap.ticker.lagSmoothing(0);
// Hero Entrance
const tl = gsap.timeline({ defaults: { ease: "power4.out" } });
tl.to(".hero-title", {
opacity: 1,
scale: 1,
filter: "blur(0px)",
duration: 2.5,
delay: 0.5,
})
.to(
".hero-subtitle",
{
opacity: 1,
y: -20,
duration: 1.5,
},
"-=2"
)
.to(
".scroll-indicator",
{
opacity: 1,
y: 0,
duration: 1,
},
"-=1"
);
// Parallax for Background Blobs
gsap.to(".blob-1", {
y: 200,
x: 100,
scrollTrigger: {
trigger: "body",
start: "top top",
end: "bottom bottom",
scrub: 1,
},
});
gsap.to(".blob-2", {
y: -300,
x: -150,
scrollTrigger: {
trigger: "body",
start: "top top",
end: "bottom bottom",
scrub: 1,
},
});
// Generic Reveal Animation — elements stay visible once revealed
const revealElements = gsap.utils.toArray(".reveal");
revealElements.forEach((el) => {
gsap.fromTo(
el,
{ opacity: 0, y: 50 },
{
opacity: 1,
y: 0,
duration: 1.2,
ease: "power3.out",
scrollTrigger: {
trigger: el,
start: "top 85%",
toggleActions: "play none none none",
},
}
);
});
// Device Showcase Parallax / Tilt
const deviceCard = document.querySelector(".device-card");
if (deviceCard) {
gsap.to(deviceCard, {
y: -50,
rotateX: 5,
scrollTrigger: {
trigger: ".intro-section",
start: "top center",
end: "bottom center",
scrub: true,
},
});
// Mouse tilt effect
window.addEventListener("mousemove", (e) => {
const rect = deviceCard.getBoundingClientRect();
const x = (e.clientX - (rect.left + rect.width / 2)) / (rect.width / 2);
const y = (e.clientY - (rect.top + rect.height / 2)) / (rect.height / 2);
gsap.to(deviceCard, {
rotateY: x * 10,
rotateX: -y * 10,
duration: 0.8,
ease: "power2.out",
});
});
}
// Staggered reveal for feature boxes
const featureGrid = document.querySelector(".feature-grid");
if (featureGrid) {
gsap.fromTo(
".feature-box",
{ opacity: 0, y: 40, scale: 0.95 },
{
opacity: 1,
y: 0,
scale: 1,
duration: 1,
stagger: 0.2,
ease: "power3.out",
scrollTrigger: {
trigger: featureGrid,
start: "top 80%",
toggleActions: "play none none none",
},
}
);
}
// Hero content zoom-out on scroll (targets wrapper to avoid conflict with entrance animation)
gsap.to(".hero-content", {
scale: 1.3,
opacity: 0,
filter: "blur(20px)",
scrollTrigger: {
trigger: ".hero-section",
start: "top top",
end: "80% top",
scrub: true,
},
});
// CTA rings expand on scroll
gsap.utils.toArray(".ring").forEach((ring, i) => {
gsap.fromTo(
ring,
{ scale: 0.5, opacity: 0 },
{
scale: 1,
opacity: 1,
duration: 1.5,
delay: i * 0.15,
scrollTrigger: {
trigger: ".cta-section",
start: "top 80%",
toggleActions: "play none none none",
},
}
);
});
// Spec numbers count-up animation
const specNumbers = document.querySelectorAll(".spec-number");
specNumbers.forEach((el) => {
const text = el.textContent;
const num = parseInt(text, 10);
if (!isNaN(num) && num > 0) {
const suffix = text.replace(String(num), "");
el.textContent = "0" + suffix;
ScrollTrigger.create({
trigger: el,
start: "top 85%",
once: true,
onEnter: () => {
gsap.to(
{ val: 0 },
{
val: num,
duration: 2,
ease: "power2.out",
onUpdate: function () {
el.textContent = Math.round(this.targets()[0].val) + suffix;
},
}
);
},
});
}
});<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Apple Vision Pro | The Future of Spatial Computing</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<!-- Background Decoration -->
<div class="bg-blobs">
<div class="blob blob-1"></div>
<div class="blob blob-2"></div>
</div>
<!-- Main Content -->
<main id="main">
<!-- Hero Section -->
<section class="hero-section">
<div class="hero-content">
<h1 class="hero-title">VISION</h1>
<p class="hero-subtitle">The era of spatial computing is here.</p>
</div>
<div class="scroll-indicator">
<span>Explore</span>
<div class="line"></div>
</div>
</section>
<!-- Product Introduction -->
<section class="intro-section">
<div class="intro-grid">
<div class="reveal intro-text">
<h2 class="section-title text-gradient">Welcome to <br/> Spatial Computing.</h2>
<p class="section-desc">Apple Vision Pro seamlessly blends digital content with your physical space. You navigate simply by using your eyes, hands, and voice.</p>
<div class="intro-cta">
<button class="btn-primary">Watch the film</button>
</div>
</div>
<div class="device-container reveal">
<div class="device-card">
<div class="device-visual">
<!-- CSS-only Vision Pro headset -->
<div class="headset">
<div class="headset-glass">
<div class="headset-lens headset-lens-l"></div>
<div class="headset-lens headset-lens-r"></div>
<div class="headset-eyesight"></div>
</div>
<div class="headset-band"></div>
<div class="headset-knob"></div>
</div>
<div class="device-glow"></div>
</div>
</div>
</div>
</div>
</section>
<!-- Dynamic Experiences -->
<section class="experience-section">
<div class="section-container">
<div class="reveal section-header">
<span class="tag">Experiences</span>
<h2 class="section-title">An infinite <br/> canvas for apps.</h2>
</div>
<div class="feature-grid">
<div class="feature-box">
<div class="feature-icon feature-icon-prod">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/>
</svg>
</div>
<h3 class="tag tag-blue">Productivity</h3>
<h4 class="feature-title">Your workspace, anywhere.</h4>
<p class="text-secondary">Arrange apps anywhere and scale them to the perfect size. It's the ultimate workspace for what you love to do.</p>
</div>
<div class="feature-box">
<div class="feature-icon feature-icon-ent">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<polygon points="5 3 19 12 5 21 5 3"/>
</svg>
</div>
<h3 class="tag tag-purple">Entertainment</h3>
<h4 class="feature-title">A personal theater.</h4>
<p class="text-secondary">Transform any room into your own personal movie theater. With more pixels than a 4K TV for each eye.</p>
</div>
<div class="feature-box">
<div class="feature-icon feature-icon-photo">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><path d="M21 15l-5-5L5 21"/>
</svg>
</div>
<h3 class="tag tag-teal">Spatial Photos</h3>
<h4 class="feature-title">Relive your memories.</h4>
<p class="text-secondary">Capture spatial photos and videos that transport you back into a moment. Panoramas wrap around you.</p>
</div>
</div>
</div>
</section>
<!-- Design & Technology -->
<section class="tech-section">
<div class="section-container glass-card reveal">
<div class="tech-header">
<h2 class="tech-title">Design by Apple.</h2>
<p class="text-secondary tech-desc">A singular piece of three-dimensionally formed laminated glass acts as an optical surface for the cameras and sensors.</p>
</div>
<div class="spec-grid">
<div class="spec-item reveal">
<div class="spec-number">23M</div>
<h5 class="spec-label">Pixels</h5>
<p class="text-secondary text-sm">Micro-OLED display system delivering stunning visual fidelity.</p>
</div>
<div class="spec-item reveal">
<div class="spec-number">12</div>
<h5 class="spec-label">Cameras</h5>
<p class="text-secondary text-sm">An advanced sensor array that maps your surroundings in real time.</p>
</div>
<div class="spec-item reveal">
<div class="spec-number">M2+R1</div>
<h5 class="spec-label">Dual Chips</h5>
<p class="text-secondary text-sm">Delivering spatial experiences with virtually no lag.</p>
</div>
<div class="spec-item reveal">
<div class="spec-number">∞</div>
<h5 class="spec-label">Spatial Audio</h5>
<p class="text-secondary text-sm">Audio pods deliver personalized sound from the world around you.</p>
</div>
</div>
</div>
</section>
<!-- Final CTA -->
<section class="cta-section">
<div class="cta-rings">
<div class="ring ring-1"></div>
<div class="ring ring-2"></div>
<div class="ring ring-3"></div>
</div>
<h2 class="reveal section-title cta-title">The Future <br/> is Here.</h2>
<div class="reveal">
<button class="btn-primary btn-glow">Pre-order Now</button>
</div>
</section>
</main>
<!-- Dependencies -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/ScrollTrigger.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lenis@1.1.18/dist/lenis.min.js"></script>
<script src="./script.js"></script>
</body>
</html>Apple Vision Pro UHD Product Page
This resource demonstrates a premium, high-fidelity product showcase. It is designed to “wow” the user with smooth transitions, depth effects, and perfectly timed typography reveals.
Core Features
- Spatial Scroll Narrative — A seamless blend of digital content and physical space, revealed through scroll-triggered GSAP timelines.
- Dynamic Glassmorphism — Components use high-fidelity backdrop blurs and subtle border glows to simulate premium materials.
- Inertial Smooth Scrolling — Powered by Lenis for a consistent, fluid experience across all input devices.
- Interactive Device Showcase — A 3D-perspective product card that reacts to both scroll position and mouse tracking.
- Micro-Animations — Staggered reveals, kinetic typography, and pulse effects that provide subtle feedback and visual interest.
Tech Stack
- GSAP & ScrollTrigger — The industry standard for high-performance web animations.
- Lenis — For smooth, inertial scrolling.
- Vanilla CSS3 — Modern properties like
backdrop-filter,clamp(), and custom properties for a flexible design system. - Responsive Layout — Adaptive grid and flexible typography ensuring a premium experience on any screen size.
Design Principles
- Spatial Depth — Using layers, blurs, and shadows to create a sense of three-dimensional space.
- Minimalist Aesthetic — Following Apple’s design language: lots of whitespace, bold typography, and a dark, premium color palette.
- Fluid Intent — Every movement has a purpose and feels natural, avoiding jarring transitions or “jumpy” animations.