Phone Mockup — Free CSS iPhone Device Frame Snippet

Phone Mockup · Layouts · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Pure-CSS frame
No phone image — crisp at any size and theme-able.
Nested-radius bezel
Inner and outer radii create a realistic rim.
Dynamic island
A single positioned pill floats over the screen.
Hardware buttons
Volume and power slivers on the frame edges.
Live, scrollable screen
Real DOM content, not a static picture.
CSS status bar
SVG signal, wifi, and a battery with a fill.
Dark-mode toggle
Swap the screen theme with one class.
No dependency
Pure HTML/CSS/JS for mockups and showcases.

About this UI Snippet

Phone Mockup — Pure-CSS Device Frame for App Screens

Screenshot of the Phone Mockup snippet rendered live

A phone mockup is a device frame you drop a screen design into — for landing pages, app-store shots, portfolio pieces, and design presentations. This one is built entirely in HTML and CSS (no image of a phone), so it's crisp at any size, theme-able, and you can put live, scrolling, interactive content inside it. It ships with a sample finance app screen and a live status-bar clock, in vanilla JavaScript with no dependency.

The frame from nested rounded rectangles

The body is a dark rounded box with heavy padding, and the screen is an inner rounded box — the gap between their border-radius values creates the realistic bezel curve where a smaller radius nested inside a larger one reads as a uniform-width rim. An inset box-shadow adds a subtle metal edge, and a large soft drop shadow lifts the whole device off the page. No device photo is involved, so it scales losslessly.

Dynamic island and hardware buttons

The notch is a single absolutely-positioned pill (.pm-island) centered at the top with a high z-index so it floats over the screen content. The volume and power buttons are thin absolutely-positioned slivers hanging off the frame's left and right edges — tiny details that sell the realism for the cost of three empty spans.

A real, scrollable screen — not a picture

Because the screen is live DOM, the app inside it actually works: overflow-y:auto makes the transaction list scroll within the device, the status bar shows a CSS-drawn battery and signal bars, and a toggle switches the screen to dark mode by swapping one class. This is the advantage of a CSS mockup over an image — you can demo genuine interaction, dark mode, and responsive content in context.

The CSS-drawn status bar

The signal bars are four <rect>s of increasing height in a tiny inline SVG, the wifi glyph is a stroked arc, and the battery is a bordered box with a nub pseudo-element (::after) and a percentage fill — all currentColor, so they invert automatically in dark mode. A live clock updates the time so it never looks frozen.

Reusing it as a wrapper

Replace the .pm-app contents with your own screen and the frame becomes a reusable container for any mobile UI. Keep the device markup as a component and pass children into the screen slot — ideal for showcasing a mobile login screen or onboarding flow on a marketing page.

Build with AI

Build, Understand, Optimize, and Extend It With AI

You don't have to work out the bezel geometry by trial and error. Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly why nesting two rounded rectangles with different border-radius values and a fixed padding gap produces a convincing uniform-width bezel, and how the currentColor-based status bar icons automatically invert when the .dark class is toggled on the screen. The same assistant can help optimize it, for example checking whether the setInterval-driven clock should instead sync to the top of the next minute rather than polling every 10 seconds, or whether the absolutely-positioned notch and side buttons hold up correctly at different frame sizes. It's also useful for extending the effect: ask it to add a second device variant (a tablet or a different phone notch style), make the frame a reusable component with a content slot, or add a subtle screen-on animation when swapping app screens. Treat the code less like a finished artifact and more like a starting point for a conversation.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a pure-CSS iPhone-style device mockup frame in plain HTML, CSS, and vanilla JavaScript, with no image of a phone anywhere — the entire device must be drawn from CSS shapes.

Requirements:
- An outer rounded rectangle representing the phone body with a large border-radius and enough padding that an inner rounded rectangle (the screen) sits inset from it, with a slightly smaller border-radius than the outer shape, so the constant-width gap between the two reads as a realistic bezel. Add an inset box-shadow for a metal-edge highlight and a large soft drop shadow beneath the whole device.
- An absolutely-positioned pill-shaped "dynamic island" notch centered near the top of the screen, above the rest of the screen content in stacking order.
- Thin absolutely-positioned slivers along the left and right edges of the phone body representing volume and power hardware buttons.
- Inside the screen, a status bar row showing a live clock (updating at least once a minute) alongside CSS/SVG-drawn signal-strength bars, a wifi icon, and a battery indicator (a bordered box with a small nub and a fill amount), all using currentColor so they automatically restyle when a theme class changes.
- Below the status bar, a real scrollable app UI (not a static image) so the mockup demonstrates genuine interactive content — include at least one interactive control, such as a button that toggles the screen between a light and dark theme by adding or removing a single CSS class.
- Structure the markup so the device frame could be reused as a wrapper component around arbitrary app content, keeping the frame, notch, buttons, and status bar independent from whatever is placed inside the scrollable app area.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA CSS phone renders with a sample app screen inside it.
  2. 2
    Scroll the screenThe transaction list scrolls inside the device frame.
  3. 3
    Watch the clockThe status-bar time updates live like a real phone.
  4. 4
    Toggle dark modeOne class swaps the screen between light and dark.
  5. 5
    Drop in your screenReplace the app contents with your own mobile UI.
  6. 6
    Reuse as a wrapperKeep the frame as a component with a screen slot.

Real-world uses

Common Use Cases

App landing pages
Showcase a screen beside a product hero.
Portfolio and case studies
Frame work next to a bento grid gallery.
Design presentations
Present a mobile login screen in context.
Feature showcases
Pair with a tablet mockup for responsive demos.
Marketing screenshots
Wrap a music player for store-style shots.
Learning CSS device art
A reference for nested-radius bezels and CSS hardware.

Got questions?

Frequently Asked Questions

Pure CSS. The device is a dark rounded box with padding, the screen is a nested rounded box, and the gap between their border-radius values forms the bezel. The notch and side buttons are positioned spans. Because there's no photo, it stays sharp at any zoom and you can recolor or resize it freely.

Yes — that's the main advantage over a screenshot. The screen is live DOM, so content scrolls with overflow-y:auto, the status-bar clock ticks, and a class toggle switches the screen to dark mode. You can embed forms, lists, animations, or any other snippet and it behaves normally within the frame.

By nesting two rounded rectangles. The outer frame has a large border-radius and padding; the inner screen has a slightly smaller radius. The constant-width gap between them, plus an inset box-shadow for a metal edge, reads as a uniform bezel — a standard trick for CSS device frames that avoids any images.

Replace everything inside the .pm-app element with your markup. The frame, status bar, and scrolling are independent of the content, so your screen just needs to fit the screen width. Keeping the device portion as a reusable component lets you pass different screens in as children.

Make the device frame a component that renders a screen slot (children, a slot, or ng-content) so you can wrap any screen. Move the live-clock interval into a mount effect with cleanup. Toggle dark mode via a state-bound class. In Tailwind, build the frame with rounded-[46px], padding, and shadow utilities, and the status-bar icons with small inline SVGs.