Nintendo UHD Console Showcase Page
An ultra-high-definition console showcase inspired by Nintendo's playful design language. Features vibrant colors, bouncy animations, parallax scroll, and joyful micro-interactions using GSAP.
Open in Lab
MCP
gsap scrolltrigger css vanilla-js
Targets: JS HTML
Code
@import url("https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;800;900&display=swap");
:root {
--red: #e60012;
--blue: #0ab9e6;
--dark: #1a1a2e;
--darker: #12121f;
--fg: #f0f0f5;
--fg-muted: #9999aa;
--card-bg: rgba(255, 255, 255, 0.05);
--border: rgba(255, 255, 255, 0.08);
--radius: 20px;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: "Nunito", -apple-system, sans-serif;
background: var(--darker);
color: var(--fg);
-webkit-font-smoothing: antialiased;
overflow-x: hidden;
}
/* --- Floating shapes --- */
.bg-shapes {
position: fixed;
inset: 0;
z-index: -1;
overflow: hidden;
pointer-events: none;
}
.shape {
position: absolute;
opacity: 0.06;
}
.shape-circle {
border-radius: 50%;
}
.shape-1 {
width: 400px;
height: 400px;
background: var(--red);
top: -100px;
left: -100px;
filter: blur(80px);
}
.shape-2 {
width: 350px;
height: 350px;
background: var(--blue);
bottom: -50px;
right: -50px;
filter: blur(80px);
}
.shape-cross {
font-size: 120px;
font-weight: 900;
color: var(--red);
top: 40%;
right: 10%;
opacity: 0.04;
}
.shape-triangle {
width: 0;
height: 0;
border-left: 60px solid transparent;
border-right: 60px solid transparent;
border-bottom: 100px solid var(--blue);
top: 20%;
left: 5%;
opacity: 0.04;
}
.shape-5 {
width: 200px;
height: 200px;
background: #f5c518;
top: 60%;
left: 50%;
filter: blur(100px);
}
/* --- Hero --- */
.hero {
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
padding: 48px 24px;
gap: 32px;
}
.hero-content {
position: relative;
}
.hero-badge {
display: inline-block;
padding: 6px 18px;
background: var(--red);
color: #fff;
border-radius: 20px;
font-size: 12px;
font-weight: 800;
letter-spacing: 0.15em;
margin-bottom: 24px;
opacity: 0;
}
.hero-title {
font-size: clamp(2.5rem, 10vw, 5.5rem);
font-weight: 900;
line-height: 1;
letter-spacing: -0.03em;
margin-bottom: 16px;
}
.hero-word {
display: block;
opacity: 0;
transform: translateY(40px) rotate(-3deg);
}
.hero-word--red {
color: var(--red);
}
.hero-word--blue {
color: var(--blue);
}
.hero-desc {
font-size: 1.1rem;
color: var(--fg-muted);
max-width: 440px;
margin: 0 auto 20px;
line-height: 1.5;
opacity: 0;
}
.hero-actions {
display: flex;
gap: 12px;
justify-content: center;
flex-wrap: wrap;
opacity: 0;
}
.text-red {
color: var(--red);
}
.text-blue {
color: var(--blue);
}
/* --- Buttons --- */
.btn {
padding: 14px 28px;
border: none;
border-radius: 50px;
font-weight: 700;
font-size: 15px;
cursor: pointer;
transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.2s;
font-family: inherit;
}
.btn:hover {
transform: scale(1.06);
}
.btn:active {
transform: scale(0.97);
}
.btn-red {
background: var(--red);
color: #fff;
box-shadow: 0 8px 25px rgba(230, 0, 18, 0.3);
}
.btn-red:hover {
box-shadow: 0 12px 35px rgba(230, 0, 18, 0.4);
}
.btn-outline {
background: transparent;
color: var(--fg);
border: 2px solid var(--border);
}
.btn-outline:hover {
border-color: rgba(255, 255, 255, 0.25);
}
.btn-large {
padding: 18px 36px;
font-size: 17px;
}
/* --- CSS Console --- */
.console-wrapper {
perspective: 800px;
opacity: 0;
transform: translateY(30px);
overflow: visible;
}
.console {
display: flex;
align-items: stretch;
transform-style: preserve-3d;
background: #1e1e2a;
border-radius: 34px;
box-shadow: 0 8px 40px rgba(0, 0, 0, 0.5);
overflow: hidden;
}
.joycon {
width: 80px;
padding: 28px 14px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
gap: 10px;
position: relative;
z-index: 1;
}
.joycon-left {
background: linear-gradient(160deg, #0ab9e6 0%, #089cc4 100%);
border-radius: 34px 0 0 34px;
border-right: 2px solid rgba(0, 0, 0, 0.2);
}
.joycon-right {
background: linear-gradient(160deg, #e60012 0%, #c2000e 100%);
border-radius: 0 34px 34px 0;
border-left: 2px solid rgba(0, 0, 0, 0.2);
}
.stick {
width: 28px;
height: 28px;
border-radius: 50%;
background: radial-gradient(circle at 40% 35%, #3a3a3a, #1a1a1a);
border: 2px solid rgba(0, 0, 0, 0.4);
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.5), 0 1px 2px rgba(255, 255, 255, 0.05);
}
.dpad {
position: relative;
width: 32px;
height: 32px;
}
.dpad-h,
.dpad-v {
position: absolute;
background: rgba(0, 0, 0, 0.35);
border-radius: 2px;
}
.dpad-h {
width: 32px;
height: 11px;
top: 10.5px;
left: 0;
}
.dpad-v {
width: 11px;
height: 32px;
top: 0;
left: 10.5px;
}
.minus-btn {
width: 14px;
height: 3px;
background: rgba(0, 0, 0, 0.35);
border-radius: 2px;
}
.capture-btn {
width: 14px;
height: 14px;
border-radius: 3px;
border: 2px solid rgba(0, 0, 0, 0.3);
}
.face-buttons {
display: grid;
grid-template-areas: ". x ." "y . a" ". b .";
gap: 3px;
}
.fb {
width: 18px;
height: 18px;
border-radius: 50%;
background: radial-gradient(circle at 40% 35%, #3a3a3a, #1a1a1a);
display: flex;
align-items: center;
justify-content: center;
font-size: 8px;
font-weight: 700;
color: rgba(255, 255, 255, 0.45);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}
.fb-y {
grid-area: y;
}
.fb-x {
grid-area: x;
}
.fb-b {
grid-area: b;
}
.fb-a {
grid-area: a;
}
.plus-btn {
font-size: 13px;
font-weight: 800;
color: rgba(0, 0, 0, 0.35);
}
.home-btn {
width: 14px;
height: 14px;
border-radius: 50%;
border: 2px solid rgba(0, 0, 0, 0.3);
}
.screen {
width: 240px;
margin: 10px 0;
background: #0a0a0f;
border: 3px solid #2a2a35;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
}
.screen-content {
text-align: center;
}
.screen-logo {
font-size: 2.5rem;
font-weight: 900;
color: var(--red);
line-height: 1;
}
.screen-text {
font-size: 0.7rem;
font-weight: 800;
color: var(--fg-muted);
letter-spacing: 0.3em;
}
@media (max-width: 480px) {
.console-wrapper {
transform: scale(0.8) translateY(30px);
}
}
/* --- Sections --- */
section {
padding: 100px 24px;
position: relative;
}
.section-container {
max-width: 1100px;
margin: 0 auto;
}
.section-header {
margin-bottom: 48px;
}
.section-header--center {
text-align: center;
}
.section-title {
font-size: clamp(2rem, 6vw, 3.5rem);
font-weight: 900;
letter-spacing: -0.03em;
line-height: 1.1;
}
.section-desc {
font-size: 1.1rem;
color: var(--fg-muted);
margin-top: 12px;
line-height: 1.5;
}
/* --- Modes --- */
.modes-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: 20px;
}
.mode-card {
background: var(--card-bg);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 36px;
text-align: center;
transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), border-color 0.3s;
}
.mode-card:hover {
transform: translateY(-8px);
border-color: rgba(255, 255, 255, 0.15);
}
.mode-card--tv .mode-icon {
color: var(--red);
}
.mode-card--tabletop .mode-icon {
color: var(--blue);
}
.mode-card--handheld .mode-icon {
color: #f5c518;
}
.mode-icon {
margin-bottom: 20px;
}
.mode-card h3 {
font-size: 1.3rem;
font-weight: 800;
margin-bottom: 8px;
}
.mode-card p {
color: var(--fg-muted);
font-size: 14px;
line-height: 1.5;
}
/* --- Games --- */
.games-row {
display: flex;
gap: 20px;
justify-content: center;
flex-wrap: wrap;
margin-top: 48px;
}
.game-card {
width: 160px;
background: var(--card-bg);
border: 1px solid var(--border);
border-radius: 16px;
overflow: hidden;
text-align: center;
transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
cursor: pointer;
}
.game-card:hover {
transform: translateY(-10px) rotate(1deg);
}
.game-cover {
height: 120px;
background: var(--card-color);
display: flex;
align-items: center;
justify-content: center;
}
.game-initial {
font-size: 3rem;
font-weight: 900;
color: rgba(255, 255, 255, 0.9);
text-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
.game-card h4 {
font-size: 0.95rem;
font-weight: 700;
margin: 12px 0 4px;
}
.game-genre {
display: block;
font-size: 12px;
color: var(--fg-muted);
margin-bottom: 12px;
}
/* --- Specs --- */
.specs-card {
background: var(--card-bg);
border: 1px solid var(--border);
border-radius: 30px;
padding: 48px;
text-align: center;
}
.specs-header {
margin-bottom: 36px;
}
.specs-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 24px;
margin-bottom: 32px;
}
.spec {
display: flex;
flex-direction: column;
gap: 4px;
}
.spec-value {
font-size: 2.2rem;
font-weight: 900;
letter-spacing: -0.03em;
}
.spec-label {
font-size: 13px;
color: var(--fg-muted);
font-weight: 600;
}
.specs-colors {
display: flex;
justify-content: center;
gap: 12px;
}
.color-dot {
width: 28px;
height: 28px;
border-radius: 50%;
border: 3px solid var(--darker);
cursor: pointer;
transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.color-dot:hover {
transform: scale(1.25);
}
.color-dot--neon-red {
background: var(--red);
}
.color-dot--neon-blue {
background: var(--blue);
}
.color-dot--white {
background: #f0f0f0;
}
.color-dot--gray {
background: #555;
}
/* --- CTA --- */
.cta-section {
min-height: 50vh;
display: flex;
align-items: center;
justify-content: center;
}
.cta-content {
text-align: center;
}
.cta-title {
font-size: clamp(2.5rem, 8vw, 5rem);
font-weight: 900;
letter-spacing: -0.03em;
margin-bottom: 12px;
}
.cta-desc {
margin: 0 auto 32px;
max-width: 400px;
}
/* --- Animations --- */
.reveal {
opacity: 0;
transform: translateY(25px);
}
/* --- Responsive --- */
@media (max-width: 768px) {
.specs-card {
padding: 32px 20px;
border-radius: 20px;
}
.games-row {
gap: 12px;
}
.game-card {
width: 130px;
}
.game-cover {
height: 90px;
}
.game-initial {
font-size: 2rem;
}
}gsap.registerPlugin(ScrollTrigger);
// --- Hero entrance with bouncy spring ---
const heroTl = gsap.timeline({
defaults: { ease: "back.out(1.7)" },
});
heroTl
.to(".hero-badge", { opacity: 1, scale: 1, duration: 0.6, delay: 0.3 })
.to(
".hero-word",
{
opacity: 1,
y: 0,
rotation: 0,
duration: 0.8,
stagger: 0.15,
},
"-=0.3"
)
.to(".hero-desc", { opacity: 1, duration: 0.6, ease: "power2.out" }, "-=0.3")
.to(".hero-actions", { opacity: 1, duration: 0.5, ease: "power2.out" }, "-=0.2")
.to(
".console-wrapper",
{
opacity: 1,
y: 0,
duration: 1,
ease: "elastic.out(1, 0.5)",
},
"-=0.5"
);
// --- Console tilt on mouse ---
const consoleEl = document.querySelector(".console");
if (consoleEl) {
document.addEventListener("mousemove", (e) => {
const x = (e.clientX / window.innerWidth - 0.5) * 2;
const y = (e.clientY / window.innerHeight - 0.5) * 2;
gsap.to(consoleEl, {
rotateY: x * 8,
rotateX: -y * 5,
duration: 0.6,
ease: "power2.out",
});
});
}
// --- Floating background shapes parallax ---
gsap.utils.toArray(".shape").forEach((shape, i) => {
gsap.to(shape, {
y: i % 2 === 0 ? 150 : -150,
x: i % 2 === 0 ? 50 : -50,
scrollTrigger: {
trigger: "body",
start: "top top",
end: "bottom bottom",
scrub: 1,
},
});
});
// --- Reveal on scroll with spring ease ---
gsap.utils.toArray(".reveal").forEach((el) => {
gsap.fromTo(
el,
{ opacity: 0, y: 25 },
{
opacity: 1,
y: 0,
duration: 0.8,
ease: "back.out(1.4)",
scrollTrigger: {
trigger: el,
start: "top 88%",
toggleActions: "play none none none",
},
}
);
});
// --- Mode cards stagger (no .reveal — dedicated animation) ---
const modesGrid = document.querySelector(".modes-grid");
if (modesGrid) {
gsap.fromTo(
".mode-card",
{ opacity: 0, y: 40, scale: 0.92 },
{
opacity: 1,
y: 0,
scale: 1,
duration: 0.8,
stagger: 0.15,
ease: "back.out(1.5)",
scrollTrigger: {
trigger: modesGrid,
start: "top 82%",
toggleActions: "play none none none",
},
}
);
}
// --- Game cards stagger with rotation (no .reveal — dedicated animation) ---
const gamesRow = document.querySelector(".games-row");
if (gamesRow) {
gsap.fromTo(
".game-card",
{ opacity: 0, y: 50, rotation: -5, scale: 0.88 },
{
opacity: 1,
y: 0,
rotation: 0,
scale: 1,
duration: 0.7,
stagger: 0.1,
ease: "back.out(1.7)",
scrollTrigger: {
trigger: gamesRow,
start: "top 82%",
toggleActions: "play none none none",
},
}
);
}
// --- Specs scale in ---
gsap.utils.toArray(".spec").forEach((spec, i) => {
gsap.fromTo(
spec,
{ opacity: 0, scale: 0.8 },
{
opacity: 1,
scale: 1,
duration: 0.6,
delay: i * 0.1,
ease: "back.out(2)",
scrollTrigger: {
trigger: ".specs-grid",
start: "top 85%",
toggleActions: "play none none none",
},
}
);
});
// --- Color dots bounce on scroll ---
gsap.fromTo(
".color-dot",
{ scale: 0 },
{
scale: 1,
duration: 0.5,
stagger: 0.08,
ease: "back.out(3)",
scrollTrigger: {
trigger: ".specs-colors",
start: "top 90%",
toggleActions: "play none none none",
},
}
);
// --- Screen glow pulse ---
const screen = document.querySelector(".screen");
if (screen) {
gsap.to(screen, {
boxShadow: "0 0 40px rgba(230, 0, 18, 0.15), inset 0 0 20px rgba(230, 0, 18, 0.05)",
duration: 2,
repeat: -1,
yoyo: true,
ease: "sine.inOut",
});
}<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Nintendo Switch — Play Anywhere</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<!-- Floating shapes background -->
<div class="bg-shapes">
<div class="shape shape-circle shape-1"></div>
<div class="shape shape-circle shape-2"></div>
<div class="shape shape-cross shape-3">+</div>
<div class="shape shape-triangle shape-4"></div>
<div class="shape shape-circle shape-5"></div>
</div>
<main>
<!-- Hero -->
<section class="hero">
<div class="hero-content">
<div class="hero-badge">NEW</div>
<h1 class="hero-title">
<span class="hero-word hero-word--red">Play.</span>
<span class="hero-word hero-word--blue">Anywhere.</span>
</h1>
<p class="hero-desc">Home console gaming in the palm of your hand. Dock it. Share it. Play it your way.</p>
<div class="hero-actions">
<button class="btn btn-red">Pre-order Now</button>
<button class="btn btn-outline">Watch Trailer</button>
</div>
</div>
<!-- CSS Console -->
<div class="console-wrapper">
<div class="console">
<div class="joycon joycon-left">
<div class="stick stick-left"></div>
<div class="dpad">
<div class="dpad-h"></div>
<div class="dpad-v"></div>
</div>
<div class="minus-btn"></div>
<div class="capture-btn"></div>
</div>
<div class="screen">
<div class="screen-content">
<div class="screen-logo">N</div>
<div class="screen-text">SWITCH</div>
</div>
</div>
<div class="joycon joycon-right">
<div class="stick stick-right"></div>
<div class="face-buttons">
<span class="fb fb-y">Y</span>
<span class="fb fb-x">X</span>
<span class="fb fb-b">B</span>
<span class="fb fb-a">A</span>
</div>
<div class="plus-btn">+</div>
<div class="home-btn"></div>
</div>
</div>
</div>
</section>
<!-- Features -->
<section class="features-section">
<div class="section-container">
<div class="reveal section-header">
<h2 class="section-title">Three Modes.<br/><span class="text-red">Infinite Fun.</span></h2>
</div>
<div class="modes-grid">
<div class="mode-card mode-card--tv">
<div class="mode-icon">
<svg width="48" height="48" 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>TV Mode</h3>
<p>Dock your Switch and play on the big screen. Up to 4K with Switch Pro.</p>
</div>
<div class="mode-card mode-card--tabletop">
<div class="mode-icon">
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<rect x="5" y="2" width="14" height="20" rx="2"/><line x1="12" y1="18" x2="12" y2="18"/>
</svg>
</div>
<h3>Tabletop Mode</h3>
<p>Prop it up, share the Joy-Con, and play together anywhere you go.</p>
</div>
<div class="mode-card mode-card--handheld">
<div class="mode-icon">
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<rect x="6" y="3" width="12" height="18" rx="2"/><path d="M12 15h.01"/>
</svg>
</div>
<h3>Handheld Mode</h3>
<p>Take your games on the go. Play your entire library anywhere.</p>
</div>
</div>
</div>
</section>
<!-- Games -->
<section class="games-section">
<div class="section-container">
<div class="reveal section-header section-header--center">
<h2 class="section-title">Legendary <span class="text-blue">Games.</span></h2>
<p class="section-desc">The best exclusives in gaming, only on Nintendo.</p>
</div>
<div class="games-row">
<div class="game-card" style="--card-color: #e60012;">
<div class="game-cover">
<div class="game-initial">M</div>
</div>
<h4>Super Mario</h4>
<span class="game-genre">Platformer</span>
</div>
<div class="game-card" style="--card-color: #00a651;">
<div class="game-cover">
<div class="game-initial">Z</div>
</div>
<h4>Zelda</h4>
<span class="game-genre">Adventure</span>
</div>
<div class="game-card" style="--card-color: #f5c518;">
<div class="game-cover">
<div class="game-initial">P</div>
</div>
<h4>Pokemon</h4>
<span class="game-genre">RPG</span>
</div>
<div class="game-card" style="--card-color: #e4007f;">
<div class="game-cover">
<div class="game-initial">K</div>
</div>
<h4>Kirby</h4>
<span class="game-genre">Platformer</span>
</div>
<div class="game-card" style="--card-color: #ff6600;">
<div class="game-cover">
<div class="game-initial">S</div>
</div>
<h4>Splatoon</h4>
<span class="game-genre">Shooter</span>
</div>
</div>
</div>
</section>
<!-- Specs -->
<section class="specs-section">
<div class="section-container">
<div class="specs-card reveal">
<div class="specs-header">
<h2 class="section-title">Built to <span class="text-red">Play.</span></h2>
</div>
<div class="specs-grid">
<div class="spec">
<span class="spec-value">7"</span>
<span class="spec-label">OLED Display</span>
</div>
<div class="spec">
<span class="spec-value">9h</span>
<span class="spec-label">Battery Life</span>
</div>
<div class="spec">
<span class="spec-value">64GB</span>
<span class="spec-label">Internal Storage</span>
</div>
<div class="spec">
<span class="spec-value">Wi-Fi 6</span>
<span class="spec-label">Online Play</span>
</div>
</div>
<div class="specs-colors">
<div class="color-dot color-dot--neon-red"></div>
<div class="color-dot color-dot--neon-blue"></div>
<div class="color-dot color-dot--white"></div>
<div class="color-dot color-dot--gray"></div>
</div>
</div>
</div>
</section>
<!-- CTA -->
<section class="cta-section">
<div class="section-container cta-content reveal">
<h2 class="cta-title">Ready to <span class="text-red">Play</span>?</h2>
<p class="section-desc cta-desc">Join millions of players worldwide.</p>
<button class="btn btn-red btn-large">Get Yours Now</button>
</div>
</section>
</main>
<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="./script.js"></script>
</body>
</html>Nintendo UHD Console Showcase Page
A premium console showcase inspired by Nintendo’s iconic design: vibrant primary colors, rounded shapes, bouncy spring physics, and an overwhelming sense of joy and fun.
Core Features
- Joy-Con Color System — Neon red and blue accent colors inspired by the Switch Joy-Con controllers.
- Bouncy Spring Animations — Every element enters with a playful spring ease, conveying Nintendo’s signature “fun” energy.
- CSS-only Console — Full Switch console rendered in pure CSS with Joy-Con details.
- Parallax Game Cards — Floating game cards with depth and tilt effects on scroll.
- Playful Typography — Rounded, bold type with color shifts and subtle rotation.
Design Principles
- Joy First — Every interaction should feel fun and inviting, like picking up a controller.
- Color as Identity — Red and blue are not decoration; they are the brand.
- Rounded Everything — Sharp corners are banned. Everything feels soft, friendly, and touchable.