UI Components Easy
Phone Mockup
Mobile phone frame (iOS-style notch) to showcase app screenshots or UI demos.
Open in Lab
MCP
css
Targets: HTML
Code
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: Inter, system-ui, sans-serif;
background: #050910;
color: #f2f6ff;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
}
.demo {
width: 100%;
max-width: 360px;
text-align: center;
}
.demo-title {
font-size: 1.5rem;
font-weight: 800;
margin-bottom: 0.375rem;
}
.demo-sub {
color: #475569;
font-size: 0.875rem;
margin-bottom: 2rem;
}
/* ── Phone wrapper (for side buttons) ── */
.phone-wrap {
position: relative;
display: inline-block;
width: 240px;
}
/* ── Side buttons ── */
.phone-buttons {
position: absolute;
}
.side-btn {
position: absolute;
background: #1e293b;
border-radius: 2px 0 0 2px;
}
.side-btn--silent {
left: -8px;
top: 60px;
width: 7px;
height: 22px;
}
.side-btn--vol-up {
left: -8px;
top: 100px;
width: 7px;
height: 36px;
}
.side-btn--vol-down {
left: -8px;
top: 144px;
width: 7px;
height: 36px;
}
.side-btn--power {
right: -8px;
top: 110px;
width: 7px;
height: 52px;
border-radius: 0 2px 2px 0;
}
/* ── Phone frame ── */
.phone-frame {
width: 240px;
background: #0f172a;
border-radius: 2.5rem;
border: 1.5px solid rgba(255, 255, 255, 0.12);
padding: 0.875rem;
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5), inset 0 0 0 1px rgba(255, 255, 255, 0.04), 0 40px 80px
rgba(0, 0, 0, 0.8);
position: relative;
overflow: hidden;
}
/* Gloss sheen */
.phone-frame::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
height: 50%;
background: linear-gradient(to bottom, rgba(255, 255, 255, 0.04) 0%, transparent 100%);
border-radius: 2.5rem 2.5rem 0 0;
pointer-events: none;
z-index: 10;
}
/* ── Notch area ── */
.phone-notch {
display: flex;
justify-content: center;
margin-bottom: 0.375rem;
}
.dynamic-island {
width: 80px;
height: 24px;
background: #000;
border-radius: 999px;
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 0.5rem;
gap: 0.3rem;
}
.island-camera {
width: 10px;
height: 10px;
border-radius: 50%;
background: #1e293b;
border: 1px solid rgba(255, 255, 255, 0.08);
position: relative;
}
.island-camera::after {
content: "";
position: absolute;
inset: 3px;
border-radius: 50%;
background: rgba(56, 189, 248, 0.3);
}
/* ── Screen ── */
.phone-screen {
background: #0a0e1a;
border-radius: 1.5rem;
overflow: hidden;
min-height: 440px;
display: flex;
flex-direction: column;
}
/* ── Status bar ── */
.status-bar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.5rem 1rem 0.25rem;
flex-shrink: 0;
}
.status-time {
font-size: 0.75rem;
font-weight: 700;
color: #f2f6ff;
}
.status-icons {
display: flex;
align-items: center;
gap: 0.3rem;
color: #f2f6ff;
}
/* ── App screen ── */
.app-screen {
flex: 1;
padding: 0.75rem 1rem 0.5rem;
display: flex;
flex-direction: column;
gap: 1rem;
background: radial-gradient(ellipse at 50% 0%, rgba(124, 58, 237, 0.3) 0%, transparent 60%),
#0a0e1a;
}
/* Album art */
.album-art {
width: 100%;
aspect-ratio: 1;
border-radius: 1rem;
overflow: hidden;
position: relative;
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.6);
}
.album-gradient {
width: 100%;
height: 100%;
background: linear-gradient(135deg, #7c3aed 0%, #2563eb 40%, #0891b2 70%, #059669 100%);
}
.album-shine {
position: absolute;
inset: 0;
background: linear-gradient(135deg, rgba(255, 255, 255, 0.12) 0%, transparent 60%);
}
/* Track info */
.track-info {
flex-shrink: 0;
}
.track-actions {
display: flex;
align-items: center;
gap: 0.5rem;
}
.track-text {
flex: 1;
display: flex;
flex-direction: column;
gap: 0.125rem;
}
.track-title {
font-size: 0.9rem;
font-weight: 700;
color: #f2f6ff;
}
.track-artist {
font-size: 0.75rem;
color: #64748b;
}
.track-action {
background: none;
border: none;
color: #475569;
cursor: pointer;
padding: 0.25rem;
transition: color 0.15s;
}
.track-action:hover {
color: #94a3b8;
}
/* Progress */
.progress-area {
flex-shrink: 0;
display: flex;
flex-direction: column;
gap: 0.375rem;
}
.progress-bar-track {
width: 100%;
height: 3px;
background: rgba(255, 255, 255, 0.12);
border-radius: 999px;
position: relative;
}
.progress-bar-fill {
height: 100%;
width: 43%;
background: #f2f6ff;
border-radius: 999px;
}
.progress-thumb {
position: absolute;
top: 50%;
left: 43%;
transform: translate(-50%, -50%);
width: 10px;
height: 10px;
border-radius: 50%;
background: #f2f6ff;
}
.progress-times {
display: flex;
justify-content: space-between;
font-size: 0.65rem;
color: #475569;
}
/* Player controls */
.player-controls {
display: flex;
align-items: center;
justify-content: space-between;
flex-shrink: 0;
}
.player-controls button {
background: none;
border: none;
color: #94a3b8;
cursor: pointer;
padding: 0.25rem;
transition: color 0.15s;
}
.player-controls button:hover {
color: #f2f6ff;
}
.play-btn {
width: 3rem;
height: 3rem;
border-radius: 50% !important;
background: #f2f6ff !important;
color: #0a0e1a !important;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
}
/* Volume */
.volume-area {
display: flex;
align-items: center;
gap: 0.5rem;
flex-shrink: 0;
color: #475569;
}
.volume-track {
flex: 1;
height: 3px;
background: rgba(255, 255, 255, 0.12);
border-radius: 999px;
}
.volume-fill {
height: 100%;
width: 70%;
background: rgba(255, 255, 255, 0.4);
border-radius: 999px;
}
/* ── Home indicator ── */
.home-indicator {
width: 80px;
height: 4px;
background: rgba(255, 255, 255, 0.3);
border-radius: 999px;
margin: 0.75rem auto 0;
}<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Phone Mockup</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="demo">
<h1 class="demo-title">Phone Mockup</h1>
<p class="demo-sub">iOS-style phone frame for app demos and screenshots.</p>
<div class="phone-wrap" role="img" aria-label="Phone mockup showing app UI">
<!-- Side buttons -->
<div class="phone-buttons" aria-hidden="true">
<div class="side-btn side-btn--silent"></div>
<div class="side-btn side-btn--vol side-btn--vol-up"></div>
<div class="side-btn side-btn--vol side-btn--vol-down"></div>
<div class="side-btn side-btn--power"></div>
</div>
<!-- Phone frame -->
<div class="phone-frame" aria-hidden="true">
<div class="phone-notch">
<div class="dynamic-island">
<div class="island-camera"></div>
</div>
</div>
<!-- Screen -->
<div class="phone-screen">
<!-- Status bar -->
<div class="status-bar">
<span class="status-time">9:41</span>
<div class="status-icons">
<!-- Signal bars -->
<svg width="16" height="12" viewBox="0 0 16 12" fill="currentColor" aria-hidden="true">
<rect x="0" y="8" width="2.5" height="4" rx="0.5" opacity="0.4"/>
<rect x="3.5" y="5.5" width="2.5" height="6.5" rx="0.5" opacity="0.6"/>
<rect x="7" y="3" width="2.5" height="9" rx="0.5"/>
<rect x="10.5" y="0" width="2.5" height="12" rx="0.5"/>
</svg>
<!-- WiFi -->
<svg width="15" height="12" viewBox="0 0 24 18" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" aria-hidden="true">
<path d="M1 6C5 2 10.5 0 12 0s7 2 11 6" opacity="0.4"/>
<path d="M4.5 10C7 7.5 9.5 6 12 6s5 1.5 7.5 4" opacity="0.7"/>
<path d="M8 14c1-1 2.5-2 4-2s3 1 4 2"/>
<circle cx="12" cy="17" r="1.5" fill="currentColor" stroke="none"/>
</svg>
<!-- Battery -->
<svg width="24" height="12" viewBox="0 0 24 12" fill="currentColor" aria-hidden="true">
<rect x="0" y="1" width="21" height="10" rx="2" fill="none" stroke="currentColor" stroke-width="1.5"/>
<rect x="21.5" y="3.5" width="2.5" height="5" rx="1"/>
<rect x="1.5" y="2.5" width="15" height="7" rx="1.5"/>
</svg>
</div>
</div>
<!-- App content (dark music player UI) -->
<div class="app-screen">
<!-- Album art -->
<div class="album-art">
<div class="album-gradient"></div>
<div class="album-shine"></div>
</div>
<!-- Track info -->
<div class="track-info">
<div class="track-actions">
<button class="track-action" aria-label="Add to library">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M20.84 4.61a5.5 5.5 0 00-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 00-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 000-7.78z"/>
</svg>
</button>
<div class="track-text">
<span class="track-title">Midnight Drift</span>
<span class="track-artist">Aurora Wave</span>
</div>
<button class="track-action" aria-label="Options">
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
<circle cx="12" cy="5" r="1.5"/><circle cx="12" cy="12" r="1.5"/><circle cx="12" cy="19" r="1.5"/>
</svg>
</button>
</div>
</div>
<!-- Progress -->
<div class="progress-area">
<div class="progress-bar-track">
<div class="progress-bar-fill"></div>
<div class="progress-thumb"></div>
</div>
<div class="progress-times">
<span>1:42</span>
<span>3:58</span>
</div>
</div>
<!-- Controls -->
<div class="player-controls">
<button aria-label="Shuffle">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="16 3 21 3 21 8"/><line x1="4" y1="20" x2="21" y2="3"/>
<polyline points="21 16 21 21 16 21"/><line x1="15" y1="15" x2="21" y2="21"/>
</svg>
</button>
<button aria-label="Previous">
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor">
<path d="M19 20L9 12l10-8v16zM5 4h2v16H5z"/>
</svg>
</button>
<button class="play-btn" aria-label="Pause">
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor">
<rect x="6" y="4" width="4" height="16" rx="1"/>
<rect x="14" y="4" width="4" height="16" rx="1"/>
</svg>
</button>
<button aria-label="Next">
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor">
<path d="M5 4l10 8-10 8V4zM19 4h-2v16h2z"/>
</svg>
</button>
<button aria-label="Repeat">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 014-4h14"/>
<polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 01-4 4H3"/>
</svg>
</button>
</div>
<!-- Volume -->
<div class="volume-area">
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M11 5L6 9H2v6h4l5 4V5zM15.54 8.46a5 5 0 010 7.07"/>
</svg>
<div class="volume-track">
<div class="volume-fill"></div>
</div>
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M11 5L6 9H2v6h4l5 4V5zM15.54 8.46a5 5 0 010 7.07M19.07 4.93a10 10 0 010 14.14"/>
</svg>
</div>
</div>
</div>
<!-- Home indicator -->
<div class="home-indicator" aria-hidden="true"></div>
</div>
</div>
</div>
</body>
</html>Phone Mockup
An iOS-style phone frame for showcasing mobile app screenshots or UI demos. Includes the dynamic island notch, side buttons, status bar, and a realistic bezel — all in pure CSS.
Features
- Dynamic island cutout at the top (CSS clip or border-radius trick)
- Realistic side button details (volume, silent, power)
- Status bar with time, battery, and signal icons
- Inner content area — drop any
<img>or markup inside - Subtle reflection sheen on the frame via
::beforepseudo - Pure CSS, zero JavaScript
- Fits any aspect ratio content inside the screen
Usage
Replace the content inside .phone-screen with your app screenshot or live HTML demo. The frame automatically centers and scales to the container.