A zero-dependency, single-file web app that renders any HTML file or URL inside real device frames.
๐ Try it live โ
๐ https://tekideki.github.io/Mobile-Preview/
No installation, no sign-up. Works offline once loaded.
Mobile Preview is a browser-based device simulator. Load a local .html file or paste any URL, and instantly see it rendered inside accurate frames for phones, tablets and desktops - with the real viewport dimensions of each device.
Perfect for:
- ๐งโ๐ป Developers checking responsive layouts without opening DevTools
- ๐จ Designers presenting mockups in realistic device frames
- โ๏ธ Bloggers & marketers grabbing screenshots at exact device sizes
- ๐งช QA testers comparing how a page behaves across device widths
Everything runs 100% client-side. Nothing is uploaded, tracked, or sent anywhere.
- ๐ฑ 12 real devices - iPhone SE/12/14 Pro/15 Pro Max, Pixel 7, Galaxy S23, iPad Mini/Air/Pro 11"/12.9", Galaxy Tab S8, Desktop
- ๐ 13 aspect ratios - 1:1, 4:3, 3:2, 16:10, 5:3, 16:9, 18:9, 18.5:9, 19:9, 19.5:9, 20:9, 21:9, 9:16 (Stories/Reels)
- โ๏ธ Custom mode - any width ร height from 100 to 4000 px, with phone / tablet / no-frame rendering and scale control
- ๐ Load local HTML files - pick a file or drag and drop it anywhere on the preview area
- ๐ Load any URL - paste a link, or just a host name (
example.combecomeshttps://example.com/); onlyhttpandhttpsare accepted - ๐ Orientation toggle - portrait โ landscape; the frame always follows the orientation you picked, whichever ratio is selected
- ๐ Zoom control - 25% to 200%, plus auto-fit so the frame always fits the viewport
- ๐งฐ Collapsible tools on phones - the toolbar folds away so the frame gets the room; one tap brings it back
- โฑ๏ธ Number fields stay honest - values outside their range are clamped and the app says so instead of silently resizing the frame
- ๐พ Every setting resets in one tap - including panel inputs, with a confirmation toast
- ๐ 4 languages - Romรขnฤ, English, Srpski (latinica), ะกัะฟัะบะธ (ัะธัะธะปะธัะฐ); every tooltip and accessible name follows the language
- ๐ Dark & light theme - follows your system, remembers your choice; URL override with
?theme=light, applied before the first paint (no white flash) - ๐ Shareable state via URL -
?lang=en,?theme=dark,?mode=ratio,?focus=url - ๐ฆ Installable PWA - four app shortcuts (URL, Devices, Ratios, Custom), offline shell, and an in-app notice when a new version is cached
- ๐ชถ Zero dependencies - one HTML file, no frameworks, no build step, no CDN, no analytics
- ๐ SEO-ready - JSON-LD (WebApplication with feature list), Open Graph, Twitter cards with alt text, canonical,
hreflangalternates, sitemap - โฟ Accessible - real
main/header/footerlandmarks, labelled inputs,aria-pressedtoggles, keyboard-navigable tab list (arrows/Home/End), live regions for results and toasts, WCAG AA contrast in both themes,prefers-reduced-motion - ๐ก๏ธ Previews are properly isolated - see below
The frame is the core of this tool, so the sandbox matters:
| Content | Sandbox | Why |
|---|---|---|
| Local files and anything you type | allow-scripts allow-forms allow-popups allow-modals |
The page has no allow-same-origin: it runs in an opaque origin, cannot read parent.document, cannot touch this app's localStorage, cannot rewrite its title, and cannot open a tab back into it |
Remote sites (https://โฆ) |
the same, plus allow-same-origin |
so the page keeps its own cookies and storage and renders realistically - it is still a separate origin from this app |
Both local files and URLs are loaded through iframe.srcdoc / iframe.src, never through document.write, so no previewed code ever executes in this app's own document.
Some sites still refuse to load in a frame (they send X-Frame-Options or a CSP frame-ancestors). The app says so in the empty state and suggests a local file - that is a browser decision, not a bug.
๐ https://tekideki.github.io/Mobile-Preview/
git clone https://github.com/TekiDeki/Mobile-Preview.git
cd Mobile-Preview
# any static server works
python -m http.server 8000Then open http://localhost:8000
๐ก For PWA features (install prompt, offline mode) serve over HTTPS or
localhost.
- Fork this repository
- Settings โ Pages
- Source:
Deploy from a branchโ Branch:mainโ Folder:/ (root) - Save โ live at
https://YOUR-USERNAME.github.io/Mobile-Preview/
| Platform | Steps |
|---|---|
| Android (Chrome) | โฎ menu โ Install app |
| iPhone / iPad (Safari) | Share button โ Add to Home Screen |
| Desktop (Chrome / Edge) | Click the install icon (โ) in the address bar |
Once installed it launches full-screen and works without a connection. Four shortcuts are available from a long press on the icon: URL, Devices, Ratios, Custom.
- Load content - click ๐ Load file to pick a local
.html, drop a file onto the preview area, or paste a URL and hit ๐ Load URL - Pick a mode:
- ๐ฑ Devices - choose one of 12 real device presets
- ๐ Aspect ratio - pick a ratio, then set the base size and display scale
- โ๏ธ Custom - enter any width ร height, choose frame type and scale
- Fine-tune - toggle orientation, adjust zoom, reload, or open the preview in a new tab
- Reset - returns every control to its default (iPhone 12, portrait, 100%, 390 px base size)
| Action | How |
|---|---|
| Move between mode tabs | Tab to the tab list, then โ / โ (or Home / End) |
| Activate a device, ratio or button | Tab to it and press Enter / Space |
| Load a URL | Focus the URL field and press Enter |
| Code | Language | Default |
|---|---|---|
ro |
Romรขnฤ | โ (fallback) |
en |
English | - (auto-detected from browser) |
sr-Latn |
Srpski (latinica) | - |
sr-Cyrl |
ะกัะฟัะบะธ (ัะธัะธะปะธัะฐ) | - |
Language priority: URL parameter (?lang=โฆ) โ saved choice โ browser language โ Romanian.
- HTML5 - one file, semantic markup with landmarks
- CSS3 - custom properties for theming (dark + light token sets), flex layout
- Vanilla JavaScript - no frameworks, no bundler, no build step
- Service Worker - cache-first shell, never intercepts your preview URLs, posts a message when a new version replaces the old cache
- Web App Manifest - installable, standalone, icons, screenshots and four shortcuts
- JSON-LD - structured data (
WebApplicationwithfeatureList)
No external CDNs. No analytics. No fonts to download. No tracking.
Mobile-Preview/
โโโ index.html # Standalone app (HTML + CSS + JS)
โโโ manifest.json # PWA manifest (icons, screenshots, shortcuts)
โโโ sw.js # Service worker (offline shell)
โโโ icon-192.png # App icon
โโโ icon-512.png # App icon (large)
โโโ icon-maskable-512.png # Maskable icon (Android)
โโโ apple-touch-icon.png # iOS home screen icon
โโโ favicon.ico
โโโ og-image.png # Social share image (1200x630)
โโโ screenshot-narrow.png # Phone screenshot (manifest + README)
โโโ screenshot-wide.png # Desktop screenshot (manifest + README)
โโโ robots.txt
โโโ sitemap.xml # with hreflang alternates
โโโ LICENSE # Apache License 2.0
โโโ NOTICE
โโโ README.md
- No backend, no accounts, no cookies, no analytics
- No preview content is uploaded, cached or stored: the app reads your file locally and hands it to the frame. Reopening the app always starts with an empty frame, and the interface says so
- Previewed URLs are loaded directly by your browser into a sandboxed iframe - the app never sees them
- Language, theme and tools-panel preferences are stored in
localStorageonly, and the app keeps working when storage is blocked (private mode)
- Device, ratio, custom and zoom geometry verified against the real pixel sizes
- Sandbox escape attempts (reading the parent document, the app's storage, the frame element, rewriting its title) all blocked
- URL handling:
javascript:,data:andfile:inputs rejected - 4 languages ร dark/light, offline reload, blocked storage, drag and drop, manifest and asset checks
- Automated accessibility scan (axe-core) with no violations in either theme
Distributed under the Apache License 2.0. See LICENSE and NOTICE for details.
- Security: local files are rendered without
allow-same-origin, so a previewed file can no longer read this app's DOM, itslocalStorageor its title; local files are delivered throughsrcdocinstead of a same-originblob:URL. - Security: URL input accepts only real
http/httpsaddresses -javascript:,data:andfile:are rejected. - Fixed: aspect-ratio mode ignored the chosen orientation for wide ratios (16:9 portrait built a landscape frame); orientation now drives the frame.
- Fixed: saved light theme flashed dark on load; the theme is applied before the first paint.
- Fixed:
localStoragewas used unguarded; it now has a safe wrapper with an in-memory fallback for private mode. - Fixed: number fields accepted values far outside their declared range (9999 px base size, 99999 px width) and silently shrank the frame; values are clamped and the change is reported.
- Fixed: the empty frame was rendered on top of the empty state before anything was loaded.
- Fixed: the stale requirement to press
?in a shared link (nothing handled it) - the hint now describes what the app really supports. - Fixed:
resetleft the panel inputs and the ratio selection untouched and gave no feedback. - New: drag and drop of
.htmlfiles onto the preview area, with a visible drop hint and a refusal message for other file types. - New: collapsible tools panel on phones, so the device frame gets the room.
- New: a notice appears when the service worker caches a new version, with a reload button.
- New: open in a new tab now works for local files too (temporary object URL), and the tab never gets a handle on this window.
- Improved: real tab list for the three modes (arrows, Home/End,
aria-selected),aria-pressedon toggles, labelled inputs,main/header/footerlandmarks, live regions for zoom, toasts and the update bar, every tooltip and accessible name translated in all four languages. - Improved: WCAG AA contrast - filled buttons and active tabs use a darker accent for white text; hint and label colours raised in both themes; focus rings 3 px.
- Improved:
?mode=,?focus=and?theme=parameters, manifest screenshots and four app shortcuts, JSON-LD feature list,og:image:alt,color-schememeta,<noscript>note, 8 MB file size guard, unsaved-preview notice. - Improved: offline cache bumped to
mobile-preview-v6(now includes the screenshots and the social image).
- 1.0 - first public release: 12 device presets, 13 aspect ratios, custom sizes, local files and URLs, four languages, dark/light themes, installable PWA with offline shell.
Built with โค๏ธ and vanilla JavaScript
Use the Install app button near the footer. On supported browsers it opens the native installation prompt when available. Otherwise it shows localized instructions for Safari on iPhone/iPad, Android, and desktop browsers. Installation is controlled by the browser; no installation is claimed without its confirmation. The button is hidden in a standalone/minimal-ui app window and after an appinstalled event in the current session. A normal browser tab cannot always detect a previous installation.
Installation needs HTTPS or trustworthy localhost. The controls add no dependencies, tracking, network calls or storage keys; existing application data is not modified. On an existing cached version, revisit online and refresh after the service worker has updated to see the button. No automatic reload is forced.