DEV Community

Cover image for Hassle free PWA icons and splash screen generation
Dominik Fiala
Dominik Fiala

Posted on

Hassle free PWA icons and splash screen generation

Recently I created my first progressive web application (PWA). Partly because I couldn't find any free one on Apple Store that would suit me, partly because I tried to convince a friend of mine that it is much faster and better to maintain than native mobile apps.

I'm mostly back-end developer so it's always fun and relaxing to hack something with technologies I don't work with on daily basis. All the coding was fun, mostly because I used great tools, mainly Vue CLI that comes with a great PWA template that allows you to start working on a project almost instantly, instead of figuring out the boilerplate yourself.

I run into some issues though. First surprise came when I found out that localStorage in PWA differs when the app is opened from home screen and when is opened in a browser. Well, just don't let people use your app in a browser, make them use the PWA version. Done.

Second one was how iOS Safari calculates the viewport height, which made layout creation in CSS a real pain. In short: it puts its own toolbar over your carefully positioned app navigation bar. I experimented with this buggyfill, it worked nice, but it made me realize I want to focus on the app functionality and not rendering details, so I adopted Framework7 into the project that took care of this issue. Done.

But to my surprise the biggest challenge of creating a simple PWA was to populate it with icons in all the resolutions various devices/OSes require. There are these 512 and 192 pixels PNG icons that Chrome DevTools validates, then there are 32 and 16 pixels favicons, and various resolutions for all the iOS devices. So far so good, it's just a square in a different resolutions. Done.

Then you find out that there is a <link rel="apple-touch-startup-image"> HTML tag that you can use so users of your app won't stare at white screen while your app is loading. But you need to create said startup image for each iOS device that is out there, all of them having different resolution and display aspect ratio.

So you can't just scale down one high resolution PNG anymore. And even worse, you can't just use one resolution and hope iOS will rescale it and use it on every screen. Well you can hope, but will be disappointed. This works with app icons though (I ended up having just the 180x180px version, all the devices seem to work fine with that).

Luckily Apple has it covered and gives you an overview of all the resolutions in on handy table.

So all the theory was in place all that was left to do was to create my app icon in various resolutions. How do I do that? I'm no graphic designer. I don't want to use online tool and then manually download the generated files into my project. I don't want to use ready made solution with dozen dependencies that outputs like gazillion files you need manually go over and cherry pick. Heck, I am a web developer, there must be a better way how to transform this:

PWA icon

...into this:

PWA splash image

Then it hit me! These graphics with various aspect ratios and resolutions are nothing more than just very simple responsive web page with one image (SVG respectively). Luckily I created the logo as a vector graphic in the beginning.

So here is a template to scalable web application icon that adapts to any screen size and orientation:

<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
  body {
    margin: 0;
    background: linear-gradient(225deg, #F9D423, #F83600);
    height: 100vh;
  }
  img {
    width: 100%;
    height: 100%;
    margin: 0 auto;
  }
  </style>
</head>
<body>
  <img src="logo-white.svg" >
</body>
</html>

Just take screenshots in various viewport size and there you have it! Well, don't be silly, don't do it by hand. Automate it! Sprinkle it with a little Node script that takes the screenshots for you (it uses Webshot CLI available via NPM).

const { exec } = require('child_process')
const util = require('util')

const sizes = [
  { name: 'favicon-16', size: '16/16' },
  { name: 'favicon-32', size: '32/32' },
  { name: 'apple-icon-180', size: '180/180' },
  { name: 'pwa-icon-192', size: '192/192' },
  { name: 'pwa-icon-512', size: '512/512' },
  { name: 'apple-splash-640', size: '640/1136' },
  { name: 'apple-splash-750', size: '750/1334' },
  { name: 'apple-splash-1242', size: '1242/2208' },
  { name: 'apple-splash-1125', size: '1125/2436' },
  { name: 'apple-splash-1125', size: '1125/2436' },
  { name: 'apple-splash-1536', size: '1536/2048' },
  { name: 'apple-splash-1668', size: '1668/2224' },
  { name: 'apple-splash-2048', size: '2048/2732' },
]

sizes.map(item => {
  exec(util.format(
    'npx webshot --window-size=%s ./src/assets/logo/logo.html ./static/img/icons/%s.png',
    item.size,
    item.name
  ))
})

One SVG, one HTML, one Node script and one locally installed NPM package. That's all it took to generate this plethora of PWA graphics:

PWA graphics

Thanks for reading! And since this is my first post here in this lovely community, I would appreciate any feedback. Happy hacking you all!

Top comments (6)

Collapse
 
onderceylan profile image
Önder Ceylan 🌚

This is an amazing idea Dominik! I was inspired by your blog post and I recently decided to build a CLI library for this purpose while experimenting with Puppeteer for my next talk.

For anyone who would like to automate this process in a generic way, here's the CLI: itnext.io/pwa-splash-screen-and-ic...

Collapse
 
jipfr profile image
Jip

Hey Dominik, is your web app public & what does it do? I can never help but wonder when it comes to PWAs :P

Collapse
 
dominikfiala profile image
Dominik Fiala

I created it to keep track of how many cigs a day i smoke. Then made it versatile to keep track of any metric on daily/weekly/monthly/... basis. Basically an app for nerds that like real life numbers 👨‍💻

Collapse
 
dominikfiala profile image
Dominik Fiala • Edited

Sure, but its in czech only, see dominikfiala.github.io/kolik/app/#/ and source is in english at github.com/dominikfiala/kolik

Collapse
 
lukvonstrom profile image
Lukas Fruntke

You could also use puppeteer, which introduces a pretty neat API for accomplishing this task too.

Collapse
 
dominikfiala profile image
Dominik Fiala • Edited

Sure thing. Or any other software capable of rendering and screenshoting a website.
But the idea is to design the app icon as a trivial responsive website. So these details dont really metter imo.