Neumorphism
Soft UI that extrudes from a monochromatic surface using dual shadows — giving elements a pillowy, physical feel.
MCP
Code
/* ============================================================
NEUMORPHISM — Soft UI Design Showcase
Base color: #E0E5EC — everything extrudes from this surface
============================================================ */
:root {
--bg: #e0e5ec;
--shadow-light: rgba(255, 255, 255, 0.8);
--shadow-dark: rgba(163, 177, 198, 0.6);
--shadow-light-strong: rgba(255, 255, 255, 0.9);
--shadow-dark-strong: rgba(163, 177, 198, 0.75);
/* Raised (convex) shadow */
--neu-raised: -6px -6px 14px var(--shadow-light), 6px 6px 14px var(--shadow-dark);
--neu-raised-sm: -3px -3px 8px var(--shadow-light), 3px 3px 8px var(--shadow-dark);
--neu-raised-lg: -10px -10px 24px var(--shadow-light-strong), 10px 10px 24px
var(--shadow-dark-strong);
/* Pressed (concave / inset) shadow */
--neu-pressed: inset -4px -4px 10px var(--shadow-light), inset 4px 4px 10px var(--shadow-dark);
--neu-pressed-sm: inset -2px -2px 6px var(--shadow-light), inset 2px 2px 6px var(--shadow-dark);
/* Typography */
--text-primary: #2d4356;
--text-muted: #6d8a96;
--text-light: #9aabb5;
/* Accent */
--accent: #6c63ff;
--accent-alt: #4a90d9;
--radius-card: 20px;
--radius-pill: 50px;
--font: "Poppins", sans-serif;
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
font-size: 16px;
}
body {
font-family: var(--font);
background-color: var(--bg);
color: var(--text-primary);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
padding: 0 0 60px;
}
/* ── Header ── */
.neu-header {
width: 100%;
padding: 28px 40px 24px;
display: flex;
align-items: center;
justify-content: center;
}
.header-inner {
display: flex;
align-items: center;
gap: 18px;
}
.logo-mark {
width: 52px;
height: 52px;
border-radius: 14px;
background: var(--bg);
box-shadow: var(--neu-raised);
display: flex;
align-items: center;
justify-content: center;
color: var(--accent);
flex-shrink: 0;
}
.header-title {
font-size: 1.75rem;
font-weight: 700;
letter-spacing: -0.5px;
color: var(--text-primary);
}
.header-tagline {
font-size: 0.8rem;
font-weight: 400;
color: var(--text-muted);
letter-spacing: 0.5px;
margin-top: 1px;
}
/* ── Main layout ── */
.page-main {
display: flex;
flex-direction: column;
gap: 28px;
width: 100%;
max-width: 460px;
padding: 0 24px;
}
/* ── Cards ── */
.neu-card {
background: var(--bg);
border-radius: var(--radius-card);
box-shadow: var(--neu-raised-lg);
padding: 28px 28px 24px;
}
.card-label {
font-size: 0.7rem;
font-weight: 600;
letter-spacing: 1.5px;
text-transform: uppercase;
color: var(--text-light);
margin-bottom: 20px;
}
/* ── Profile Card ── */
.profile-card {
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
padding: 36px 28px 28px;
}
.avatar-wrap {
position: relative;
width: 88px;
height: 88px;
}
.avatar {
width: 88px;
height: 88px;
border-radius: 50%;
background: var(--bg);
box-shadow: var(--neu-raised-lg);
display: flex;
align-items: center;
justify-content: center;
color: var(--text-muted);
position: relative;
z-index: 1;
transition: box-shadow 0.3s ease;
}
.avatar-ring {
position: absolute;
inset: -5px;
border-radius: 50%;
border: 2px solid transparent;
background: linear-gradient(135deg, var(--accent), var(--accent-alt)) border-box;
-webkit-mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0);
-webkit-mask-composite: destination-out;
mask-composite: exclude;
opacity: 0;
transition: opacity 0.3s ease;
}
.avatar-wrap:hover .avatar-ring {
opacity: 1;
}
.avatar-wrap:hover .avatar {
box-shadow: var(--neu-pressed);
}
.profile-name {
font-size: 1.3rem;
font-weight: 600;
color: var(--text-primary);
letter-spacing: -0.3px;
}
.profile-role {
font-size: 0.82rem;
color: var(--text-muted);
font-weight: 400;
margin-top: -10px;
}
.profile-stats {
display: flex;
align-items: center;
gap: 0;
background: var(--bg);
border-radius: 14px;
box-shadow: var(--neu-pressed-sm);
padding: 14px 20px;
width: 100%;
justify-content: space-around;
}
.stat-pill {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
}
.stat-value {
font-size: 1.1rem;
font-weight: 700;
color: var(--text-primary);
letter-spacing: -0.5px;
}
.stat-label {
font-size: 0.68rem;
color: var(--text-light);
font-weight: 400;
text-transform: uppercase;
letter-spacing: 0.8px;
}
.stat-divider {
width: 1px;
height: 32px;
background: linear-gradient(to bottom, transparent, rgba(163, 177, 198, 0.5), transparent);
}
/* ── Buttons ── */
.buttons-card {
}
.button-row {
display: flex;
gap: 14px;
flex-wrap: wrap;
}
.btn {
display: inline-flex;
align-items: center;
gap: 8px;
font-family: var(--font);
font-size: 0.82rem;
font-weight: 500;
padding: 12px 22px;
border-radius: var(--radius-pill);
border: none;
cursor: pointer;
background: var(--bg);
color: var(--text-primary);
letter-spacing: 0.3px;
transition: box-shadow 0.2s ease, transform 0.15s ease, color 0.2s ease;
outline: none;
}
/* Convex — raised, pops out */
.btn-convex {
box-shadow: var(--neu-raised);
color: var(--accent);
}
.btn-convex:hover {
box-shadow: -4px -4px 10px var(--shadow-light), 4px 4px 10px var(--shadow-dark);
}
.btn-convex:active,
.btn-convex.active {
box-shadow: var(--neu-pressed);
color: var(--accent);
transform: scale(0.98);
}
/* Concave — pressed in */
.btn-concave {
box-shadow: var(--neu-pressed);
color: var(--text-muted);
}
.btn-concave:hover {
color: var(--accent-alt);
}
.btn-concave:active {
box-shadow: inset -2px -2px 5px var(--shadow-light), inset 2px 2px 5px var(--shadow-dark);
transform: scale(0.98);
}
/* Flat — subtle raised */
.btn-flat {
box-shadow: var(--neu-raised-sm);
color: var(--text-muted);
font-weight: 400;
}
.btn-flat:hover {
box-shadow: var(--neu-raised);
color: var(--text-primary);
}
.btn-flat:active {
box-shadow: var(--neu-pressed-sm);
transform: scale(0.98);
}
/* Focus ring */
.btn:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 3px;
}
/* ── Input ── */
.input-card {
}
.input-group {
display: flex;
flex-direction: column;
gap: 10px;
}
.input-label {
font-size: 0.78rem;
font-weight: 500;
color: var(--text-muted);
letter-spacing: 0.4px;
}
.input-wrap {
position: relative;
}
.input-icon {
position: absolute;
left: 18px;
top: 50%;
transform: translateY(-50%);
color: var(--text-light);
pointer-events: none;
transition: color 0.2s ease;
}
.neu-input {
width: 100%;
background: var(--bg);
border: none;
border-radius: 14px;
box-shadow: var(--neu-pressed);
padding: 14px 18px 14px 44px;
font-family: var(--font);
font-size: 0.88rem;
font-weight: 400;
color: var(--text-primary);
outline: none;
transition: box-shadow 0.25s ease;
}
.neu-input::placeholder {
color: var(--text-light);
}
.neu-input:focus {
box-shadow: inset -3px -3px 8px var(--shadow-light), inset 3px 3px 8px var(--shadow-dark), 0 0 0
2px rgba(108, 99, 255, 0.25);
}
.input-wrap:focus-within .input-icon {
color: var(--accent);
}
/* ── Badges ── */
.badges-card {
}
.badge-row {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.badge {
display: inline-flex;
align-items: center;
padding: 6px 16px;
border-radius: var(--radius-pill);
font-size: 0.74rem;
font-weight: 500;
letter-spacing: 0.4px;
background: var(--bg);
color: var(--text-muted);
box-shadow: var(--neu-raised-sm);
transition: box-shadow 0.2s ease, color 0.2s ease;
cursor: default;
user-select: none;
}
.badge:hover {
box-shadow: var(--neu-raised);
color: var(--text-primary);
}
.badge-accent {
box-shadow: var(--neu-pressed-sm);
color: var(--accent);
}
.badge-accent:hover {
box-shadow: var(--neu-pressed);
}
/* ── Responsive ── */
@media (max-width: 480px) {
.button-row {
flex-direction: column;
}
.btn {
justify-content: center;
}
.page-main {
padding: 0 16px;
}
.header-inner {
flex-direction: column;
text-align: center;
gap: 12px;
}
}/* ============================================================
Neumorphism — Interactive Effects
Convex press, ripple on click, badge toggle
============================================================ */
(function () {
"use strict";
// ── Button press state ──────────────────────────────────────
const primaryBtn = document.getElementById("btn-primary");
const secondaryBtn = document.getElementById("btn-secondary");
function addPressEffect(btn) {
if (!btn) return;
btn.addEventListener("mousedown", () => btn.classList.add("active"));
btn.addEventListener("mouseup", () => btn.classList.remove("active"));
btn.addEventListener("mouseleave", () => btn.classList.remove("active"));
}
addPressEffect(primaryBtn);
// ── Badge toggle (active/inactive) ─────────────────────────
const badges = document.querySelectorAll(".badge");
badges.forEach((badge) => {
badge.addEventListener("click", () => {
badge.classList.toggle("badge-accent");
});
});
// ── Ripple effect on convex button ─────────────────────────
if (primaryBtn) {
primaryBtn.addEventListener("click", function (e) {
const rect = primaryBtn.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const ripple = document.createElement("span");
ripple.className = "neu-ripple";
ripple.style.cssText = `
position: absolute;
left: ${x}px;
top: ${y}px;
width: 0;
height: 0;
border-radius: 50%;
background: rgba(108, 99, 255, 0.18);
transform: translate(-50%, -50%);
pointer-events: none;
animation: neu-ripple-anim 0.55s ease-out forwards;
`;
primaryBtn.style.position = "relative";
primaryBtn.style.overflow = "hidden";
primaryBtn.appendChild(ripple);
ripple.addEventListener("animationend", () => ripple.remove());
});
}
// Inject keyframe for ripple
const style = document.createElement("style");
style.textContent = `
@keyframes neu-ripple-anim {
to {
width: 160px;
height: 160px;
opacity: 0;
}
}
`;
document.head.appendChild(style);
// ── Input focus glow label ──────────────────────────────────
const input = document.getElementById("neu-input");
const label = document.querySelector(".input-label");
if (input && label) {
input.addEventListener("focus", () => {
label.style.color = "#6C63FF";
label.style.transition = "color 0.2s ease";
});
input.addEventListener("blur", () => {
label.style.color = "";
});
}
})();<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Neumorphism — Soft UI</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<!-- Header -->
<header class="neu-header">
<div class="header-inner">
<div class="logo-mark">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="10"/>
<path d="M8 12h8M12 8v8"/>
</svg>
</div>
<div class="header-text">
<h1 class="header-title">Neumorphism</h1>
<p class="header-tagline">Soft UI — sculpted from light & shadow</p>
</div>
</div>
</header>
<!-- Main content -->
<main class="page-main">
<!-- Profile Card -->
<section class="neu-card profile-card">
<div class="avatar-wrap">
<div class="avatar">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/>
<circle cx="12" cy="7" r="4"/>
</svg>
</div>
<div class="avatar-ring"></div>
</div>
<div class="profile-info">
<h2 class="profile-name">Maya Solis</h2>
<p class="profile-role">Senior Product Designer</p>
</div>
<div class="profile-stats">
<div class="stat-pill">
<span class="stat-value">248</span>
<span class="stat-label">Projects</span>
</div>
<div class="stat-divider"></div>
<div class="stat-pill">
<span class="stat-value">14k</span>
<span class="stat-label">Followers</span>
</div>
<div class="stat-divider"></div>
<div class="stat-pill">
<span class="stat-value">96%</span>
<span class="stat-label">Rating</span>
</div>
</div>
</section>
<!-- Buttons -->
<section class="neu-card buttons-card">
<h3 class="card-label">Controls</h3>
<div class="button-row">
<button class="btn btn-convex" id="btn-primary">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
Get Started
</button>
<button class="btn btn-concave" id="btn-secondary">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"><circle cx="12" cy="12" r="10"/><path d="M12 8v4l3 3"/></svg>
Schedule
</button>
<button class="btn btn-flat" id="btn-ghost">
Learn More
</button>
</div>
</section>
<!-- Input -->
<section class="neu-card input-card">
<h3 class="card-label">Search</h3>
<div class="input-group">
<label class="input-label" for="neu-input">Find a designer</label>
<div class="input-wrap">
<svg class="input-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
<circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/>
</svg>
<input class="neu-input" id="neu-input" type="text" placeholder="Search by name or skill…" />
</div>
</div>
</section>
<!-- Badges -->
<section class="neu-card badges-card">
<h3 class="card-label">Skills</h3>
<div class="badge-row">
<span class="badge badge-accent">UI Design</span>
<span class="badge">Figma</span>
<span class="badge">Prototyping</span>
<span class="badge badge-accent">Motion</span>
<span class="badge">Research</span>
<span class="badge">Systems</span>
</div>
</section>
</main>
<script src="script.js"></script>
</body>
</html>Neumorphism
Neumorphism (short for “new skeuomorphism”) is a UI design trend that makes elements appear to physically extrude from or press into a shared background surface. Rather than casting a shadow downward onto a different background, neumorphic elements share the exact same color as their parent — with two opposing shadows creating the illusion of depth. One light shadow is cast toward the top-left, the other darker shadow toward the bottom-right.
The result is a soft, tactile, almost clay-like interface. Every element feels like it was molded from the same material — buttons appear as raised bumps, pressed inputs appear inset into the surface, and cards feel like gentle reliefs on the page.
The critical constraint is the strict monochromatic palette. Because the shadow trick only works when element and background share the same hue, you cannot introduce high-contrast colors without breaking the illusion. Accent colors like indigo or steel blue are reserved sparingly for active states and focus indicators.
Key characteristics
- Background and all element backgrounds share the identical base color (
#E0E5EC) - Every raised surface uses two shadows: light white-ish on top-left, muted gray-blue on bottom-right
- Pressed / concave elements invert the shadows to
insetdirections - Zero or very subtle borders — the form is defined purely by shadow
- Muted, desaturated typography keeps text from jumping out of the tactile surface
- Focus/active accents use a single indigo or steel-blue pop
When to use
- Dashboard UIs and control panels where a calm, premium feel is desired
- Music players, smart home controls, wearable companion apps
- Settings screens and preference panels
- Any context where a “physical knob” or “molded surface” metaphor suits the product