bezelkit · an open-source web component

Most mockups break your screenshots.

This is an iPhone 17 Pro screenshot, 1206 × 2622. Here's what a typical mockup does to it.

Scroll

width: 100%; height: 100%

Squashed.

The mockup's screen is 9:16. Your screenshot is 19.5:9, so it gets pressed 18% flat. Circles turn into ovals.

status bar: painted on

Doubled.

The frame draws its own status bar over the one already in your screenshot.

object-fit: cover

Sliced.

Cover keeps the shape but trims 80 px off each end. Your tab bar goes with it.

notch: z-index 10

Covered.

Then the painted-on notch lands on your header.

fit="auto"

Your screenshots,framed properly.

bezelkit draws the device's real screen in CSS pixels, compares it with your screenshot and picks the fit. This one matches the iPhone 17 Pro, so it maps 1:1.

bezelkit · an open-source web component

Most mockups break your screenshots.

The same iPhone 17 Pro screenshot, 1206 × 2622, four ways a typical mockup gets it wrong, and bezelkit.

device="…"

Every screen at its real size.

26 current frames, drawn in CSS. Screens use each device's published viewport, and frames scale to any width without blurring.

el.flip()

Turn it over.

An 800 ms turn to the back: camera plateau, finish, mirrored buttons. All CSS. No photos, no logos.

side="both"

Both sides, one tag.

The back tilts in behind the front, ready for a product shot. Pick a finish.

Install

One tag.
No build step.

<script type="module" src="https://cdn.jsdelivr.net/npm/bezelkit@0/dist/bezelkit.js"></script>
<bezel-device
  device="iphone-17-pro"
  src="screenshot.png">
</bezel-device>

Zero dependencies. The same tag works in plain HTML, React 19, Vue, Svelte, Astro, MDX and Markdown docs. Screens also take a video, a URL or your own HTML, and stay clickable.

iphone-17-pro · 402 × 874

Try it

Four ways to fit, picked for you

bezelkit compares your image's shape with the device's real screen and uses whichever strategy loses the least. These are live frames, not pictures.

Playground

Drop in your own screenshot, recording, or URL. Everything here runs locally in your browser.

Colour
Content
Drop an image or video here, or browse
Fit
Orientation
Status bar & home indicator
Theme · Glare

41 frames and counting

Each one is drawn in CSS at the device's real viewport, so it stays sharp at any size. Pick a device to try it in the playground.

API

Using an AI assistant?

Point it at bezelkit.dev/llms-full.txt. It has every attribute, the fit rules, framework notes and all 41 devices with their screenshot resolutions, so Claude, ChatGPT or Cursor can wire it up for you.

One element for plain HTML, React 19, Vue, Svelte and Astro. Give it a width and it scales; give it a width and height and it fits inside both. The full reference is in the README.

AttributeValuesWhat it does
deviceiphone-17-pro … see aboveWhich frame to render.
srcimage · video · URLType is detected from the extension; URLs become a live iframe at the true viewport. Omit it to slot your own HTML.
fitauto cover top contain scroll fillauto picks for you, as shown above.
color · orientationfinish name · landscapeOfficial finishes or any CSS colour; content rotates with the device.
side · variant · foldedback both · deck 3d · booleanBack panels and stacked shots, 3D laptops and desktops, and foldables. flip(), fold() and open() animate them.
chrome · safe-areaauto on off · pad noneStatus bar and home indicator, and keeping live HTML clear of the notch.

Frame your first screenshot.

Drop one on the phone. It stays in your browser. bezelkit reads its size and tells you which fit it picked.

★ Star on GitHub

Drop a screenshot here.