The web app manifest is a simple JSON file that tells the browser about your web application and how it should behave when 'installed' on the user's mobile device or desktop. Having a manifest is one of the requirements to show the Add to Home Screen prompt.
A typical manifest file includes information about the app name
, icons
it should use, the start_url
it should start at when launched, and more.
Starting with this code lab, we are going to build on top of an existing project. Fork and then Clone the following repository: https://github.com/The-Guide/fe-guild-2019-pwa.git
$ git clone https://github.com/[YOUR GITHUB PROFILE]/fe-guild-2019-pwa.git
$ cd fe-guild-2019-pwa
The master
branch contains the final code for the application but if you want to code along you need to checkout
the correct branch
$ git checkout pwa-app-manifest-init
First install the dependencies
$ npm install
Then type in the terminal
$ npm start
and open Chrome at localhost:8080
Create a manifest.json
file in the same folder as index.html
.
A minimal manifest.json
file for a progressive web app.
{
"name": "Progressive Selfies",
"short_name": "PWA Selfies",
"icons": [
{
"src": "/src/images/icons/app-icon-192x192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "/src/images/icons/app-icon-512x512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": "/index.html",
"scope": ".",
"display": "standalone",
"background_color": "#fff",
"theme_color": "#3f51b5"
}
When you have created the manifest, add a link
tag to all the pages that encompass your web app
<link rel="manifest" href="/manifest.json">
short_name
and/or name
You must provide at least the short_name
or name
property. If both are provided short_name
is used on the user's home screen, launcher, or other places where space may be limited. name
is used in the app install prompt.
"name": "Progressive Selfies",
"short_name": "PWA Selfies"
icons
when a user adds your site to their home screen, you can define a set of icons for the browser to use. These icons are used in places like the home screen, app launcher, task switcher, splash screen, etc.
icons
is an array of image objects. Each object should include the src
, a sizes
property, and the type
of image.
"icons": [
{
"src": "/src/images/icons/app-icon-192x192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "/src/images/icons/app-icon-512x512.png",
"type": "image/png",
"sizes": "512x512"
}
]
start_url
The start_url
tells the browser where your application should start when it is launched and prevents the app from starting on whatever page the user was on when they added your app to their home screen.
Your start_url
should direct the user straight into your app, rather than a product landing page. Think about what the user will want to do once they open your app, and place them there.
"start_url": "/index.html"
background_color
The background_color
property is used on the splash screen when the application is first launched.
display
Display Mode | Description | Fallback |
fullscreen | All of the available display area is used, and no user agent chrome is shown. | standalone |
standalone | The application will look and feel like a standalone application. This can include the application having a different window, its own icon in the application launcher, etc. In this mode, the user agent will exclude UI elements for controlling navigation but can include other UI elements such as a status bar. | minimal-ui |
minimal-ui | Not supported by Chrome The application will look and feel like a standalone application but will have a minimal set of UI elements for controlling navigation. The elements will vary by browser. | browser |
browser | The application opens in a conventional browser tab or new window, depending on the browser and platform. This is the default. | (None) |
orientation
You can enforce a specific orientation, which is advantageous for apps that work in only one orientation, such as games. Use this selectively. Users prefer selecting the orientation.
"orientation": "portrait-primary"
Orientation may be one of the following values:
any
natural
landscape
landscape-primary
landscape-secondary
portrait
portrait-primary
portrait-secondary
scope
The scope
defines the set of URLs that the browser considers to be within your app, and is used to decide when the user has left the app and should be bounced back out to a browser tab. The scope
controls the URL structure that encompasses all the entry and exit points in your web app. Your start_url
must reside within the scope.
A few other tips:
scope
in your manifest, then the default implied scope
is the directory that your web app manifest is served from.scope
attribute can be a relative path (../
), or any higher level path (/
) which would allow for an increase in coverage of navigations in your web app.start_url
must be in the scope.start_url
is relative to the path defined in the scope
attribute.start_url
starting with /
will always be the root of the origin.theme_color
The theme_color
sets the color of the toolbar and may be reflected in the app's preview in task switchers.
description
Provides a general description of what the pinned website does.
"description": "Take selfies PWA style."
dir
Specifies the primary text direction for the name
, short_name
, and description
properties. Together with the lang
property, it helps the correct display of right-to-left languages.
"dir": "rtl",
"lang": "ar",
"short_name": "بطة وجه التطبيق"
It may be one of the following values:
ltr
(left-to-right)rtl
(right-to-left)auto
lang
Specifies the language for the name
, short_name
, and description
properties. This value is a string containing a single language tag.
"lang": "en-US"
A complete manifest.json
:
{
"name": "Progressive Selfies",
"short_name": "PWA Selfies",
"icons": [
{
"src": "src/images/icons/app-icon-48x48.png",
"type": "image/png",
"sizes": "48x48"
},
{
"src": "src/images/icons/app-icon-96x96.png",
"type": "image/png",
"sizes": "96x96"
},
{
"src": "src/images/icons/app-icon-144x144.png",
"type": "image/png",
"sizes": "144x144"
},
{
"src": "src/images/icons/app-icon-192x192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "src/images/icons/app-icon-256x256.png",
"type": "image/png",
"sizes": "256x256"
},
{
"src": "src/images/icons/app-icon-384x384.png",
"type": "image/png",
"sizes": "384x384"
},
{
"src": "src/images/icons/app-icon-512x512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": "/index.html",
"scope": ".",
"display": "standalone",
"orientation": "portrait-primary",
"background_color": "#fff",
"theme_color": "#3f51b5",
"description": "Take selfies PWA style.",
"dir": "ltr",
"lang": "en-US"
}
manifest.json
and check in Chrome Developer Tools, Application -> Manifest
manifest.json
and check in Chrome Developer Tools, Application -> Manifest
Unlike Android, for which many native-like features are automatically generated by the Web App Manifest, iOS requires some additional HTML and CSS tricks. Here are seven suggestions on how to make your PWA more native-like on iOS.
There are two ways to make your PWA run as a standalone application (that is, in a new window without the web browser’s UI controls) on iOS. The first way is to use the apple-mobile-web-app-capable
meta tag in the head element of your HTML code with the following code.
<meta name="apple-mobile-web-app-capable" content="yes">
The second way is to set the display
property of your Web App Manifest to standalone
(see the previous step).
You may customize the iOS status bar (the area along the upper edge of the screen displaying the time and battery status) of your PWA. In order to do this, you must use the apple-mobile-web-app-status-bar-style
meta tag in the head element of your code.
<meta name="apple-mobile-web-app-status-bar-style" content="black">
Unfortunately, the number of ways to customize the status bar is fairly limited, but Apple offers three distinct settings for the content
attribute.
default
results in a white status bar with black text and symbols.black
results in a black status bar and black text and symbols, making it appear completely black. If you do not use the status bar meta tag, this is what status bar will look like.black-translucent
results in white text and symbols and the status bar will take the same background color as the body element of your web app.The title of your PWA will be shown below its launch icon on the home screen. To avoid truncation, this title should not be longer than 12 characters, although it ultimately comes down to the width of the characters used (for example, the letter w is wider than the letter i.) If the original name of your PWA does not fit below the icon, you may assign a short version of the name.
One way to specify a short name for your PWA is to use the apple-mobile-web-app-title
meta tag with the following line in the head element of your code.
<meta name="apple-mobile-web-app-title" content="PWA Selfies">
Unfortunately, iOS does not use the icons specified in the Web App Manifest. Instead, to use a custom icon for all pages of your app, you must provide your icon in PNG format.
Different iOS devices use different sizes for the home screen icons. To specify an icon for a particular size, use the sizes
attribute of the link element. If no icon is specified for the recommended icon size for the device, the icon with the smallest size larger than the recommended one is used instead.
<link rel="apple-touch-icon" href="src/images/icons/apple-icon-57x57.png" sizes="57x57">
<link rel="apple-touch-icon" href="src/images/icons/apple-icon-60x60.png" sizes="60x60">
<link rel="apple-touch-icon" href="src/images/icons/apple-icon-72x72.png" sizes="72x72">
<link rel="apple-touch-icon" href="src/images/icons/apple-icon-76x76.png" sizes="76x76">
<link rel="apple-touch-icon" href="src/images/icons/apple-icon-114x114.png" sizes="114x114">
<link rel="apple-touch-icon" href="src/images/icons/apple-icon-120x120.png" sizes="120x120">
<link rel="apple-touch-icon" href="src/images/icons/apple-icon-144x144.png" sizes="144x144">
<link rel="apple-touch-icon" href="src/images/icons/apple-icon-152x152.png" sizes="152x152">
<link rel="apple-touch-icon" href="src/images/icons/apple-icon-180x180.png" sizes="180x180">
Recall that iOS requires opaque icons. Any transparent parts of the icon will be colored black.
The next step to make your Progressive Web App more native-like is to replace the dull, white launch screen with your own image. To add a custom splash screen, use the following link element.
<link rel="apple-touch-startup-image" href="src/images/apple-launch.png">
In order for this image to show, it is important that its dimensions are the same as those of the device the app is run on. For example, to work on an iPhone X, launch.png
would have to be of the size 1125 by 2436 pixels. The problem that arises here is that there are multiple iOS devices with different resolutions, and unfortunately, we cannot just simply repeat this code multiple times for images of different sizes. Instead, we need to use the media attribute to specify which launch image is intended for which device.
Add the following code to the head element of your PWA to support custom splash screens for the different iOS devices.
<link href="src/images/splashscreens/iphone5_splash.png" media="(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image" />
<link href="src/images/splashscreens/iphone6_splash.png" media="(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image" />
<link href="src/images/splashscreens/iphoneplus_splash.png" media="(device-width: 621px) and (device-height: 1104px) and (-webkit-device-pixel-ratio: 3)" rel="apple-touch-startup-image" />
<link href="src/images/splashscreens/iphonex_splash.png" media="(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3)" rel="apple-touch-startup-image" />
<link href="src/images/splashscreens/iphonexr_splash.png" media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image" />
<link href="src/images/splashscreens/iphonexsmax_splash.png" media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3)" rel="apple-touch-startup-image" />
<link href="src/images/splashscreens/ipad_splash.png" media="(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image" />
<link href="src/images/splashscreens/ipadpro1_splash.png" media="(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image" />
<link href="src/images/splashscreens/ipadpro3_splash.png" media="(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image" />
<link href="src/images/splashscreens/ipadpro2_splash.png" media="(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image" />
On default, the iOS web browser adds certain interactive effects for texts and links that native applications do not have. Therefore, to make your PWA feel more native-like — and less like a website or document — you may disable (or at least partially disable) these effects. The following subsections target the three most common types of effects.
Just like most native iOS applications do not allow text selection, you may disable this feature in your PWA. To do this, set the -webkit-user-select
CSS property to none
for the elements you do not want selectable. To turn off text selection only if the application is started from a home-screen icon with display-mode: standalone
, assign the folowing property to your body element.
@media all and (display-mode: standalone) {
body {
-webkit-user-select: none;
}
}
When tapping a link in the iOS web browser, a grey box appears around the element. Although there is no simple way of disabling this effect, you may change the highlighting color to transparent, and thus effectively make it disappear. To do this for your PWA, set the -webkit-tap-highlight-color
property to transparent
for the desired elements (or assign it to the body element to disable link highlighting for all elements.)
@media all and (display-mode: standalone) {
body {
-webkit-tap-highlight-color: transparent;
}
}
If you tap and hold on an element in the iOS browser, it will open a callout menu (like the one above.) To disable this effect on iOS, set the -webkit-touch-callout
property to none
for the desired elements. Again, to disable the effect for all elements, assign the property to your body element.
@media all and (display-mode: standalone) {
body {
-webkit-touch-callout: none;
}
}
For some reason or another, you might not be able to serve a json file that contains your web app manifest. Maybe you’d like to construct the app manifest on the client side using custom client-selected theme color or icons without involving your server.
In index.html
<base href="/">
<!--<link rel="manifest" href="manifest.json">-->
<link rel="manifest" id="manifestPlaceholder">
What we did:
base
taghref
attribute from the link[rel="manifest"]
tagid
attributeIn src/js/app.js
const manifest = { ... }; // Replace { ... } with the content of the manifest.json file
window.addEventListener('load', () => {
const base = document.querySelector('base');
let baseUrl = base && base.href || '';
if (!baseUrl.endsWith('/')) {
baseUrl = `${baseUrl}/`;
}
manifest['start_url'] = `${baseUrl}index.html`;
manifest.icons.forEach(icon => {
icon.src = `${baseUrl}${icon.src}`;
});
const stringManifest = JSON.stringify(manifest);
const blob = new Blob([stringManifest], {type: 'application/json'});
const manifestURL = URL.createObjectURL(blob);
document.querySelector('#manifestPlaceholder').setAttribute('href', manifestURL);
});
What we did:
manifest
with the content of the manifest.json
filescope
and startup_url
propertiesload
event callback read the value of the href
tag from the base
tag and:startup_url
.src
property for each icon
.json
blob and an URL
for it.href
tag back to the link[rel="manifest"]
tag.blob:http://localhost:8080/9a3ad65e-8dde-4690-8245-6a6d260479d6
Generating by hand all the assets required for the Web App Manifest is not a difficult task' but for sure it is not a fun one.
Here are some resources to make your life easier:
A web app manifest file is a simple JSON file that lets you control how your web app appears to your users. It provides useful information about the application (such as its name, author, icon, and description) in a text file.
If you're using a web app manifest, you'll probably want to set up an app install banner as well. For that, there are some conditions to be met, and we will handle them in the Service Workers code lab.
Here is a checklist which breaks down the things we learned in this code lab.
$ git checkout pwa-app-manifest-final