6 CSS Minimalist UI Designs03 / 06
Vera Lindstrom Portfolio
A brutalist-white minimalist portfolio UI for a Stockholm-based art director — a gallery-wall approach where the interface disappears so the creative work takes center stage. Sticky header with serif name + uppercase nav + green-dotted availability status, a giant typographic index letter "V" sitting half-revealed behind a Playfair Display hero headline (Visual / *Architect* / & Director), a numbered "Selected Work" project list where each row slides a cream fill in from the left on hover with a 45-degree rotating arrow and per-project SVG color preview card that follows the cursor, a two-column "About / Disciplines" strip with a numbered service index, and a giant italic contact email that animates letter-spacing on hover. Typography pairs Playfair Display (display) with IBM Plex Sans (UI). Best for designer portfolios, photographer sites, architect studios, art director landing pages, creative agency homepages.
Published
The code
<section class="mu-pf" aria-label="Vera Lindstrom creative portfolio demo">
<div class="preview-img" data-mu-pf-preview aria-hidden="true">
<svg data-mu-pf-preview-svg width="320" height="220" viewBox="0 0 320 220"></svg>
</div>
<header class="header">
<div class="h-name">Vera Lindström</div>
<nav class="h-nav">
<a href="#">Work</a>
<a href="#">About</a>
<a href="#">Journal</a>
<a href="#">Contact</a>
</nav>
<div class="h-status">
<div class="status-dot" aria-hidden="true"></div>
Available for projects
</div>
</header>
<section class="hero">
<div class="hero-index" aria-hidden="true">V</div>
<div class="hero-text">
<h1 class="hero-title">
Visual<br><em>Architect</em><br>& Director
</h1>
<div class="hero-meta">
<div class="hero-role">Art Direction · Branding · UI</div>
<p class="hero-desc">Building brand identities and digital experiences that earn their silence. Stockholm-based, globally engaged.</p>
</div>
</div>
<div class="hero-scroll-indicator" aria-hidden="true">
<div class="scroll-v-line"></div>
<div class="scroll-v-txt">Scroll</div>
</div>
</section>
<section class="work-section">
<div class="section-rule">
<span class="rule-num">01</span>
<div class="rule-line"></div>
<span class="rule-label">Selected Work</span>
</div>
<div class="project-list">
<div class="project-item" data-color="#1a1714" data-color2="#3a3028" data-accent="#c8ff00">
<div class="project-num">001</div>
<div class="project-info">
<div class="project-title">Maison Collective</div>
<div class="project-tags">
<span class="tag">Brand Identity</span>
<span class="tag">·</span>
<span class="tag">Art Direction</span>
</div>
</div>
<div class="project-right">
<span class="project-year">2025</span>
<div class="project-arrow">→</div>
</div>
</div>
<div class="project-item" data-color="#d4c4a8" data-color2="#b8a080" data-accent="#8a6040">
<div class="project-num">002</div>
<div class="project-info">
<div class="project-title">Aether Digital</div>
<div class="project-tags">
<span class="tag">Product UI</span>
<span class="tag">·</span>
<span class="tag">Design System</span>
</div>
</div>
<div class="project-right">
<span class="project-year">2025</span>
<div class="project-arrow">→</div>
</div>
</div>
<div class="project-item" data-color="#2c4a3e" data-color2="#1a3028" data-accent="#a8d4b8">
<div class="project-num">003</div>
<div class="project-info">
<div class="project-title"><em>Forma</em> Architecture</div>
<div class="project-tags">
<span class="tag">Photography</span>
<span class="tag">·</span>
<span class="tag">Editorial</span>
</div>
</div>
<div class="project-right">
<span class="project-year">2024</span>
<div class="project-arrow">→</div>
</div>
</div>
<div class="project-item" data-color="#8b6a3a" data-color2="#6a4a20" data-accent="#f0c880">
<div class="project-num">004</div>
<div class="project-info">
<div class="project-title">Norde Finance</div>
<div class="project-tags">
<span class="tag">Motion</span>
<span class="tag">·</span>
<span class="tag">Campaign</span>
</div>
</div>
<div class="project-right">
<span class="project-year">2024</span>
<div class="project-arrow">→</div>
</div>
</div>
<div class="project-item" data-color="#4a3858" data-color2="#2a1838" data-accent="#d4a8f0">
<div class="project-num">005</div>
<div class="project-info">
<div class="project-title">Lune Editorial</div>
<div class="project-tags">
<span class="tag">Publication</span>
<span class="tag">·</span>
<span class="tag">Typography</span>
</div>
</div>
<div class="project-right">
<span class="project-year">2024</span>
<div class="project-arrow">→</div>
</div>
</div>
</div>
</section>
<div class="about-strip">
<div class="about-left">
<div class="about-eyebrow">About the Practice</div>
<h2 class="about-title">Design that<br>trusts the <em>void</em></h2>
<p class="about-body">With fifteen years across Stockholm, London, and Tokyo, I've learned that the most memorable work is often the most restrained. I collaborate with founders, cultural institutions, and agencies to craft visual systems that hold their integrity across every surface.</p>
</div>
<div class="about-right">
<div class="about-eyebrow">Disciplines</div>
<div class="services-list">
<div class="service-item"><span class="svc-num">—</span><span class="svc-name">Brand Identity & Systems</span><span class="svc-type">Strategy · Visual</span></div>
<div class="service-item"><span class="svc-num">—</span><span class="svc-name">Digital Product Design</span><span class="svc-type">UI · UX · Prototyping</span></div>
<div class="service-item"><span class="svc-num">—</span><span class="svc-name">Art Direction</span><span class="svc-type">Photo · Film · Print</span></div>
<div class="service-item"><span class="svc-num">—</span><span class="svc-name">Editorial Design</span><span class="svc-type">Books · Magazines</span></div>
<div class="service-item"><span class="svc-num">—</span><span class="svc-name">Motion & Campaign</span><span class="svc-type">Digital · Out-of-home</span></div>
</div>
</div>
</div>
<div class="contact-section">
<div class="contact-label">Start a conversation</div>
<a class="contact-email" href="#">vera@lindstrom.studio</a>
<div class="contact-links">
<a class="contact-link" href="#">Instagram</a>
<a class="contact-link" href="#">LinkedIn</a>
<a class="contact-link" href="#">Are.na</a>
<a class="contact-link" href="#">Readcv</a>
</div>
</div>
<footer class="footer">
<span>© 2025 Vera Lindström Studio</span>
<span>Stockholm · SE</span>
<span>Currently: Available Q3 2025</span>
</footer>
</section><section class="mu-pf" aria-label="Vera Lindstrom creative portfolio demo">
<div class="preview-img" data-mu-pf-preview aria-hidden="true">
<svg data-mu-pf-preview-svg width="320" height="220" viewBox="0 0 320 220"></svg>
</div>
<header class="header">
<div class="h-name">Vera Lindström</div>
<nav class="h-nav">
<a href="#">Work</a>
<a href="#">About</a>
<a href="#">Journal</a>
<a href="#">Contact</a>
</nav>
<div class="h-status">
<div class="status-dot" aria-hidden="true"></div>
Available for projects
</div>
</header>
<section class="hero">
<div class="hero-index" aria-hidden="true">V</div>
<div class="hero-text">
<h1 class="hero-title">
Visual<br><em>Architect</em><br>& Director
</h1>
<div class="hero-meta">
<div class="hero-role">Art Direction · Branding · UI</div>
<p class="hero-desc">Building brand identities and digital experiences that earn their silence. Stockholm-based, globally engaged.</p>
</div>
</div>
<div class="hero-scroll-indicator" aria-hidden="true">
<div class="scroll-v-line"></div>
<div class="scroll-v-txt">Scroll</div>
</div>
</section>
<section class="work-section">
<div class="section-rule">
<span class="rule-num">01</span>
<div class="rule-line"></div>
<span class="rule-label">Selected Work</span>
</div>
<div class="project-list">
<div class="project-item" data-color="#1a1714" data-color2="#3a3028" data-accent="#c8ff00">
<div class="project-num">001</div>
<div class="project-info">
<div class="project-title">Maison Collective</div>
<div class="project-tags">
<span class="tag">Brand Identity</span>
<span class="tag">·</span>
<span class="tag">Art Direction</span>
</div>
</div>
<div class="project-right">
<span class="project-year">2025</span>
<div class="project-arrow">→</div>
</div>
</div>
<div class="project-item" data-color="#d4c4a8" data-color2="#b8a080" data-accent="#8a6040">
<div class="project-num">002</div>
<div class="project-info">
<div class="project-title">Aether Digital</div>
<div class="project-tags">
<span class="tag">Product UI</span>
<span class="tag">·</span>
<span class="tag">Design System</span>
</div>
</div>
<div class="project-right">
<span class="project-year">2025</span>
<div class="project-arrow">→</div>
</div>
</div>
<div class="project-item" data-color="#2c4a3e" data-color2="#1a3028" data-accent="#a8d4b8">
<div class="project-num">003</div>
<div class="project-info">
<div class="project-title"><em>Forma</em> Architecture</div>
<div class="project-tags">
<span class="tag">Photography</span>
<span class="tag">·</span>
<span class="tag">Editorial</span>
</div>
</div>
<div class="project-right">
<span class="project-year">2024</span>
<div class="project-arrow">→</div>
</div>
</div>
<div class="project-item" data-color="#8b6a3a" data-color2="#6a4a20" data-accent="#f0c880">
<div class="project-num">004</div>
<div class="project-info">
<div class="project-title">Norde Finance</div>
<div class="project-tags">
<span class="tag">Motion</span>
<span class="tag">·</span>
<span class="tag">Campaign</span>
</div>
</div>
<div class="project-right">
<span class="project-year">2024</span>
<div class="project-arrow">→</div>
</div>
</div>
<div class="project-item" data-color="#4a3858" data-color2="#2a1838" data-accent="#d4a8f0">
<div class="project-num">005</div>
<div class="project-info">
<div class="project-title">Lune Editorial</div>
<div class="project-tags">
<span class="tag">Publication</span>
<span class="tag">·</span>
<span class="tag">Typography</span>
</div>
</div>
<div class="project-right">
<span class="project-year">2024</span>
<div class="project-arrow">→</div>
</div>
</div>
</div>
</section>
<div class="about-strip">
<div class="about-left">
<div class="about-eyebrow">About the Practice</div>
<h2 class="about-title">Design that<br>trusts the <em>void</em></h2>
<p class="about-body">With fifteen years across Stockholm, London, and Tokyo, I've learned that the most memorable work is often the most restrained. I collaborate with founders, cultural institutions, and agencies to craft visual systems that hold their integrity across every surface.</p>
</div>
<div class="about-right">
<div class="about-eyebrow">Disciplines</div>
<div class="services-list">
<div class="service-item"><span class="svc-num">—</span><span class="svc-name">Brand Identity & Systems</span><span class="svc-type">Strategy · Visual</span></div>
<div class="service-item"><span class="svc-num">—</span><span class="svc-name">Digital Product Design</span><span class="svc-type">UI · UX · Prototyping</span></div>
<div class="service-item"><span class="svc-num">—</span><span class="svc-name">Art Direction</span><span class="svc-type">Photo · Film · Print</span></div>
<div class="service-item"><span class="svc-num">—</span><span class="svc-name">Editorial Design</span><span class="svc-type">Books · Magazines</span></div>
<div class="service-item"><span class="svc-num">—</span><span class="svc-name">Motion & Campaign</span><span class="svc-type">Digital · Out-of-home</span></div>
</div>
</div>
</div>
<div class="contact-section">
<div class="contact-label">Start a conversation</div>
<a class="contact-email" href="#">vera@lindstrom.studio</a>
<div class="contact-links">
<a class="contact-link" href="#">Instagram</a>
<a class="contact-link" href="#">LinkedIn</a>
<a class="contact-link" href="#">Are.na</a>
<a class="contact-link" href="#">Readcv</a>
</div>
</div>
<footer class="footer">
<span>© 2025 Vera Lindström Studio</span>
<span>Stockholm · SE</span>
<span>Currently: Available Q3 2025</span>
</footer>
</section>/* ─── 03 Vera Lindström — minimalist creative portfolio UI ─────── */
@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,700;0,900;1,400;1,700&family=IBM+Plex+Sans:wght@300;400&display=swap');
.mu-pf {
--mu-pf-white: #fafafa;
--mu-pf-off: #f2f0ec;
--mu-pf-ink: #0f0f0f;
--mu-pf-mid: #888;
--mu-pf-light: #ccc;
--mu-pf-rule: #e8e4de;
--mu-pf-serif: 'Playfair Display', serif;
--mu-pf-sans: 'IBM Plex Sans', sans-serif;
position: relative;
width: 100%;
min-height: 1400px;
background: var(--mu-pf-white);
color: var(--mu-pf-ink);
font-family: var(--mu-pf-sans);
overflow-x: hidden;
box-sizing: border-box;
}
.mu-pf *,
.mu-pf *::before,
.mu-pf *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.mu-pf .header {
position: sticky;
top: 0;
z-index: 10;
background: var(--mu-pf-white);
display: flex;
align-items: center;
justify-content: space-between;
padding: 28px 56px;
}
.mu-pf .h-name {
font-family: var(--mu-pf-serif);
font-size: 18px;
font-weight: 400;
letter-spacing: 0.02em;
}
.mu-pf .h-nav {
display: flex;
gap: 36px;
}
.mu-pf .h-nav a {
font-size: 11px;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--mu-pf-mid);
text-decoration: none;
transition: color 0.2s;
}
.mu-pf .h-nav a:hover {
color: var(--mu-pf-ink);
}
.mu-pf .h-status {
font-size: 11px;
letter-spacing: 0.12em;
color: var(--mu-pf-mid);
display: flex;
align-items: center;
gap: 8px;
}
.mu-pf .status-dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: #4caf50;
animation: mu-pf-blink 2s infinite;
}
@keyframes mu-pf-blink {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.3;
}
}
.mu-pf .hero {
min-height: 540px;
display: flex;
flex-direction: column;
justify-content: flex-end;
padding: 0 56px 64px;
position: relative;
}
.mu-pf .hero-index {
position: absolute;
top: 50%;
left: 56px;
transform: translateY(-50%);
font-family: var(--mu-pf-serif);
font-size: clamp(160px,18vw,260px);
font-weight: 900;
color: var(--mu-pf-off);
line-height: 1;
letter-spacing: -0.05em;
user-select: none;
pointer-events: none;
}
.mu-pf .hero-text {
position: relative;
z-index: 2;
display: grid;
grid-template-columns: 1fr auto;
align-items: flex-end;
gap: 64px;
padding-top: 180px;
}
.mu-pf .hero-title {
font-family: var(--mu-pf-serif);
font-size: clamp(52px,7vw,96px);
font-weight: 400;
line-height: 1.05;
letter-spacing: -0.02em;
animation: mu-pf-fadein 1s ease 0.2s both;
}
.mu-pf .hero-title em {
font-style: italic;
font-weight: 400;
}
.mu-pf .hero-meta {
text-align: right;
max-width: 260px;
animation: mu-pf-fadein 1s ease 0.4s both;
}
.mu-pf .hero-role {
font-size: 11px;
letter-spacing: 0.2em;
text-transform: uppercase;
color: var(--mu-pf-mid);
margin-bottom: 14px;
}
.mu-pf .hero-desc {
font-size: 13px;
line-height: 1.8;
color: var(--mu-pf-mid);
font-weight: 300;
}
.mu-pf .hero-scroll-indicator {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
position: absolute;
right: 56px;
bottom: 64px;
}
.mu-pf .scroll-v-line {
width: 1px;
height: 60px;
background: var(--mu-pf-light);
animation: mu-pf-scrollline 2s ease infinite;
}
@keyframes mu-pf-scrollline {
0% {
transform: scaleY(0);
transform-origin: top;
}
50% {
transform: scaleY(1);
transform-origin: top;
}
51% {
transform: scaleY(1);
transform-origin: bottom;
}
100% {
transform: scaleY(0);
transform-origin: bottom;
}
}
.mu-pf .scroll-v-txt {
font-size: 9px;
letter-spacing: 0.2em;
color: var(--mu-pf-light);
text-transform: uppercase;
writing-mode: vertical-rl;
transform: rotate(180deg);
}
@keyframes mu-pf-fadein {
from {
opacity: 0;
transform: translateY(16px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.mu-pf .work-section {
padding: 0 56px 120px;
}
.mu-pf .section-rule {
display: flex;
align-items: center;
gap: 24px;
padding: 64px 0 48px;
}
.mu-pf .rule-num {
font-family: var(--mu-pf-serif);
font-size: 11px;
color: var(--mu-pf-mid);
font-style: italic;
}
.mu-pf .rule-line {
flex: 1;
height: 1px;
background: var(--mu-pf-light);
}
.mu-pf .rule-label {
font-size: 10px;
letter-spacing: 0.25em;
text-transform: uppercase;
color: var(--mu-pf-mid);
}
.mu-pf .project-list {
display: flex;
flex-direction: column;
gap: 0;
}
.mu-pf .project-item {
display: grid;
grid-template-columns: 80px 1fr auto;
align-items: center;
gap: 32px;
padding: 28px 0;
border-bottom: 1px solid var(--mu-pf-rule);
cursor: pointer;
position: relative;
overflow: hidden;
transition: padding 0.3s ease;
}
.mu-pf .project-item:first-child {
border-top: 1px solid var(--mu-pf-rule);
}
.mu-pf .project-item::before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 0;
background: var(--mu-pf-off);
z-index: 0;
transition: width 0.4s cubic-bezier(0.23,1,0.32,1);
}
.mu-pf .project-item:hover::before {
width: 100%;
}
.mu-pf .project-item:hover {
padding-left: 24px;
}
.mu-pf .project-item:hover .project-title {
letter-spacing: 0.01em;
}
.mu-pf .project-num {
font-family: var(--mu-pf-serif);
font-size: 13px;
color: var(--mu-pf-light);
font-style: italic;
position: relative;
z-index: 1;
}
.mu-pf .project-info {
position: relative;
z-index: 1;
}
.mu-pf .project-title {
font-family: var(--mu-pf-serif);
font-size: clamp(24px,3.5vw,42px);
font-weight: 400;
line-height: 1.1;
transition: letter-spacing 0.3s;
}
.mu-pf .project-tags {
display: flex;
gap: 12px;
margin-top: 6px;
}
.mu-pf .tag {
font-size: 10px;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--mu-pf-mid);
}
.mu-pf .project-right {
display: flex;
align-items: center;
gap: 32px;
position: relative;
z-index: 1;
}
.mu-pf .project-year {
font-size: 12px;
color: var(--mu-pf-mid);
font-family: var(--mu-pf-sans);
}
.mu-pf .project-arrow {
width: 44px;
height: 44px;
border: 1px solid var(--mu-pf-light);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
color: var(--mu-pf-mid);
transition: all 0.3s;
}
.mu-pf .project-item:hover .project-arrow {
background: var(--mu-pf-ink);
border-color: var(--mu-pf-ink);
color: var(--mu-pf-white);
transform: rotate(45deg);
}
/* Hover SVG preview — positioned absolute inside the wrapper, follows
the mouse via offsetX/offsetY computed against the wrapper. */
.mu-pf .preview-img {
position: absolute;
pointer-events: none;
z-index: 50;
width: 320px;
height: 220px;
opacity: 0;
transform: translateY(10px) rotate(-2deg);
transition: opacity 0.3s, transform 0.3s;
border-radius: 2px;
overflow: hidden;
top: 0;
left: 0;
}
.mu-pf .preview-img.visible {
opacity: 1;
transform: translateY(0) rotate(-1deg);
}
.mu-pf .about-strip {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0;
margin: 0 56px;
border-top: 1px solid var(--mu-pf-rule);
padding: 80px 0;
}
.mu-pf .about-left {
padding-right: 80px;
border-right: 1px solid var(--mu-pf-rule);
}
.mu-pf .about-right {
padding-left: 80px;
}
.mu-pf .about-eyebrow {
font-size: 10px;
letter-spacing: 0.25em;
text-transform: uppercase;
color: var(--mu-pf-mid);
margin-bottom: 20px;
}
.mu-pf .about-title {
font-family: var(--mu-pf-serif);
font-size: clamp(32px,4vw,52px);
font-weight: 400;
line-height: 1.15;
margin-bottom: 24px;
}
.mu-pf .about-title em {
font-style: italic;
}
.mu-pf .about-body {
font-size: 13.5px;
line-height: 1.9;
color: var(--mu-pf-mid);
font-weight: 300;
max-width: 400px;
}
.mu-pf .services-list {
display: flex;
flex-direction: column;
gap: 16px;
}
.mu-pf .service-item {
display: flex;
align-items: baseline;
gap: 16px;
padding-bottom: 16px;
border-bottom: 1px solid #ece8e2;
}
.mu-pf .service-item:last-child {
border-bottom: none;
padding-bottom: 0;
}
.mu-pf .svc-num {
font-family: var(--mu-pf-serif);
font-size: 11px;
color: var(--mu-pf-light);
font-style: italic;
min-width: 24px;
}
.mu-pf .svc-name {
font-size: 14px;
font-weight: 400;
}
.mu-pf .svc-type {
margin-left: auto;
font-size: 10px;
letter-spacing: 0.1em;
color: var(--mu-pf-mid);
}
.mu-pf .contact-section {
padding: 80px 56px;
text-align: center;
border-top: 1px solid var(--mu-pf-rule);
}
.mu-pf .contact-label {
font-size: 10px;
letter-spacing: 0.3em;
text-transform: uppercase;
color: var(--mu-pf-mid);
margin-bottom: 24px;
}
.mu-pf .contact-email {
font-family: var(--mu-pf-serif);
font-size: clamp(36px,6vw,80px);
font-weight: 400;
font-style: italic;
text-decoration: none;
color: var(--mu-pf-ink);
display: inline-block;
transition: letter-spacing 0.4s;
}
.mu-pf .contact-email:hover {
letter-spacing: 0.02em;
}
.mu-pf .contact-links {
display: flex;
justify-content: center;
gap: 40px;
margin-top: 40px;
}
.mu-pf .contact-link {
font-size: 11px;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--mu-pf-mid);
text-decoration: none;
transition: color 0.2s;
}
.mu-pf .contact-link:hover {
color: var(--mu-pf-ink);
}
.mu-pf .footer {
display: flex;
justify-content: space-between;
align-items: center;
padding: 28px 56px;
border-top: 1px solid var(--mu-pf-rule);
}
.mu-pf .footer span {
font-size: 11px;
color: var(--mu-pf-mid);
}
@media (max-width: 760px) {
.mu-pf .header,
.mu-pf .hero,
.mu-pf .work-section,
.mu-pf .contact-section,
.mu-pf .footer {
padding-left: 24px;
padding-right: 24px;
}
.mu-pf .h-nav {
display: none;
}
.mu-pf .hero-text {
grid-template-columns: 1fr;
gap: 32px;
}
.mu-pf .hero-meta {
text-align: left;
}
.mu-pf .hero-scroll-indicator {
display: none;
}
.mu-pf .about-strip {
grid-template-columns: 1fr;
margin: 0 24px;
}
.mu-pf .about-left {
padding-right: 0;
border-right: none;
border-bottom: 1px solid var(--mu-pf-rule);
padding-bottom: 48px;
margin-bottom: 48px;
}
.mu-pf .about-right {
padding-left: 0;
}
.mu-pf .footer {
flex-direction: column;
gap: 12px;
}
}
@media (prefers-reduced-motion: reduce) {
.mu-pf .status-dot,
.mu-pf .scroll-v-line,
.mu-pf .hero-title,
.mu-pf .hero-meta {
animation: none !important;
}
.mu-pf .project-item,
.mu-pf .project-arrow,
.mu-pf .preview-img {
transition: none !important;
}
}/* ─── 03 Vera Lindström — minimalist creative portfolio UI ─────── */
@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,700;0,900;1,400;1,700&family=IBM+Plex+Sans:wght@300;400&display=swap');
.mu-pf {
--mu-pf-white: #fafafa;
--mu-pf-off: #f2f0ec;
--mu-pf-ink: #0f0f0f;
--mu-pf-mid: #888;
--mu-pf-light: #ccc;
--mu-pf-rule: #e8e4de;
--mu-pf-serif: 'Playfair Display', serif;
--mu-pf-sans: 'IBM Plex Sans', sans-serif;
position: relative;
width: 100%;
min-height: 1400px;
background: var(--mu-pf-white);
color: var(--mu-pf-ink);
font-family: var(--mu-pf-sans);
overflow-x: hidden;
box-sizing: border-box;
}
.mu-pf *,
.mu-pf *::before,
.mu-pf *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.mu-pf .header {
position: sticky;
top: 0;
z-index: 10;
background: var(--mu-pf-white);
display: flex;
align-items: center;
justify-content: space-between;
padding: 28px 56px;
}
.mu-pf .h-name {
font-family: var(--mu-pf-serif);
font-size: 18px;
font-weight: 400;
letter-spacing: 0.02em;
}
.mu-pf .h-nav {
display: flex;
gap: 36px;
}
.mu-pf .h-nav a {
font-size: 11px;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--mu-pf-mid);
text-decoration: none;
transition: color 0.2s;
}
.mu-pf .h-nav a:hover {
color: var(--mu-pf-ink);
}
.mu-pf .h-status {
font-size: 11px;
letter-spacing: 0.12em;
color: var(--mu-pf-mid);
display: flex;
align-items: center;
gap: 8px;
}
.mu-pf .status-dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: #4caf50;
animation: mu-pf-blink 2s infinite;
}
@keyframes mu-pf-blink {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.3;
}
}
.mu-pf .hero {
min-height: 540px;
display: flex;
flex-direction: column;
justify-content: flex-end;
padding: 0 56px 64px;
position: relative;
}
.mu-pf .hero-index {
position: absolute;
top: 50%;
left: 56px;
transform: translateY(-50%);
font-family: var(--mu-pf-serif);
font-size: clamp(160px,18vw,260px);
font-weight: 900;
color: var(--mu-pf-off);
line-height: 1;
letter-spacing: -0.05em;
user-select: none;
pointer-events: none;
}
.mu-pf .hero-text {
position: relative;
z-index: 2;
display: grid;
grid-template-columns: 1fr auto;
align-items: flex-end;
gap: 64px;
padding-top: 180px;
}
.mu-pf .hero-title {
font-family: var(--mu-pf-serif);
font-size: clamp(52px,7vw,96px);
font-weight: 400;
line-height: 1.05;
letter-spacing: -0.02em;
animation: mu-pf-fadein 1s ease 0.2s both;
}
.mu-pf .hero-title em {
font-style: italic;
font-weight: 400;
}
.mu-pf .hero-meta {
text-align: right;
max-width: 260px;
animation: mu-pf-fadein 1s ease 0.4s both;
}
.mu-pf .hero-role {
font-size: 11px;
letter-spacing: 0.2em;
text-transform: uppercase;
color: var(--mu-pf-mid);
margin-bottom: 14px;
}
.mu-pf .hero-desc {
font-size: 13px;
line-height: 1.8;
color: var(--mu-pf-mid);
font-weight: 300;
}
.mu-pf .hero-scroll-indicator {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
position: absolute;
right: 56px;
bottom: 64px;
}
.mu-pf .scroll-v-line {
width: 1px;
height: 60px;
background: var(--mu-pf-light);
animation: mu-pf-scrollline 2s ease infinite;
}
@keyframes mu-pf-scrollline {
0% {
transform: scaleY(0);
transform-origin: top;
}
50% {
transform: scaleY(1);
transform-origin: top;
}
51% {
transform: scaleY(1);
transform-origin: bottom;
}
100% {
transform: scaleY(0);
transform-origin: bottom;
}
}
.mu-pf .scroll-v-txt {
font-size: 9px;
letter-spacing: 0.2em;
color: var(--mu-pf-light);
text-transform: uppercase;
writing-mode: vertical-rl;
transform: rotate(180deg);
}
@keyframes mu-pf-fadein {
from {
opacity: 0;
transform: translateY(16px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.mu-pf .work-section {
padding: 0 56px 120px;
}
.mu-pf .section-rule {
display: flex;
align-items: center;
gap: 24px;
padding: 64px 0 48px;
}
.mu-pf .rule-num {
font-family: var(--mu-pf-serif);
font-size: 11px;
color: var(--mu-pf-mid);
font-style: italic;
}
.mu-pf .rule-line {
flex: 1;
height: 1px;
background: var(--mu-pf-light);
}
.mu-pf .rule-label {
font-size: 10px;
letter-spacing: 0.25em;
text-transform: uppercase;
color: var(--mu-pf-mid);
}
.mu-pf .project-list {
display: flex;
flex-direction: column;
gap: 0;
}
.mu-pf .project-item {
display: grid;
grid-template-columns: 80px 1fr auto;
align-items: center;
gap: 32px;
padding: 28px 0;
border-bottom: 1px solid var(--mu-pf-rule);
cursor: pointer;
position: relative;
overflow: hidden;
transition: padding 0.3s ease;
}
.mu-pf .project-item:first-child {
border-top: 1px solid var(--mu-pf-rule);
}
.mu-pf .project-item::before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 0;
background: var(--mu-pf-off);
z-index: 0;
transition: width 0.4s cubic-bezier(0.23,1,0.32,1);
}
.mu-pf .project-item:hover::before {
width: 100%;
}
.mu-pf .project-item:hover {
padding-left: 24px;
}
.mu-pf .project-item:hover .project-title {
letter-spacing: 0.01em;
}
.mu-pf .project-num {
font-family: var(--mu-pf-serif);
font-size: 13px;
color: var(--mu-pf-light);
font-style: italic;
position: relative;
z-index: 1;
}
.mu-pf .project-info {
position: relative;
z-index: 1;
}
.mu-pf .project-title {
font-family: var(--mu-pf-serif);
font-size: clamp(24px,3.5vw,42px);
font-weight: 400;
line-height: 1.1;
transition: letter-spacing 0.3s;
}
.mu-pf .project-tags {
display: flex;
gap: 12px;
margin-top: 6px;
}
.mu-pf .tag {
font-size: 10px;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--mu-pf-mid);
}
.mu-pf .project-right {
display: flex;
align-items: center;
gap: 32px;
position: relative;
z-index: 1;
}
.mu-pf .project-year {
font-size: 12px;
color: var(--mu-pf-mid);
font-family: var(--mu-pf-sans);
}
.mu-pf .project-arrow {
width: 44px;
height: 44px;
border: 1px solid var(--mu-pf-light);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
color: var(--mu-pf-mid);
transition: all 0.3s;
}
.mu-pf .project-item:hover .project-arrow {
background: var(--mu-pf-ink);
border-color: var(--mu-pf-ink);
color: var(--mu-pf-white);
transform: rotate(45deg);
}
/* Hover SVG preview — positioned absolute inside the wrapper, follows
the mouse via offsetX/offsetY computed against the wrapper. */
.mu-pf .preview-img {
position: absolute;
pointer-events: none;
z-index: 50;
width: 320px;
height: 220px;
opacity: 0;
transform: translateY(10px) rotate(-2deg);
transition: opacity 0.3s, transform 0.3s;
border-radius: 2px;
overflow: hidden;
top: 0;
left: 0;
}
.mu-pf .preview-img.visible {
opacity: 1;
transform: translateY(0) rotate(-1deg);
}
.mu-pf .about-strip {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0;
margin: 0 56px;
border-top: 1px solid var(--mu-pf-rule);
padding: 80px 0;
}
.mu-pf .about-left {
padding-right: 80px;
border-right: 1px solid var(--mu-pf-rule);
}
.mu-pf .about-right {
padding-left: 80px;
}
.mu-pf .about-eyebrow {
font-size: 10px;
letter-spacing: 0.25em;
text-transform: uppercase;
color: var(--mu-pf-mid);
margin-bottom: 20px;
}
.mu-pf .about-title {
font-family: var(--mu-pf-serif);
font-size: clamp(32px,4vw,52px);
font-weight: 400;
line-height: 1.15;
margin-bottom: 24px;
}
.mu-pf .about-title em {
font-style: italic;
}
.mu-pf .about-body {
font-size: 13.5px;
line-height: 1.9;
color: var(--mu-pf-mid);
font-weight: 300;
max-width: 400px;
}
.mu-pf .services-list {
display: flex;
flex-direction: column;
gap: 16px;
}
.mu-pf .service-item {
display: flex;
align-items: baseline;
gap: 16px;
padding-bottom: 16px;
border-bottom: 1px solid #ece8e2;
}
.mu-pf .service-item:last-child {
border-bottom: none;
padding-bottom: 0;
}
.mu-pf .svc-num {
font-family: var(--mu-pf-serif);
font-size: 11px;
color: var(--mu-pf-light);
font-style: italic;
min-width: 24px;
}
.mu-pf .svc-name {
font-size: 14px;
font-weight: 400;
}
.mu-pf .svc-type {
margin-left: auto;
font-size: 10px;
letter-spacing: 0.1em;
color: var(--mu-pf-mid);
}
.mu-pf .contact-section {
padding: 80px 56px;
text-align: center;
border-top: 1px solid var(--mu-pf-rule);
}
.mu-pf .contact-label {
font-size: 10px;
letter-spacing: 0.3em;
text-transform: uppercase;
color: var(--mu-pf-mid);
margin-bottom: 24px;
}
.mu-pf .contact-email {
font-family: var(--mu-pf-serif);
font-size: clamp(36px,6vw,80px);
font-weight: 400;
font-style: italic;
text-decoration: none;
color: var(--mu-pf-ink);
display: inline-block;
transition: letter-spacing 0.4s;
}
.mu-pf .contact-email:hover {
letter-spacing: 0.02em;
}
.mu-pf .contact-links {
display: flex;
justify-content: center;
gap: 40px;
margin-top: 40px;
}
.mu-pf .contact-link {
font-size: 11px;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--mu-pf-mid);
text-decoration: none;
transition: color 0.2s;
}
.mu-pf .contact-link:hover {
color: var(--mu-pf-ink);
}
.mu-pf .footer {
display: flex;
justify-content: space-between;
align-items: center;
padding: 28px 56px;
border-top: 1px solid var(--mu-pf-rule);
}
.mu-pf .footer span {
font-size: 11px;
color: var(--mu-pf-mid);
}
@media (max-width: 760px) {
.mu-pf .header,
.mu-pf .hero,
.mu-pf .work-section,
.mu-pf .contact-section,
.mu-pf .footer {
padding-left: 24px;
padding-right: 24px;
}
.mu-pf .h-nav {
display: none;
}
.mu-pf .hero-text {
grid-template-columns: 1fr;
gap: 32px;
}
.mu-pf .hero-meta {
text-align: left;
}
.mu-pf .hero-scroll-indicator {
display: none;
}
.mu-pf .about-strip {
grid-template-columns: 1fr;
margin: 0 24px;
}
.mu-pf .about-left {
padding-right: 0;
border-right: none;
border-bottom: 1px solid var(--mu-pf-rule);
padding-bottom: 48px;
margin-bottom: 48px;
}
.mu-pf .about-right {
padding-left: 0;
}
.mu-pf .footer {
flex-direction: column;
gap: 12px;
}
}
@media (prefers-reduced-motion: reduce) {
.mu-pf .status-dot,
.mu-pf .scroll-v-line,
.mu-pf .hero-title,
.mu-pf .hero-meta {
animation: none !important;
}
.mu-pf .project-item,
.mu-pf .project-arrow,
.mu-pf .preview-img {
transition: none !important;
}
}(() => {
// Scoped portfolio interactions. Drops the source mock's full-viewport
// mix-blend-mode cursor (which would look broken inside an embedded
// card) and keeps the hover-triggered SVG project preview that's the
// actual differentiator. The preview is positioned via offsetX/offsetY
// against the wrapper element so two demos can coexist on a page.
const root = document.querySelector('.mu-pf');
if (!root) return;
const preview = root.querySelector('[data-mu-pf-preview]');
const previewSvg = root.querySelector('[data-mu-pf-preview-svg]');
if (!preview || !previewSvg) return;
// Mouse position relative to the wrapper (not viewport), so the preview
// floats correctly regardless of scroll position.
root.addEventListener('mousemove', (e) => {
const r = root.getBoundingClientRect();
const x = e.clientX - r.left;
const y = e.clientY - r.top;
preview.style.left = (x + 24) + 'px';
preview.style.top = (y - 100) + 'px';
});
const items = root.querySelectorAll('.project-item');
items.forEach((item, i) => {
item.addEventListener('mouseenter', () => {
preview.classList.add('visible');
const c1 = item.dataset.color || '#1a1714';
const c2 = item.dataset.color2 || '#3a3028';
const c3 = item.dataset.accent || '#c8ff00';
previewSvg.innerHTML =
'<defs>' +
'<linearGradient id="mu-pf-pg' + i + '" x1="0%" y1="0%" x2="100%" y2="100%">' +
'<stop offset="0%" style="stop-color:' + c1 + '"/>' +
'<stop offset="100%" style="stop-color:' + c2 + '"/>' +
'</linearGradient>' +
'</defs>' +
'<rect width="320" height="220" fill="url(#mu-pf-pg' + i + ')"/>' +
'<line x1="0" y1="40" x2="320" y2="40" stroke="' + c3 + '" stroke-width="0.5" opacity="0.3"/>' +
'<line x1="0" y1="180" x2="320" y2="180" stroke="' + c3 + '" stroke-width="0.5" opacity="0.3"/>' +
'<text x="160" y="125" text-anchor="middle" font-family="\'Playfair Display\',serif" font-size="14" fill="' + c3 + '" opacity="0.5" letter-spacing="8">' + String(i + 1).padStart(3, '0') + '</text>' +
'<circle cx="280" cy="40" r="20" fill="none" stroke="' + c3 + '" stroke-width="0.5" opacity="0.3"/>';
});
item.addEventListener('mouseleave', () => {
preview.classList.remove('visible');
});
});
})();(() => {
// Scoped portfolio interactions. Drops the source mock's full-viewport
// mix-blend-mode cursor (which would look broken inside an embedded
// card) and keeps the hover-triggered SVG project preview that's the
// actual differentiator. The preview is positioned via offsetX/offsetY
// against the wrapper element so two demos can coexist on a page.
const root = document.querySelector('.mu-pf');
if (!root) return;
const preview = root.querySelector('[data-mu-pf-preview]');
const previewSvg = root.querySelector('[data-mu-pf-preview-svg]');
if (!preview || !previewSvg) return;
// Mouse position relative to the wrapper (not viewport), so the preview
// floats correctly regardless of scroll position.
root.addEventListener('mousemove', (e) => {
const r = root.getBoundingClientRect();
const x = e.clientX - r.left;
const y = e.clientY - r.top;
preview.style.left = (x + 24) + 'px';
preview.style.top = (y - 100) + 'px';
});
const items = root.querySelectorAll('.project-item');
items.forEach((item, i) => {
item.addEventListener('mouseenter', () => {
preview.classList.add('visible');
const c1 = item.dataset.color || '#1a1714';
const c2 = item.dataset.color2 || '#3a3028';
const c3 = item.dataset.accent || '#c8ff00';
previewSvg.innerHTML =
'<defs>' +
'<linearGradient id="mu-pf-pg' + i + '" x1="0%" y1="0%" x2="100%" y2="100%">' +
'<stop offset="0%" style="stop-color:' + c1 + '"/>' +
'<stop offset="100%" style="stop-color:' + c2 + '"/>' +
'</linearGradient>' +
'</defs>' +
'<rect width="320" height="220" fill="url(#mu-pf-pg' + i + ')"/>' +
'<line x1="0" y1="40" x2="320" y2="40" stroke="' + c3 + '" stroke-width="0.5" opacity="0.3"/>' +
'<line x1="0" y1="180" x2="320" y2="180" stroke="' + c3 + '" stroke-width="0.5" opacity="0.3"/>' +
'<text x="160" y="125" text-anchor="middle" font-family="\'Playfair Display\',serif" font-size="14" fill="' + c3 + '" opacity="0.5" letter-spacing="8">' + String(i + 1).padStart(3, '0') + '</text>' +
'<circle cx="280" cy="40" r="20" fill="none" stroke="' + c3 + '" stroke-width="0.5" opacity="0.3"/>';
});
item.addEventListener('mouseleave', () => {
preview.classList.remove('visible');
});
});
})();Here's a working CSS Minimalist UI Design from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Vera Lindstrom Portfolio
Source: https://codefronts.com/design-styles/css-minimalist-ui/vera-lindstrom-portfolio/
A brutalist-white minimalist portfolio UI for a Stockholm-based art director — a gallery-wall approach where the interface disappears so the creative work takes center stage. Sticky header with serif name + uppercase nav + green-dotted availability status, a giant typographic index letter "V" sitting half-revealed behind a Playfair Display hero headline (Visual / *Architect* / & Director), a numbered "Selected Work" project list where each row slides a cream fill in from the left on hover with a 45-degree rotating arrow and per-project SVG color preview card that follows the cursor, a two-column "About / Disciplines" strip with a numbered service index, and a giant italic contact email that animates letter-spacing on hover. Typography pairs Playfair Display (display) with IBM Plex Sans (UI). Best for designer portfolios, photographer sites, architect studios, art director landing pages, creative agency homepages.
## HTML
```html
<section class="mu-pf" aria-label="Vera Lindstrom creative portfolio demo">
<div class="preview-img" data-mu-pf-preview aria-hidden="true">
<svg data-mu-pf-preview-svg width="320" height="220" viewBox="0 0 320 220"></svg>
</div>
<header class="header">
<div class="h-name">Vera Lindström</div>
<nav class="h-nav">
<a href="#">Work</a>
<a href="#">About</a>
<a href="#">Journal</a>
<a href="#">Contact</a>
</nav>
<div class="h-status">
<div class="status-dot" aria-hidden="true"></div>
Available for projects
</div>
</header>
<section class="hero">
<div class="hero-index" aria-hidden="true">V</div>
<div class="hero-text">
<h1 class="hero-title">
Visual<br><em>Architect</em><br>& Director
</h1>
<div class="hero-meta">
<div class="hero-role">Art Direction · Branding · UI</div>
<p class="hero-desc">Building brand identities and digital experiences that earn their silence. Stockholm-based, globally engaged.</p>
</div>
</div>
<div class="hero-scroll-indicator" aria-hidden="true">
<div class="scroll-v-line"></div>
<div class="scroll-v-txt">Scroll</div>
</div>
</section>
<section class="work-section">
<div class="section-rule">
<span class="rule-num">01</span>
<div class="rule-line"></div>
<span class="rule-label">Selected Work</span>
</div>
<div class="project-list">
<div class="project-item" data-color="#1a1714" data-color2="#3a3028" data-accent="#c8ff00">
<div class="project-num">001</div>
<div class="project-info">
<div class="project-title">Maison Collective</div>
<div class="project-tags">
<span class="tag">Brand Identity</span>
<span class="tag">·</span>
<span class="tag">Art Direction</span>
</div>
</div>
<div class="project-right">
<span class="project-year">2025</span>
<div class="project-arrow">→</div>
</div>
</div>
<div class="project-item" data-color="#d4c4a8" data-color2="#b8a080" data-accent="#8a6040">
<div class="project-num">002</div>
<div class="project-info">
<div class="project-title">Aether Digital</div>
<div class="project-tags">
<span class="tag">Product UI</span>
<span class="tag">·</span>
<span class="tag">Design System</span>
</div>
</div>
<div class="project-right">
<span class="project-year">2025</span>
<div class="project-arrow">→</div>
</div>
</div>
<div class="project-item" data-color="#2c4a3e" data-color2="#1a3028" data-accent="#a8d4b8">
<div class="project-num">003</div>
<div class="project-info">
<div class="project-title"><em>Forma</em> Architecture</div>
<div class="project-tags">
<span class="tag">Photography</span>
<span class="tag">·</span>
<span class="tag">Editorial</span>
</div>
</div>
<div class="project-right">
<span class="project-year">2024</span>
<div class="project-arrow">→</div>
</div>
</div>
<div class="project-item" data-color="#8b6a3a" data-color2="#6a4a20" data-accent="#f0c880">
<div class="project-num">004</div>
<div class="project-info">
<div class="project-title">Norde Finance</div>
<div class="project-tags">
<span class="tag">Motion</span>
<span class="tag">·</span>
<span class="tag">Campaign</span>
</div>
</div>
<div class="project-right">
<span class="project-year">2024</span>
<div class="project-arrow">→</div>
</div>
</div>
<div class="project-item" data-color="#4a3858" data-color2="#2a1838" data-accent="#d4a8f0">
<div class="project-num">005</div>
<div class="project-info">
<div class="project-title">Lune Editorial</div>
<div class="project-tags">
<span class="tag">Publication</span>
<span class="tag">·</span>
<span class="tag">Typography</span>
</div>
</div>
<div class="project-right">
<span class="project-year">2024</span>
<div class="project-arrow">→</div>
</div>
</div>
</div>
</section>
<div class="about-strip">
<div class="about-left">
<div class="about-eyebrow">About the Practice</div>
<h2 class="about-title">Design that<br>trusts the <em>void</em></h2>
<p class="about-body">With fifteen years across Stockholm, London, and Tokyo, I've learned that the most memorable work is often the most restrained. I collaborate with founders, cultural institutions, and agencies to craft visual systems that hold their integrity across every surface.</p>
</div>
<div class="about-right">
<div class="about-eyebrow">Disciplines</div>
<div class="services-list">
<div class="service-item"><span class="svc-num">—</span><span class="svc-name">Brand Identity & Systems</span><span class="svc-type">Strategy · Visual</span></div>
<div class="service-item"><span class="svc-num">—</span><span class="svc-name">Digital Product Design</span><span class="svc-type">UI · UX · Prototyping</span></div>
<div class="service-item"><span class="svc-num">—</span><span class="svc-name">Art Direction</span><span class="svc-type">Photo · Film · Print</span></div>
<div class="service-item"><span class="svc-num">—</span><span class="svc-name">Editorial Design</span><span class="svc-type">Books · Magazines</span></div>
<div class="service-item"><span class="svc-num">—</span><span class="svc-name">Motion & Campaign</span><span class="svc-type">Digital · Out-of-home</span></div>
</div>
</div>
</div>
<div class="contact-section">
<div class="contact-label">Start a conversation</div>
<a class="contact-email" href="#">vera@lindstrom.studio</a>
<div class="contact-links">
<a class="contact-link" href="#">Instagram</a>
<a class="contact-link" href="#">LinkedIn</a>
<a class="contact-link" href="#">Are.na</a>
<a class="contact-link" href="#">Readcv</a>
</div>
</div>
<footer class="footer">
<span>© 2025 Vera Lindström Studio</span>
<span>Stockholm · SE</span>
<span>Currently: Available Q3 2025</span>
</footer>
</section>
```
## CSS
```css
/* ─── 03 Vera Lindström — minimalist creative portfolio UI ─────── */
@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,700;0,900;1,400;1,700&family=IBM+Plex+Sans:wght@300;400&display=swap');
.mu-pf {
--mu-pf-white: #fafafa;
--mu-pf-off: #f2f0ec;
--mu-pf-ink: #0f0f0f;
--mu-pf-mid: #888;
--mu-pf-light: #ccc;
--mu-pf-rule: #e8e4de;
--mu-pf-serif: 'Playfair Display', serif;
--mu-pf-sans: 'IBM Plex Sans', sans-serif;
position: relative;
width: 100%;
min-height: 1400px;
background: var(--mu-pf-white);
color: var(--mu-pf-ink);
font-family: var(--mu-pf-sans);
overflow-x: hidden;
box-sizing: border-box;
}
.mu-pf *,
.mu-pf *::before,
.mu-pf *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.mu-pf .header {
position: sticky;
top: 0;
z-index: 10;
background: var(--mu-pf-white);
display: flex;
align-items: center;
justify-content: space-between;
padding: 28px 56px;
}
.mu-pf .h-name {
font-family: var(--mu-pf-serif);
font-size: 18px;
font-weight: 400;
letter-spacing: 0.02em;
}
.mu-pf .h-nav {
display: flex;
gap: 36px;
}
.mu-pf .h-nav a {
font-size: 11px;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--mu-pf-mid);
text-decoration: none;
transition: color 0.2s;
}
.mu-pf .h-nav a:hover {
color: var(--mu-pf-ink);
}
.mu-pf .h-status {
font-size: 11px;
letter-spacing: 0.12em;
color: var(--mu-pf-mid);
display: flex;
align-items: center;
gap: 8px;
}
.mu-pf .status-dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: #4caf50;
animation: mu-pf-blink 2s infinite;
}
@keyframes mu-pf-blink {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.3;
}
}
.mu-pf .hero {
min-height: 540px;
display: flex;
flex-direction: column;
justify-content: flex-end;
padding: 0 56px 64px;
position: relative;
}
.mu-pf .hero-index {
position: absolute;
top: 50%;
left: 56px;
transform: translateY(-50%);
font-family: var(--mu-pf-serif);
font-size: clamp(160px,18vw,260px);
font-weight: 900;
color: var(--mu-pf-off);
line-height: 1;
letter-spacing: -0.05em;
user-select: none;
pointer-events: none;
}
.mu-pf .hero-text {
position: relative;
z-index: 2;
display: grid;
grid-template-columns: 1fr auto;
align-items: flex-end;
gap: 64px;
padding-top: 180px;
}
.mu-pf .hero-title {
font-family: var(--mu-pf-serif);
font-size: clamp(52px,7vw,96px);
font-weight: 400;
line-height: 1.05;
letter-spacing: -0.02em;
animation: mu-pf-fadein 1s ease 0.2s both;
}
.mu-pf .hero-title em {
font-style: italic;
font-weight: 400;
}
.mu-pf .hero-meta {
text-align: right;
max-width: 260px;
animation: mu-pf-fadein 1s ease 0.4s both;
}
.mu-pf .hero-role {
font-size: 11px;
letter-spacing: 0.2em;
text-transform: uppercase;
color: var(--mu-pf-mid);
margin-bottom: 14px;
}
.mu-pf .hero-desc {
font-size: 13px;
line-height: 1.8;
color: var(--mu-pf-mid);
font-weight: 300;
}
.mu-pf .hero-scroll-indicator {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
position: absolute;
right: 56px;
bottom: 64px;
}
.mu-pf .scroll-v-line {
width: 1px;
height: 60px;
background: var(--mu-pf-light);
animation: mu-pf-scrollline 2s ease infinite;
}
@keyframes mu-pf-scrollline {
0% {
transform: scaleY(0);
transform-origin: top;
}
50% {
transform: scaleY(1);
transform-origin: top;
}
51% {
transform: scaleY(1);
transform-origin: bottom;
}
100% {
transform: scaleY(0);
transform-origin: bottom;
}
}
.mu-pf .scroll-v-txt {
font-size: 9px;
letter-spacing: 0.2em;
color: var(--mu-pf-light);
text-transform: uppercase;
writing-mode: vertical-rl;
transform: rotate(180deg);
}
@keyframes mu-pf-fadein {
from {
opacity: 0;
transform: translateY(16px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.mu-pf .work-section {
padding: 0 56px 120px;
}
.mu-pf .section-rule {
display: flex;
align-items: center;
gap: 24px;
padding: 64px 0 48px;
}
.mu-pf .rule-num {
font-family: var(--mu-pf-serif);
font-size: 11px;
color: var(--mu-pf-mid);
font-style: italic;
}
.mu-pf .rule-line {
flex: 1;
height: 1px;
background: var(--mu-pf-light);
}
.mu-pf .rule-label {
font-size: 10px;
letter-spacing: 0.25em;
text-transform: uppercase;
color: var(--mu-pf-mid);
}
.mu-pf .project-list {
display: flex;
flex-direction: column;
gap: 0;
}
.mu-pf .project-item {
display: grid;
grid-template-columns: 80px 1fr auto;
align-items: center;
gap: 32px;
padding: 28px 0;
border-bottom: 1px solid var(--mu-pf-rule);
cursor: pointer;
position: relative;
overflow: hidden;
transition: padding 0.3s ease;
}
.mu-pf .project-item:first-child {
border-top: 1px solid var(--mu-pf-rule);
}
.mu-pf .project-item::before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 0;
background: var(--mu-pf-off);
z-index: 0;
transition: width 0.4s cubic-bezier(0.23,1,0.32,1);
}
.mu-pf .project-item:hover::before {
width: 100%;
}
.mu-pf .project-item:hover {
padding-left: 24px;
}
.mu-pf .project-item:hover .project-title {
letter-spacing: 0.01em;
}
.mu-pf .project-num {
font-family: var(--mu-pf-serif);
font-size: 13px;
color: var(--mu-pf-light);
font-style: italic;
position: relative;
z-index: 1;
}
.mu-pf .project-info {
position: relative;
z-index: 1;
}
.mu-pf .project-title {
font-family: var(--mu-pf-serif);
font-size: clamp(24px,3.5vw,42px);
font-weight: 400;
line-height: 1.1;
transition: letter-spacing 0.3s;
}
.mu-pf .project-tags {
display: flex;
gap: 12px;
margin-top: 6px;
}
.mu-pf .tag {
font-size: 10px;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--mu-pf-mid);
}
.mu-pf .project-right {
display: flex;
align-items: center;
gap: 32px;
position: relative;
z-index: 1;
}
.mu-pf .project-year {
font-size: 12px;
color: var(--mu-pf-mid);
font-family: var(--mu-pf-sans);
}
.mu-pf .project-arrow {
width: 44px;
height: 44px;
border: 1px solid var(--mu-pf-light);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
color: var(--mu-pf-mid);
transition: all 0.3s;
}
.mu-pf .project-item:hover .project-arrow {
background: var(--mu-pf-ink);
border-color: var(--mu-pf-ink);
color: var(--mu-pf-white);
transform: rotate(45deg);
}
/* Hover SVG preview — positioned absolute inside the wrapper, follows
the mouse via offsetX/offsetY computed against the wrapper. */
.mu-pf .preview-img {
position: absolute;
pointer-events: none;
z-index: 50;
width: 320px;
height: 220px;
opacity: 0;
transform: translateY(10px) rotate(-2deg);
transition: opacity 0.3s, transform 0.3s;
border-radius: 2px;
overflow: hidden;
top: 0;
left: 0;
}
.mu-pf .preview-img.visible {
opacity: 1;
transform: translateY(0) rotate(-1deg);
}
.mu-pf .about-strip {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0;
margin: 0 56px;
border-top: 1px solid var(--mu-pf-rule);
padding: 80px 0;
}
.mu-pf .about-left {
padding-right: 80px;
border-right: 1px solid var(--mu-pf-rule);
}
.mu-pf .about-right {
padding-left: 80px;
}
.mu-pf .about-eyebrow {
font-size: 10px;
letter-spacing: 0.25em;
text-transform: uppercase;
color: var(--mu-pf-mid);
margin-bottom: 20px;
}
.mu-pf .about-title {
font-family: var(--mu-pf-serif);
font-size: clamp(32px,4vw,52px);
font-weight: 400;
line-height: 1.15;
margin-bottom: 24px;
}
.mu-pf .about-title em {
font-style: italic;
}
.mu-pf .about-body {
font-size: 13.5px;
line-height: 1.9;
color: var(--mu-pf-mid);
font-weight: 300;
max-width: 400px;
}
.mu-pf .services-list {
display: flex;
flex-direction: column;
gap: 16px;
}
.mu-pf .service-item {
display: flex;
align-items: baseline;
gap: 16px;
padding-bottom: 16px;
border-bottom: 1px solid #ece8e2;
}
.mu-pf .service-item:last-child {
border-bottom: none;
padding-bottom: 0;
}
.mu-pf .svc-num {
font-family: var(--mu-pf-serif);
font-size: 11px;
color: var(--mu-pf-light);
font-style: italic;
min-width: 24px;
}
.mu-pf .svc-name {
font-size: 14px;
font-weight: 400;
}
.mu-pf .svc-type {
margin-left: auto;
font-size: 10px;
letter-spacing: 0.1em;
color: var(--mu-pf-mid);
}
.mu-pf .contact-section {
padding: 80px 56px;
text-align: center;
border-top: 1px solid var(--mu-pf-rule);
}
.mu-pf .contact-label {
font-size: 10px;
letter-spacing: 0.3em;
text-transform: uppercase;
color: var(--mu-pf-mid);
margin-bottom: 24px;
}
.mu-pf .contact-email {
font-family: var(--mu-pf-serif);
font-size: clamp(36px,6vw,80px);
font-weight: 400;
font-style: italic;
text-decoration: none;
color: var(--mu-pf-ink);
display: inline-block;
transition: letter-spacing 0.4s;
}
.mu-pf .contact-email:hover {
letter-spacing: 0.02em;
}
.mu-pf .contact-links {
display: flex;
justify-content: center;
gap: 40px;
margin-top: 40px;
}
.mu-pf .contact-link {
font-size: 11px;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--mu-pf-mid);
text-decoration: none;
transition: color 0.2s;
}
.mu-pf .contact-link:hover {
color: var(--mu-pf-ink);
}
.mu-pf .footer {
display: flex;
justify-content: space-between;
align-items: center;
padding: 28px 56px;
border-top: 1px solid var(--mu-pf-rule);
}
.mu-pf .footer span {
font-size: 11px;
color: var(--mu-pf-mid);
}
@media (max-width: 760px) {
.mu-pf .header,
.mu-pf .hero,
.mu-pf .work-section,
.mu-pf .contact-section,
.mu-pf .footer {
padding-left: 24px;
padding-right: 24px;
}
.mu-pf .h-nav {
display: none;
}
.mu-pf .hero-text {
grid-template-columns: 1fr;
gap: 32px;
}
.mu-pf .hero-meta {
text-align: left;
}
.mu-pf .hero-scroll-indicator {
display: none;
}
.mu-pf .about-strip {
grid-template-columns: 1fr;
margin: 0 24px;
}
.mu-pf .about-left {
padding-right: 0;
border-right: none;
border-bottom: 1px solid var(--mu-pf-rule);
padding-bottom: 48px;
margin-bottom: 48px;
}
.mu-pf .about-right {
padding-left: 0;
}
.mu-pf .footer {
flex-direction: column;
gap: 12px;
}
}
@media (prefers-reduced-motion: reduce) {
.mu-pf .status-dot,
.mu-pf .scroll-v-line,
.mu-pf .hero-title,
.mu-pf .hero-meta {
animation: none !important;
}
.mu-pf .project-item,
.mu-pf .project-arrow,
.mu-pf .preview-img {
transition: none !important;
}
}
```
## JavaScript
```js
(() => {
// Scoped portfolio interactions. Drops the source mock's full-viewport
// mix-blend-mode cursor (which would look broken inside an embedded
// card) and keeps the hover-triggered SVG project preview that's the
// actual differentiator. The preview is positioned via offsetX/offsetY
// against the wrapper element so two demos can coexist on a page.
const root = document.querySelector('.mu-pf');
if (!root) return;
const preview = root.querySelector('[data-mu-pf-preview]');
const previewSvg = root.querySelector('[data-mu-pf-preview-svg]');
if (!preview || !previewSvg) return;
// Mouse position relative to the wrapper (not viewport), so the preview
// floats correctly regardless of scroll position.
root.addEventListener('mousemove', (e) => {
const r = root.getBoundingClientRect();
const x = e.clientX - r.left;
const y = e.clientY - r.top;
preview.style.left = (x + 24) + 'px';
preview.style.top = (y - 100) + 'px';
});
const items = root.querySelectorAll('.project-item');
items.forEach((item, i) => {
item.addEventListener('mouseenter', () => {
preview.classList.add('visible');
const c1 = item.dataset.color || '#1a1714';
const c2 = item.dataset.color2 || '#3a3028';
const c3 = item.dataset.accent || '#c8ff00';
previewSvg.innerHTML =
'<defs>' +
'<linearGradient id="mu-pf-pg' + i + '" x1="0%" y1="0%" x2="100%" y2="100%">' +
'<stop offset="0%" style="stop-color:' + c1 + '"/>' +
'<stop offset="100%" style="stop-color:' + c2 + '"/>' +
'</linearGradient>' +
'</defs>' +
'<rect width="320" height="220" fill="url(#mu-pf-pg' + i + ')"/>' +
'<line x1="0" y1="40" x2="320" y2="40" stroke="' + c3 + '" stroke-width="0.5" opacity="0.3"/>' +
'<line x1="0" y1="180" x2="320" y2="180" stroke="' + c3 + '" stroke-width="0.5" opacity="0.3"/>' +
'<text x="160" y="125" text-anchor="middle" font-family="\'Playfair Display\',serif" font-size="14" fill="' + c3 + '" opacity="0.5" letter-spacing="8">' + String(i + 1).padStart(3, '0') + '</text>' +
'<circle cx="280" cy="40" r="20" fill="none" stroke="' + c3 + '" stroke-width="0.5" opacity="0.3"/>';
});
item.addEventListener('mouseleave', () => {
preview.classList.remove('visible');
});
});
})();
```Here's a working CSS Minimalist UI Design from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Vera Lindstrom Portfolio
Source: https://codefronts.com/design-styles/css-minimalist-ui/vera-lindstrom-portfolio/
A brutalist-white minimalist portfolio UI for a Stockholm-based art director — a gallery-wall approach where the interface disappears so the creative work takes center stage. Sticky header with serif name + uppercase nav + green-dotted availability status, a giant typographic index letter "V" sitting half-revealed behind a Playfair Display hero headline (Visual / *Architect* / & Director), a numbered "Selected Work" project list where each row slides a cream fill in from the left on hover with a 45-degree rotating arrow and per-project SVG color preview card that follows the cursor, a two-column "About / Disciplines" strip with a numbered service index, and a giant italic contact email that animates letter-spacing on hover. Typography pairs Playfair Display (display) with IBM Plex Sans (UI). Best for designer portfolios, photographer sites, architect studios, art director landing pages, creative agency homepages.
## HTML
```html
<section class="mu-pf" aria-label="Vera Lindstrom creative portfolio demo">
<div class="preview-img" data-mu-pf-preview aria-hidden="true">
<svg data-mu-pf-preview-svg width="320" height="220" viewBox="0 0 320 220"></svg>
</div>
<header class="header">
<div class="h-name">Vera Lindström</div>
<nav class="h-nav">
<a href="#">Work</a>
<a href="#">About</a>
<a href="#">Journal</a>
<a href="#">Contact</a>
</nav>
<div class="h-status">
<div class="status-dot" aria-hidden="true"></div>
Available for projects
</div>
</header>
<section class="hero">
<div class="hero-index" aria-hidden="true">V</div>
<div class="hero-text">
<h1 class="hero-title">
Visual<br><em>Architect</em><br>& Director
</h1>
<div class="hero-meta">
<div class="hero-role">Art Direction · Branding · UI</div>
<p class="hero-desc">Building brand identities and digital experiences that earn their silence. Stockholm-based, globally engaged.</p>
</div>
</div>
<div class="hero-scroll-indicator" aria-hidden="true">
<div class="scroll-v-line"></div>
<div class="scroll-v-txt">Scroll</div>
</div>
</section>
<section class="work-section">
<div class="section-rule">
<span class="rule-num">01</span>
<div class="rule-line"></div>
<span class="rule-label">Selected Work</span>
</div>
<div class="project-list">
<div class="project-item" data-color="#1a1714" data-color2="#3a3028" data-accent="#c8ff00">
<div class="project-num">001</div>
<div class="project-info">
<div class="project-title">Maison Collective</div>
<div class="project-tags">
<span class="tag">Brand Identity</span>
<span class="tag">·</span>
<span class="tag">Art Direction</span>
</div>
</div>
<div class="project-right">
<span class="project-year">2025</span>
<div class="project-arrow">→</div>
</div>
</div>
<div class="project-item" data-color="#d4c4a8" data-color2="#b8a080" data-accent="#8a6040">
<div class="project-num">002</div>
<div class="project-info">
<div class="project-title">Aether Digital</div>
<div class="project-tags">
<span class="tag">Product UI</span>
<span class="tag">·</span>
<span class="tag">Design System</span>
</div>
</div>
<div class="project-right">
<span class="project-year">2025</span>
<div class="project-arrow">→</div>
</div>
</div>
<div class="project-item" data-color="#2c4a3e" data-color2="#1a3028" data-accent="#a8d4b8">
<div class="project-num">003</div>
<div class="project-info">
<div class="project-title"><em>Forma</em> Architecture</div>
<div class="project-tags">
<span class="tag">Photography</span>
<span class="tag">·</span>
<span class="tag">Editorial</span>
</div>
</div>
<div class="project-right">
<span class="project-year">2024</span>
<div class="project-arrow">→</div>
</div>
</div>
<div class="project-item" data-color="#8b6a3a" data-color2="#6a4a20" data-accent="#f0c880">
<div class="project-num">004</div>
<div class="project-info">
<div class="project-title">Norde Finance</div>
<div class="project-tags">
<span class="tag">Motion</span>
<span class="tag">·</span>
<span class="tag">Campaign</span>
</div>
</div>
<div class="project-right">
<span class="project-year">2024</span>
<div class="project-arrow">→</div>
</div>
</div>
<div class="project-item" data-color="#4a3858" data-color2="#2a1838" data-accent="#d4a8f0">
<div class="project-num">005</div>
<div class="project-info">
<div class="project-title">Lune Editorial</div>
<div class="project-tags">
<span class="tag">Publication</span>
<span class="tag">·</span>
<span class="tag">Typography</span>
</div>
</div>
<div class="project-right">
<span class="project-year">2024</span>
<div class="project-arrow">→</div>
</div>
</div>
</div>
</section>
<div class="about-strip">
<div class="about-left">
<div class="about-eyebrow">About the Practice</div>
<h2 class="about-title">Design that<br>trusts the <em>void</em></h2>
<p class="about-body">With fifteen years across Stockholm, London, and Tokyo, I've learned that the most memorable work is often the most restrained. I collaborate with founders, cultural institutions, and agencies to craft visual systems that hold their integrity across every surface.</p>
</div>
<div class="about-right">
<div class="about-eyebrow">Disciplines</div>
<div class="services-list">
<div class="service-item"><span class="svc-num">—</span><span class="svc-name">Brand Identity & Systems</span><span class="svc-type">Strategy · Visual</span></div>
<div class="service-item"><span class="svc-num">—</span><span class="svc-name">Digital Product Design</span><span class="svc-type">UI · UX · Prototyping</span></div>
<div class="service-item"><span class="svc-num">—</span><span class="svc-name">Art Direction</span><span class="svc-type">Photo · Film · Print</span></div>
<div class="service-item"><span class="svc-num">—</span><span class="svc-name">Editorial Design</span><span class="svc-type">Books · Magazines</span></div>
<div class="service-item"><span class="svc-num">—</span><span class="svc-name">Motion & Campaign</span><span class="svc-type">Digital · Out-of-home</span></div>
</div>
</div>
</div>
<div class="contact-section">
<div class="contact-label">Start a conversation</div>
<a class="contact-email" href="#">vera@lindstrom.studio</a>
<div class="contact-links">
<a class="contact-link" href="#">Instagram</a>
<a class="contact-link" href="#">LinkedIn</a>
<a class="contact-link" href="#">Are.na</a>
<a class="contact-link" href="#">Readcv</a>
</div>
</div>
<footer class="footer">
<span>© 2025 Vera Lindström Studio</span>
<span>Stockholm · SE</span>
<span>Currently: Available Q3 2025</span>
</footer>
</section>
```
## CSS
```css
/* ─── 03 Vera Lindström — minimalist creative portfolio UI ─────── */
@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,700;0,900;1,400;1,700&family=IBM+Plex+Sans:wght@300;400&display=swap');
.mu-pf {
--mu-pf-white: #fafafa;
--mu-pf-off: #f2f0ec;
--mu-pf-ink: #0f0f0f;
--mu-pf-mid: #888;
--mu-pf-light: #ccc;
--mu-pf-rule: #e8e4de;
--mu-pf-serif: 'Playfair Display', serif;
--mu-pf-sans: 'IBM Plex Sans', sans-serif;
position: relative;
width: 100%;
min-height: 1400px;
background: var(--mu-pf-white);
color: var(--mu-pf-ink);
font-family: var(--mu-pf-sans);
overflow-x: hidden;
box-sizing: border-box;
}
.mu-pf *,
.mu-pf *::before,
.mu-pf *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.mu-pf .header {
position: sticky;
top: 0;
z-index: 10;
background: var(--mu-pf-white);
display: flex;
align-items: center;
justify-content: space-between;
padding: 28px 56px;
}
.mu-pf .h-name {
font-family: var(--mu-pf-serif);
font-size: 18px;
font-weight: 400;
letter-spacing: 0.02em;
}
.mu-pf .h-nav {
display: flex;
gap: 36px;
}
.mu-pf .h-nav a {
font-size: 11px;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--mu-pf-mid);
text-decoration: none;
transition: color 0.2s;
}
.mu-pf .h-nav a:hover {
color: var(--mu-pf-ink);
}
.mu-pf .h-status {
font-size: 11px;
letter-spacing: 0.12em;
color: var(--mu-pf-mid);
display: flex;
align-items: center;
gap: 8px;
}
.mu-pf .status-dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: #4caf50;
animation: mu-pf-blink 2s infinite;
}
@keyframes mu-pf-blink {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.3;
}
}
.mu-pf .hero {
min-height: 540px;
display: flex;
flex-direction: column;
justify-content: flex-end;
padding: 0 56px 64px;
position: relative;
}
.mu-pf .hero-index {
position: absolute;
top: 50%;
left: 56px;
transform: translateY(-50%);
font-family: var(--mu-pf-serif);
font-size: clamp(160px,18vw,260px);
font-weight: 900;
color: var(--mu-pf-off);
line-height: 1;
letter-spacing: -0.05em;
user-select: none;
pointer-events: none;
}
.mu-pf .hero-text {
position: relative;
z-index: 2;
display: grid;
grid-template-columns: 1fr auto;
align-items: flex-end;
gap: 64px;
padding-top: 180px;
}
.mu-pf .hero-title {
font-family: var(--mu-pf-serif);
font-size: clamp(52px,7vw,96px);
font-weight: 400;
line-height: 1.05;
letter-spacing: -0.02em;
animation: mu-pf-fadein 1s ease 0.2s both;
}
.mu-pf .hero-title em {
font-style: italic;
font-weight: 400;
}
.mu-pf .hero-meta {
text-align: right;
max-width: 260px;
animation: mu-pf-fadein 1s ease 0.4s both;
}
.mu-pf .hero-role {
font-size: 11px;
letter-spacing: 0.2em;
text-transform: uppercase;
color: var(--mu-pf-mid);
margin-bottom: 14px;
}
.mu-pf .hero-desc {
font-size: 13px;
line-height: 1.8;
color: var(--mu-pf-mid);
font-weight: 300;
}
.mu-pf .hero-scroll-indicator {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
position: absolute;
right: 56px;
bottom: 64px;
}
.mu-pf .scroll-v-line {
width: 1px;
height: 60px;
background: var(--mu-pf-light);
animation: mu-pf-scrollline 2s ease infinite;
}
@keyframes mu-pf-scrollline {
0% {
transform: scaleY(0);
transform-origin: top;
}
50% {
transform: scaleY(1);
transform-origin: top;
}
51% {
transform: scaleY(1);
transform-origin: bottom;
}
100% {
transform: scaleY(0);
transform-origin: bottom;
}
}
.mu-pf .scroll-v-txt {
font-size: 9px;
letter-spacing: 0.2em;
color: var(--mu-pf-light);
text-transform: uppercase;
writing-mode: vertical-rl;
transform: rotate(180deg);
}
@keyframes mu-pf-fadein {
from {
opacity: 0;
transform: translateY(16px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.mu-pf .work-section {
padding: 0 56px 120px;
}
.mu-pf .section-rule {
display: flex;
align-items: center;
gap: 24px;
padding: 64px 0 48px;
}
.mu-pf .rule-num {
font-family: var(--mu-pf-serif);
font-size: 11px;
color: var(--mu-pf-mid);
font-style: italic;
}
.mu-pf .rule-line {
flex: 1;
height: 1px;
background: var(--mu-pf-light);
}
.mu-pf .rule-label {
font-size: 10px;
letter-spacing: 0.25em;
text-transform: uppercase;
color: var(--mu-pf-mid);
}
.mu-pf .project-list {
display: flex;
flex-direction: column;
gap: 0;
}
.mu-pf .project-item {
display: grid;
grid-template-columns: 80px 1fr auto;
align-items: center;
gap: 32px;
padding: 28px 0;
border-bottom: 1px solid var(--mu-pf-rule);
cursor: pointer;
position: relative;
overflow: hidden;
transition: padding 0.3s ease;
}
.mu-pf .project-item:first-child {
border-top: 1px solid var(--mu-pf-rule);
}
.mu-pf .project-item::before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 0;
background: var(--mu-pf-off);
z-index: 0;
transition: width 0.4s cubic-bezier(0.23,1,0.32,1);
}
.mu-pf .project-item:hover::before {
width: 100%;
}
.mu-pf .project-item:hover {
padding-left: 24px;
}
.mu-pf .project-item:hover .project-title {
letter-spacing: 0.01em;
}
.mu-pf .project-num {
font-family: var(--mu-pf-serif);
font-size: 13px;
color: var(--mu-pf-light);
font-style: italic;
position: relative;
z-index: 1;
}
.mu-pf .project-info {
position: relative;
z-index: 1;
}
.mu-pf .project-title {
font-family: var(--mu-pf-serif);
font-size: clamp(24px,3.5vw,42px);
font-weight: 400;
line-height: 1.1;
transition: letter-spacing 0.3s;
}
.mu-pf .project-tags {
display: flex;
gap: 12px;
margin-top: 6px;
}
.mu-pf .tag {
font-size: 10px;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--mu-pf-mid);
}
.mu-pf .project-right {
display: flex;
align-items: center;
gap: 32px;
position: relative;
z-index: 1;
}
.mu-pf .project-year {
font-size: 12px;
color: var(--mu-pf-mid);
font-family: var(--mu-pf-sans);
}
.mu-pf .project-arrow {
width: 44px;
height: 44px;
border: 1px solid var(--mu-pf-light);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
color: var(--mu-pf-mid);
transition: all 0.3s;
}
.mu-pf .project-item:hover .project-arrow {
background: var(--mu-pf-ink);
border-color: var(--mu-pf-ink);
color: var(--mu-pf-white);
transform: rotate(45deg);
}
/* Hover SVG preview — positioned absolute inside the wrapper, follows
the mouse via offsetX/offsetY computed against the wrapper. */
.mu-pf .preview-img {
position: absolute;
pointer-events: none;
z-index: 50;
width: 320px;
height: 220px;
opacity: 0;
transform: translateY(10px) rotate(-2deg);
transition: opacity 0.3s, transform 0.3s;
border-radius: 2px;
overflow: hidden;
top: 0;
left: 0;
}
.mu-pf .preview-img.visible {
opacity: 1;
transform: translateY(0) rotate(-1deg);
}
.mu-pf .about-strip {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0;
margin: 0 56px;
border-top: 1px solid var(--mu-pf-rule);
padding: 80px 0;
}
.mu-pf .about-left {
padding-right: 80px;
border-right: 1px solid var(--mu-pf-rule);
}
.mu-pf .about-right {
padding-left: 80px;
}
.mu-pf .about-eyebrow {
font-size: 10px;
letter-spacing: 0.25em;
text-transform: uppercase;
color: var(--mu-pf-mid);
margin-bottom: 20px;
}
.mu-pf .about-title {
font-family: var(--mu-pf-serif);
font-size: clamp(32px,4vw,52px);
font-weight: 400;
line-height: 1.15;
margin-bottom: 24px;
}
.mu-pf .about-title em {
font-style: italic;
}
.mu-pf .about-body {
font-size: 13.5px;
line-height: 1.9;
color: var(--mu-pf-mid);
font-weight: 300;
max-width: 400px;
}
.mu-pf .services-list {
display: flex;
flex-direction: column;
gap: 16px;
}
.mu-pf .service-item {
display: flex;
align-items: baseline;
gap: 16px;
padding-bottom: 16px;
border-bottom: 1px solid #ece8e2;
}
.mu-pf .service-item:last-child {
border-bottom: none;
padding-bottom: 0;
}
.mu-pf .svc-num {
font-family: var(--mu-pf-serif);
font-size: 11px;
color: var(--mu-pf-light);
font-style: italic;
min-width: 24px;
}
.mu-pf .svc-name {
font-size: 14px;
font-weight: 400;
}
.mu-pf .svc-type {
margin-left: auto;
font-size: 10px;
letter-spacing: 0.1em;
color: var(--mu-pf-mid);
}
.mu-pf .contact-section {
padding: 80px 56px;
text-align: center;
border-top: 1px solid var(--mu-pf-rule);
}
.mu-pf .contact-label {
font-size: 10px;
letter-spacing: 0.3em;
text-transform: uppercase;
color: var(--mu-pf-mid);
margin-bottom: 24px;
}
.mu-pf .contact-email {
font-family: var(--mu-pf-serif);
font-size: clamp(36px,6vw,80px);
font-weight: 400;
font-style: italic;
text-decoration: none;
color: var(--mu-pf-ink);
display: inline-block;
transition: letter-spacing 0.4s;
}
.mu-pf .contact-email:hover {
letter-spacing: 0.02em;
}
.mu-pf .contact-links {
display: flex;
justify-content: center;
gap: 40px;
margin-top: 40px;
}
.mu-pf .contact-link {
font-size: 11px;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--mu-pf-mid);
text-decoration: none;
transition: color 0.2s;
}
.mu-pf .contact-link:hover {
color: var(--mu-pf-ink);
}
.mu-pf .footer {
display: flex;
justify-content: space-between;
align-items: center;
padding: 28px 56px;
border-top: 1px solid var(--mu-pf-rule);
}
.mu-pf .footer span {
font-size: 11px;
color: var(--mu-pf-mid);
}
@media (max-width: 760px) {
.mu-pf .header,
.mu-pf .hero,
.mu-pf .work-section,
.mu-pf .contact-section,
.mu-pf .footer {
padding-left: 24px;
padding-right: 24px;
}
.mu-pf .h-nav {
display: none;
}
.mu-pf .hero-text {
grid-template-columns: 1fr;
gap: 32px;
}
.mu-pf .hero-meta {
text-align: left;
}
.mu-pf .hero-scroll-indicator {
display: none;
}
.mu-pf .about-strip {
grid-template-columns: 1fr;
margin: 0 24px;
}
.mu-pf .about-left {
padding-right: 0;
border-right: none;
border-bottom: 1px solid var(--mu-pf-rule);
padding-bottom: 48px;
margin-bottom: 48px;
}
.mu-pf .about-right {
padding-left: 0;
}
.mu-pf .footer {
flex-direction: column;
gap: 12px;
}
}
@media (prefers-reduced-motion: reduce) {
.mu-pf .status-dot,
.mu-pf .scroll-v-line,
.mu-pf .hero-title,
.mu-pf .hero-meta {
animation: none !important;
}
.mu-pf .project-item,
.mu-pf .project-arrow,
.mu-pf .preview-img {
transition: none !important;
}
}
```
## JavaScript
```js
(() => {
// Scoped portfolio interactions. Drops the source mock's full-viewport
// mix-blend-mode cursor (which would look broken inside an embedded
// card) and keeps the hover-triggered SVG project preview that's the
// actual differentiator. The preview is positioned via offsetX/offsetY
// against the wrapper element so two demos can coexist on a page.
const root = document.querySelector('.mu-pf');
if (!root) return;
const preview = root.querySelector('[data-mu-pf-preview]');
const previewSvg = root.querySelector('[data-mu-pf-preview-svg]');
if (!preview || !previewSvg) return;
// Mouse position relative to the wrapper (not viewport), so the preview
// floats correctly regardless of scroll position.
root.addEventListener('mousemove', (e) => {
const r = root.getBoundingClientRect();
const x = e.clientX - r.left;
const y = e.clientY - r.top;
preview.style.left = (x + 24) + 'px';
preview.style.top = (y - 100) + 'px';
});
const items = root.querySelectorAll('.project-item');
items.forEach((item, i) => {
item.addEventListener('mouseenter', () => {
preview.classList.add('visible');
const c1 = item.dataset.color || '#1a1714';
const c2 = item.dataset.color2 || '#3a3028';
const c3 = item.dataset.accent || '#c8ff00';
previewSvg.innerHTML =
'<defs>' +
'<linearGradient id="mu-pf-pg' + i + '" x1="0%" y1="0%" x2="100%" y2="100%">' +
'<stop offset="0%" style="stop-color:' + c1 + '"/>' +
'<stop offset="100%" style="stop-color:' + c2 + '"/>' +
'</linearGradient>' +
'</defs>' +
'<rect width="320" height="220" fill="url(#mu-pf-pg' + i + ')"/>' +
'<line x1="0" y1="40" x2="320" y2="40" stroke="' + c3 + '" stroke-width="0.5" opacity="0.3"/>' +
'<line x1="0" y1="180" x2="320" y2="180" stroke="' + c3 + '" stroke-width="0.5" opacity="0.3"/>' +
'<text x="160" y="125" text-anchor="middle" font-family="\'Playfair Display\',serif" font-size="14" fill="' + c3 + '" opacity="0.5" letter-spacing="8">' + String(i + 1).padStart(3, '0') + '</text>' +
'<circle cx="280" cy="40" r="20" fill="none" stroke="' + c3 + '" stroke-width="0.5" opacity="0.3"/>';
});
item.addEventListener('mouseleave', () => {
preview.classList.remove('visible');
});
});
})();
```