Pages Medium
Portfolio Case Study Page
A single project case study page with hero, overview stats, problem/solution sections, image gallery, and results metrics. Pure CSS.
Open in Lab
MCP
css
Targets: JS HTML
Code
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
background: #fff;
color: #111;
}
.site-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 18px 40px;
border-bottom: 1px solid #e5e7eb;
position: sticky;
top: 0;
background: #fff;
z-index: 10;
}
.logo {
font-size: 20px;
font-weight: 800;
text-decoration: none;
color: #111;
}
nav {
display: flex;
gap: 24px;
align-items: center;
}
nav a {
font-size: 14px;
color: #555;
text-decoration: none;
}
nav a.nav-cta {
color: #6366f1;
font-weight: 600;
}
/* Hero */
.hero {
max-width: 900px;
margin: 80px auto 0;
padding: 0 40px;
}
.hero-meta {
display: flex;
gap: 8px;
flex-wrap: wrap;
margin-bottom: 20px;
}
.tag {
display: inline-block;
padding: 4px 12px;
background: #f3f4f6;
color: #555;
border-radius: 20px;
font-size: 12px;
font-weight: 600;
}
.hero h1 {
font-size: clamp(28px, 5vw, 52px);
font-weight: 900;
line-height: 1.15;
margin-bottom: 20px;
}
.hero p {
font-size: 18px;
color: #555;
line-height: 1.6;
margin-bottom: 40px;
}
.hero-cover {
height: 440px;
border-radius: 20px;
background: linear-gradient(135deg, #0f0f13 0%, #1e1b4b 50%, #312e81 100%);
position: relative;
overflow: hidden;
}
.hero-cover::after {
content: "";
position: absolute;
inset: 40px;
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 12px;
background: rgba(255, 255, 255, 0.03);
}
/* Overview */
.overview {
max-width: 900px;
margin: 60px auto;
padding: 0 40px;
}
.overview-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1px;
background: #e5e7eb;
border: 1px solid #e5e7eb;
border-radius: 16px;
overflow: hidden;
}
@media (max-width: 600px) {
.overview-grid {
grid-template-columns: 1fr 1fr;
}
}
.overview-item {
background: #fff;
padding: 20px 24px;
display: flex;
flex-direction: column;
gap: 6px;
}
.ov-label {
font-size: 11px;
font-weight: 700;
color: #888;
text-transform: uppercase;
letter-spacing: 0.06em;
}
.overview-item strong {
font-size: 15px;
color: #111;
}
/* Case sections */
.case-section {
max-width: 900px;
margin: 0 auto 60px;
padding: 0 40px;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 48px;
align-items: center;
}
.case-section.alt {
background: #f9fafb;
padding: 60px 40px;
max-width: 100%;
}
.case-section.alt .case-content {
max-width: 900px;
margin: 0 auto;
grid-column: 1 / -1;
}
@media (max-width: 768px) {
.case-section {
grid-template-columns: 1fr;
}
}
.section-label {
font-size: 12px;
font-weight: 700;
color: #6366f1;
text-transform: uppercase;
letter-spacing: 0.08em;
margin-bottom: 12px;
}
.case-content h2 {
font-size: 28px;
font-weight: 800;
margin-bottom: 20px;
}
.case-content p {
font-size: 16px;
color: #555;
line-height: 1.8;
margin-bottom: 14px;
}
.case-content ul {
padding-left: 20px;
display: flex;
flex-direction: column;
gap: 8px;
}
.case-content li {
font-size: 16px;
color: #555;
line-height: 1.6;
}
.case-callout {
display: flex;
flex-direction: column;
gap: 24px;
}
.callout-stat {
padding: 24px;
background: #0f0f13;
border-radius: 16px;
color: #fff;
}
.callout-stat span {
font-size: 44px;
font-weight: 900;
color: #a5b4fc;
display: block;
margin-bottom: 8px;
}
.callout-stat p {
font-size: 14px;
color: #888;
line-height: 1.5;
}
/* Gallery */
.gallery-section {
max-width: 900px;
margin: 0 auto 80px;
padding: 0 40px;
}
.gallery-label {
font-size: 12px;
font-weight: 700;
color: #6366f1;
text-transform: uppercase;
letter-spacing: 0.08em;
margin-bottom: 12px;
}
.gallery-section h2 {
font-size: 28px;
font-weight: 800;
margin-bottom: 28px;
}
.mockup-grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: auto auto;
gap: 14px;
}
.mockup {
border-radius: 12px;
height: 180px;
}
.mockup.wide {
grid-column: 1 / -1;
height: 220px;
}
.m1 {
background: linear-gradient(135deg, #6366f1, #8b5cf6);
}
.m2 {
background: linear-gradient(135deg, #0ea5e9, #6366f1);
}
.m3 {
background: linear-gradient(135deg, #10b981, #0ea5e9);
}
.m4 {
background: linear-gradient(135deg, #0f0f13, #312e81);
}
/* Results */
.results-section {
background: #0f0f13;
padding: 80px 40px;
text-align: center;
}
.results-section .section-label {
color: #a5b4fc;
}
.results-section h2 {
font-size: 32px;
font-weight: 800;
color: #fff;
margin-bottom: 48px;
}
.results-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 24px;
max-width: 900px;
margin: 0 auto;
}
@media (max-width: 768px) {
.results-grid {
grid-template-columns: 1fr 1fr;
}
}
.result-card {
padding: 32px 16px;
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 16px;
}
.result-num {
font-size: 56px;
font-weight: 900;
color: #fff;
line-height: 1;
display: inline;
}
.result-unit {
font-size: 32px;
font-weight: 900;
color: #a5b4fc;
display: inline;
}
.result-card p {
font-size: 13px;
color: #888;
margin-top: 10px;
line-height: 1.5;
}
/* Next section */
.next-section {
padding: 64px 40px;
text-align: center;
border-top: 1px solid #f3f4f6;
}
.next-label {
font-size: 12px;
font-weight: 700;
color: #888;
text-transform: uppercase;
letter-spacing: 0.06em;
display: block;
margin-bottom: 12px;
}
.next-link {
font-size: clamp(20px, 4vw, 36px);
font-weight: 900;
color: #111;
text-decoration: none;
border-bottom: 3px solid #6366f1;
padding-bottom: 4px;
transition: color 0.2s;
}
.next-link:hover {
color: #6366f1;
}// Animate result counters when they enter the viewport
const resultNums = document.querySelectorAll(".result-num");
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) return;
const el = entry.target;
const target = parseFloat(el.dataset.target);
const isDecimal = !Number.isInteger(target);
const duration = 1200;
const start = performance.now();
function tick(now) {
const elapsed = now - start;
const progress = Math.min(elapsed / duration, 1);
const eased = 1 - Math.pow(1 - progress, 3);
const value = target * eased;
el.textContent = isDecimal ? value.toFixed(1) : Math.floor(value);
if (progress < 1) requestAnimationFrame(tick);
}
requestAnimationFrame(tick);
observer.unobserve(el);
});
},
{ threshold: 0.3 }
);
resultNums.forEach((el) => observer.observe(el));<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="style.css" />
<title>Case Study — Brand Redesign</title>
</head>
<body>
<header class="site-header">
<a href="#" class="logo">Portfolio</a>
<nav><a href="#">Work</a><a href="#">About</a><a href="#" class="nav-cta">Contact</a></nav>
</header>
<!-- Hero -->
<section class="hero">
<div class="hero-meta">
<span class="tag">UX Design</span>
<span class="tag">Branding</span>
<span class="tag">2026</span>
</div>
<h1>Brand Redesign: From Confusion to Clarity</h1>
<p>A complete redesign of a SaaS dashboard serving 50,000 users — reducing onboarding drop-off by 42%.</p>
<div class="hero-cover"></div>
</section>
<!-- Overview -->
<section class="overview">
<div class="overview-grid">
<div class="overview-item"><span class="ov-label">Client</span><strong>Acme SaaS Inc.</strong></div>
<div class="overview-item"><span class="ov-label">Timeline</span><strong>12 weeks</strong></div>
<div class="overview-item"><span class="ov-label">My Role</span><strong>Lead Designer</strong></div>
<div class="overview-item"><span class="ov-label">Team</span><strong>4 people</strong></div>
<div class="overview-item"><span class="ov-label">Tools</span><strong>Figma, Framer</strong></div>
<div class="overview-item"><span class="ov-label">Deliverables</span><strong>Design system, prototypes</strong></div>
</div>
</section>
<!-- Challenge -->
<section class="case-section">
<div class="case-content">
<div class="section-label">01 — Challenge</div>
<h2>The Problem</h2>
<p>The original dashboard had grown organically over 5 years without a coherent design vision. Users described it as "overwhelming", "confusing", and "hard to find anything in." New users took an average of 18 minutes to complete their first key action.</p>
<p>The goal was clear: redesign the core experience to reduce time-to-value and improve retention in the critical first 30 days.</p>
</div>
<div class="case-callout">
<div class="callout-stat"><span>18 min</span><p>Average time to first key action</p></div>
<div class="callout-stat"><span>61%</span><p>Onboarding drop-off rate</p></div>
</div>
</section>
<!-- Solution -->
<section class="case-section alt">
<div class="case-content">
<div class="section-label">02 — Solution</div>
<h2>The Approach</h2>
<p>We started with 3 weeks of user research — 24 interviews, 200 survey responses, and 40 session recordings. The core insight: users weren't failing because the features didn't exist; they couldn't find them.</p>
<p>The redesign focused on three pillars:</p>
<ul>
<li><strong>Progressive disclosure</strong> — show only what's needed at each stage</li>
<li><strong>Contextual guidance</strong> — inline hints, not modal tutorials</li>
<li><strong>Consistent patterns</strong> — one way to do each type of action</li>
</ul>
</div>
</section>
<!-- Gallery -->
<section class="gallery-section">
<div class="gallery-label">03 — Mockups</div>
<h2>Selected Screens</h2>
<div class="mockup-grid">
<div class="mockup m1"></div>
<div class="mockup m2"></div>
<div class="mockup m3"></div>
<div class="mockup m4 wide"></div>
</div>
</section>
<!-- Results -->
<section class="results-section">
<div class="section-label">04 — Results</div>
<h2>Impact</h2>
<div class="results-grid">
<div class="result-card">
<div class="result-num" data-target="42">0</div>
<div class="result-unit">%</div>
<p>Reduction in onboarding drop-off</p>
</div>
<div class="result-card">
<div class="result-num" data-target="67">0</div>
<div class="result-unit">%</div>
<p>Faster time to first key action</p>
</div>
<div class="result-card">
<div class="result-num" data-target="28">0</div>
<div class="result-unit">%</div>
<p>Improvement in 30-day retention</p>
</div>
<div class="result-card">
<div class="result-num" data-target="4.8">0</div>
<div class="result-unit">★</div>
<p>App store rating after relaunch</p>
</div>
</div>
</section>
<!-- Next project -->
<section class="next-section">
<span class="next-label">Next Project →</span>
<a href="#" class="next-link">Mobile Banking App Redesign</a>
</section>
<script src="script.js"></script>
</body>
</html>Portfolio Case Study Page
A single-project case study page with the editorial layout common in design portfolios: full-bleed hero, project metadata, challenge/solution prose sections, a mockup gallery, and a results stats row.
Sections
- Hero — project title, tag, and cover image
- Overview — client, timeline, role, tech stack
- Challenge — problem statement
- Solution — approach and key decisions
- Gallery — 3-column mockup grid
- Results — animated metric counters
- Next project — navigation to the next case study
When to use it
- Designer / developer portfolio sites
- Agency project showcase pages
- Freelance work presentations