On Android, a site's installed home-screen icon shows up shrunken inside a white circle rather than filling the shape. Which part of a web app manifest's `icons` entries controls that, and how do you author the asset?
answer
- the platform, not you, chooses the shape
- one member on each icon entry
- full-bleed art, cropped on purpose
- eighty percent, centred, circular
- a second asset, not a relabelled one
basics
~20 sThe icon entry's purpose member controls it. With the default purpose of any, the platform pads the icon onto a background shape; an entry marked purpose maskable tells it to crop your full-bleed asset to the device's mask instead.
solid answer
~50 sEach object in a manifest's `icons` array can carry a `purpose` member. The default, `"any"`, means the icon is a normal icon the platform may letterbox onto a solid background shape — which is exactly the shrunken-in-a-white-circle look. `"maskable"` declares that the asset is designed to be cropped: the image is full-bleed edge to edge, and the platform applies whatever mask it uses (circle, squircle, rounded square). Authoring one means keeping all meaningful content inside a safe zone — a centred circle whose diameter is 80% of the icon's width — and letting background colour run to the edges, because the outer margin can be cut off. Ship it as its own entry, typically a 512×512 PNG, rather than only flipping `purpose` on your existing padded asset, since a padded image marked maskable comes out looking too small the other way.
code
json · 6 lines{
"icons": [
{ "src": "/icon-512.png", "sizes": "512x512", "type": "image/png" },
{ "src": "/icon-maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" }
]
}go deeper
Know that a manifest icon entry can carry a purpose member and that maskable is the value used for home-screen icons designed to be cropped.
Explain the difference between the any and maskable contracts and why they need different artwork rather than the same file labelled twice.
Read the symptom backwards to the cause — a shrunken mark on a plate means no maskable candidate matched, clipped artwork means the safe zone was violated — and remember to verify against the deployed manifest and a fresh install.
Treat icon geometry as part of the brand asset spec: define the 80% safe zone and the full-bleed variant once, so every platform's icon is cut from a documented source rather than improvised per release.
## The two icon contracts Android's adaptive-icon system does not draw the icon you supply directly. It composites it into a shape that varies by device and launcher — a circle here, a squircle there, a rounded square elsewhere. That means the platform has to know something you have not told it: is your image already designed to fill the shape, or is it a standalone mark that needs framing? The manifest answers that per icon entry, via `purpose`. ```json "icons": [ { "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" }, { "src": "/icon-512.png", "sizes": "512x512", "type": "image/png" }, { "src": "/icon-maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" } ] ``` - **`"any"`** (the default when `purpose` is absent) — a conventional icon. The platform will not crop it, so to fit it into an adaptive shape it scales it down and places it on a background plate. That plate is usually white or a system colour, which is precisely the reported symptom. - **`"maskable"`** — the asset is full-bleed and expects to be cropped. The platform applies its mask directly, and the icon fills the shape. - **`"monochrome"`** — a third defined value: a single-colour silhouette the platform may tint for themed-icon surfaces. Alpha carries the shape; colour is discarded. ## The safe zone A maskable icon is authored to a specific geometry. The guarantee the format gives you is a **safe zone**: a circle centred on the icon whose diameter is 80% of the icon's width. Anything inside that circle survives every mask; anything outside it may be cropped by some device's shape. So the authoring rules are: - **Bleed the background to all four edges.** No transparency at the corners — after cropping to a circle, transparent corners are invisible anyway, but on a mask that keeps more of the square they show as holes. - **Keep the mark inside the 80% circle.** In practice the logo occupies rather less than that, because a mark that exactly touches the safe-zone boundary looks cramped on the tighter masks. - **Design at 512×512** and export a PNG. One large maskable asset is normally enough; the platform downscales. The classic mistake is taking the existing padded 512 icon — mark centred with generous transparent margin — and just adding `"purpose": "maskable"`. Now the platform crops instead of padding, but the asset was already padded, so the visible mark ends up tiny inside the shape. The failure is the mirror image of the original bug, and it is why maskable normally means a *separate* asset. ## Why keep an `"any"` entry too `purpose` accepts a space-separated list, so `"purpose": "any maskable"` is legal and claims the asset works for both. Resist it unless the asset genuinely is designed for both, which is rare — an image that crops well is over-padded when used un-cropped, and vice versa. The robust arrangement is separate entries: a normal `any` icon for surfaces that frame it themselves (install prompts, app lists, some desktop launchers) and a dedicated `maskable` one for adaptive home-screen shapes. Browsers select per surface from the array, the same way icon links form a candidate set — declaring both means every surface has a correctly designed option. ## Diagnosing it The reported symptom is diagnostic on its own: **shrunken mark on a solid plate** means the platform decided it must frame your icon, i.e. no maskable entry matched. The opposite symptom — **the logo's edges cut off**, or a full-bleed image with its wordmark clipped — means a maskable entry exists but its content strays outside the safe zone. Check the manifest that is actually served, not the source file: a build step that rewrites icon paths and drops unknown members is a real way for `purpose` to vanish between the repo and production. And remember that changing the manifest does not restyle an already-installed shortcut on most platforms; verify with a fresh install. ## Scope note This is squarely an authoring-and-markup question — what the manifest declares and how the asset is drawn. iOS takes its home-screen icon from `<link rel="apple-touch-icon">` and applies its own rounding to an opaque square, so the maskable mechanism does not apply there; that asset is designed separately.
- Why not just add `"purpose": "any maskable"` to the icon you already have?Because the two contracts want different art. An `any` icon is padded so it looks right when framed; a maskable one bleeds to the edges because it will be cropped. Labelling a padded asset maskable makes the platform crop art that was already inset, so the mark renders tiny. The list syntax is legal, but it is only honest when the asset was designed for both.
- What exactly is the safe zone, and what happens to the area outside it?It is a circle centred on the icon with a diameter of 80% of the icon's width. Content inside it survives every mask a platform might apply. The margin outside is expendable — a circular mask removes it entirely, a squircle keeps some of it — so it should hold background only, never part of the logo or any text.
- You added a maskable entry, redeployed, and the home-screen icon still looks wrong. What do you check first?Whether you are looking at a stale install. Most platforms bake the icon at install time and do not restyle an existing shortcut when the manifest changes, so verify by removing and reinstalling. If it is still wrong, fetch the deployed manifest and confirm the `purpose` member actually survived the build — path-rewriting steps have been known to drop members they do not recognise.
saying these in an interview costs you the question
- Thinks the white plate comes from the PNG's own background
- Adds purpose maskable to the existing padded icon and expects it to fill the shape
- Believes maskable means the browser generates the rounded corners for you
- Puts the wordmark near the icon's edge and is surprised it gets cropped
- Judges the fix from an already-installed shortcut without reinstalling