PWA Icons — Web App Manifest Icons, Maskable Icons, and Apple Touch Icons
Progressive Web Apps need icons in multiple sizes for home screens, app switchers, and splash screens. Learn how to configure web manifest icons, create maskable icons, and set...
PWAs need a manifest.json with correctly sized icons to be installable. Missing sizes, wrong MIME types, or forgetting maskable purpose prevent installation on some platforms.
Generate your base favicon and icons with the Favicon Generator.
Web App Manifest icon configuration
{
"name": "My App",
"short_name": "App",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#3b82f6",
"icons": [
{
"src": "/icons/icon-72x72.png",
"sizes": "72x72",
"type": "image/png"
},
{
"src": "/icons/icon-96x96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "/icons/icon-128x128.png",
"sizes": "128x128",
"type": "image/png"
},
{
"src": "/icons/icon-144x144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "/icons/icon-152x152.png",
"sizes": "152x152",
"type": "image/png"
},
{
"src": "/icons/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/icons/icon-384x384.png",
"sizes": "384x384",
"type": "image/png"
},
{
"src": "/icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
The minimum installable set: 192×192 and 512×512. Chrome requires 512×512 to show an install prompt.
Maskable icons
Android 8+ applies adaptive icon shapes (circle, squircle, etc.) to app icons. Without maskable purpose, Android uses the full square image without applying the device’s shape.
{
"icons": [
{
"src": "/icons/icon-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any"
},
{
"src": "/icons/icon-maskable-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
}
]
}
Maskable icon safe zone: The center 80% of the image (a circle inscribed in 80% of the total area). Keep all important content within this circle — the outer 10% on each side can be clipped by the device shape.
Total icon: 192×192px
Safe zone: ~154px circle in center (80% of 192 = 153.6)
Padding: ~19px on each side
Design your maskable icon with the entire canvas filled (no transparent border). Test at maskable.app.
Apple Touch Icon
iOS Safari ignores the Web App Manifest. Use <link> tags in <head>:
<!-- Apple touch icons (iOS/iPadOS) -->
<link rel="apple-touch-icon" sizes="180x180" href="/icons/apple-touch-icon.png">
<link rel="apple-touch-icon" sizes="152x152" href="/icons/apple-touch-icon-152x152.png">
<link rel="apple-touch-icon" sizes="120x120" href="/icons/apple-touch-icon-120x120.png">
<link rel="apple-touch-icon" sizes="76x76" href="/icons/apple-touch-icon-76x76.png">
<!-- Fallback for older iOS: just name it apple-touch-icon.png in root -->
<!-- iOS finds /apple-touch-icon.png and /apple-touch-icon-precomposed.png automatically -->
<!-- Splash screens (optional but recommended) -->
<link rel="apple-touch-startup-image" href="/icons/splash-2048x2732.png"
media="(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2)">
The most important Apple touch icon size is 180×180 (for iPhone with 3× retina display).
Generate icons with sharp (Node.js)
import sharp from 'sharp'; // npm install sharp
const ICON_SIZES = [72, 96, 128, 144, 152, 180, 192, 384, 512];
async function generateIcons(inputSvg) {
for (const size of ICON_SIZES) {
await sharp(inputSvg)
.resize(size, size)
.png()
.toFile(`public/icons/icon-${size}x${size}.png`);
console.log(`Generated ${size}×${size}`);
}
// Maskable icon: add padding (10% on each side = 20% total padding)
const maskableSize = 192;
const iconSize = Math.round(maskableSize * 0.8); // 154px
const padding = Math.round((maskableSize - iconSize) / 2); // 19px
await sharp(inputSvg)
.resize(iconSize, iconSize)
.extend({
top: padding,
bottom: padding,
left: padding,
right: padding,
background: { r: 59, g: 130, b: 246, alpha: 1 }, // brand color
})
.resize(maskableSize, maskableSize)
.png()
.toFile(`public/icons/icon-maskable-${maskableSize}x${maskableSize}.png`);
}
generateIcons('src/logo.svg');
Vite PWA plugin (recommended for Vite projects)
// vite.config.js
import { VitePWA } from 'vite-plugin-pwa';
export default {
plugins: [
VitePWA({
registerType: 'autoUpdate',
manifest: {
name: 'My App',
short_name: 'App',
icons: [
{
src: 'icons/icon-192x192.png',
sizes: '192x192',
type: 'image/png',
},
{
src: 'icons/icon-512x512.png',
sizes: '512x512',
type: 'image/png',
purpose: 'any maskable',
},
],
},
}),
],
};
Using "purpose": "any maskable" on the same image works, but dedicated maskable icons (with padding) look better on Android adaptive shapes.
Icon checklist
| Icon | Size | Purpose |
|---|---|---|
icon-192x192.png | 192×192 | Android install |
icon-512x512.png | 512×512 | Chrome install prompt, splash screen |
icon-maskable-192x192.png | 192×192 | Android adaptive icon |
apple-touch-icon.png | 180×180 | iOS home screen |
favicon.ico | 16, 32, 48 in ICO | Browser tab |
favicon.svg | Scalable | Modern browsers |
Related tools
- Favicon Generator — generate all icon sizes from one image
- Image Compressor — optimize PNG icons for smaller file size
- Base64 Encoder — encode small icons as inline data URIs
Related posts
- Apple Touch Icon — Add an iOS Home Screen Icon to Your Website — The apple-touch-icon is the image iOS uses when someone adds your site to their …
- Favicon Caching — Force Browser Refresh After Favicon Change — Browsers aggressively cache favicons, sometimes for days or weeks. Learn how to …
- Favicon ICO — Create and Implement .ico Files for Your Website — The favicon.ico file is the icon shown in browser tabs, bookmarks, and history. …
- SVG Favicon — Modern Vector Favicons for Any Screen — SVG favicons scale perfectly at any size and support dark mode via CSS media que…
Related tool
Generate favicon package from any image or emoji. Multiple sizes (16, 32, 48, 180, 192, 512), manifest.json, and HTML snippet.
Written by Mian Ali Khalid. Part of the Frontend & Design pillar.