Supporting iPhone X for mobile web & Cordova app using Onsen UI

Naoki Matagawa
Nov 8, 2017 · 16 min read
Image for post
Image for post
Final Output

is the latest model of Apple’s iPhone series unveiled in September 2017. This unique & eloquent handset will be sold worldwide from November 3rd.

At the first glance you will notice this handset, especially its screen, is a total re-shape from the existing iPhones.

  1. It has a on the top.
  2. .
  3. A is always present on the bottom.
Image for post
Image for post
(Source: https://developer.apple.com/ios/human-interface-guidelines/overview/iphone-x/ )

These changes will affect Therefore, developers have to deal with changes/adaptations specifically for iPhone X. In this article, I will talk about necessary changes needed for iPhone X.

Along the way I’ll mention how to create Vue apps using Onsen UI, which has recently supported iPhone X.

TL;DR

  • If you see left/right in your web or Cordova apps in landscape mode of iPhone X Safari, or body { background-color: black; } .
  • If the notch, the rounded corners or the bottom bar of iPhone X in your web or Cordova apps, to outermost boxes. (If you are using Onsen UI, it can be done by attaching onsflag-iphonex-portrait and onsflag-iphonex-landscape attributes to html element.)
  • If you see in your Cordova app on iPhone X, you can remove them by using cordova-plugin-splashscreen or providing an iPhone X-size (2436 x 1242 px) splash screen image.
  • The source code of the example is available at this GitHub repo.

This article is divided into two main parts:

  • : Creating Native-like Web Apps for iPhone X
  • : Creating Native-like Apps with Cordova for iPhone X

PART I — Creating Native-like Web Apps for iPhone X

In the case of web apps, supporting iPhone X means .

But what happens if we show web apps in iPhone X safari?

Set up a web app

First of all, let’s create a web app. For smoother explanation, I’m going to implement pattern, the most common pattern in iOS apps.

Image for post
Image for post
Tab bar pattern (Source: https://developer.apple.com/ios/human-interface-guidelines/bars/tab-bars/ )

I chose Onsen UI for its implementation. Onsen UI is an open source library containing a set of iOS and Android components for Vue apps.

The versions of NPM packages which we’ll use are shown below:

  • vue@2.5.2
  • onsenui@2.7.0 (Core package)
  • vue-onsenui@2.3.0 (Additional package for Vue)

(1) For existing Vue projects, Onsen UI can be installed with NPM or Yarn:

# NPM
npm install onsenui vue-onsenui --save-dev
# Yarn
yarn add onsenui vue-onsenui -D

Some necessary files must be included in the app:

import 'onsenui/css/onsenui.css'; // Webpack CSS import
import 'onsenui/css/onsen-css-components.css'; // Webpack CSS import
import VueOnsen from 'vue-onsenui';
Vue.use(VueOnsen);

(2) Otherwise, new projects can be . It can optionally add Vuex and some other features:

vue init OnsenUI/vue-pwa-webpack # For PWA

Once Vue and Onsen UI are set up, the next step is to create App.vue and NotesPage.vue with the following codes and get the tab bar pattern implemented.

App.vue
NotesPage.vue

That’s it.

I don’t explain much about how to implement the tab bar pattern in this post. If you’d like to know more about it, please refer to the v-ons-tabbar section in the Onsen UI docs.

Problem I —Left/Right Blank Area in Landscape Mode

So, let’s show the created tab bar pattern in iPhone X Safari. Now I’ll use the iPhone X Simulator available on Xcode 9 instead of the real one.

Launching a local HTTP server and accessing it from the simulator will show the following screens:

Image for post
Image for post
Tab bar pattern in iPhone X Safari (portrait mode)

It seems fine in the case of portrait mode. Then, let’s see what happens if we rotate the screen.

Image for post
Image for post
Tab bar pattern in iPhone X Safari (landscape mode)

Oh, white blank areas appeared on the both side. Actually they are . This is because if there are no blank areas on both side, the notch and the rounded corners will hide some of the page contents.

I’ll call it .


The color of these left/right blank areas , so if we set it to black some of the strangeness can be reduced.

body {
background-color: black; /* Quick fix for Problem I */
}
Image for post
Image for post
In the case that background-color is set to black

But this solution causes a mismatch between the width of the address bar and that of the page in non-black colored pages and results in a weird looking, so the solution is not a complete one.

Fix Problem I — Controlling the Left/Right Blank Areas

iPhone X Safari provides a feature to enable/disable the left/right blank areas.

The blank areas can be controlled by utilizing a special argument in <meta name="viewport" content="...">. viewport-fit accepts auto , contain , and cover as valid values.

So let’s set viewport-fit to cover.

<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no, =cover">
Image for post
Image for post

The blank areas have gone and Problem I has been fixed.

Problem II — Page Contents Hidden by the Obstacles

There are more problems other than Problem I. You would notice that . Moreover, by solving Problem I, the notch and the rounded corners have hidden more page contents.

Image for post
Image for post
The notch, the rounded corners and the bottom bar are hiding some part of the page contents

is that .

Fix Problem II

Basically we can fix the problem that page components are hidden by setting appropriate values to margin and padding in order to prevent boxes are hidden by the notch, the corners and the bar.

Image for post
Image for post
We must set margin and padding so that texts and figures don’t go into the red area

As the easiest solution, we can also set margin-left and margin-right to the body element. Depending on the design of your web app, it might be enough. But if there is a box like tab bars which expands from the left side to the right side, setting margin to the body element makes the box discontinue and causes a weird look. In addition, we have to deal with the problem that texts are hidden by the black bottom bar.

Hence, depending on the design of your web app, you have to . It’s quite tedious, but it is also necessary to achieve an optimized UI for iPhone X Safari.


If we want to set margin and padding to a particular box, we need to make the setting enabled only in landscape mode.

In order to achieve it, orientation media feature can be used. When(orientation: landscape) is added to a media query, the corresponding style sheet will be active only if the viewport is in landscape mode (the dimension satisfies width > height).

@media screen and  {
.some-box {
padding-left: 44px;
padding-right: 44px;
}
}

By the way, how far we should locate boxes from the edge of the screen to prevent the boxes hidden by the notch, the corners and the bar?

As the concrete values, Apple has defined a concept, called .

Understanding Safe Area

Safe area is a region, where .

All apps should adhere to the and layout margins defined by UIKit, which ensure appropriate insetting based on the device and context.

(Source: https://developer.apple.com/ios/human-interface-guidelines/overview/iphone-x/)

Image for post
Image for post
Landscape safe area (Source: https://developer.apple.com/ios/update-apps-for-iphone-x/ )

Therefore if we want to locate boxes far from the edges of the screen, we just need to set the , which is a set of lengths from each edge of the screen.

iPhone X Safari has “top=0, right=44, bottom=21, left=44” as its safe area insets in landscape mode. (We can check the value by using API of iOS.) So we just need to in our case.

Problem II can be fixed by such steady adjustment.

The official WebKit blog explains how to support safe area with a new CSS function constant() and four constants in a post published on Sep 22, 2017. The four constants safe-area-inset-* have two nice characteristics: “the value is set only if viewport-fit is set to cover “ and “the value is automatically switched between the portrait value and the landscape value if the screen rotates.”

But constant() function and the four constants safe-area-inset-* have the following problems:

(1) constant() function has been as of Sep 21, 2017. constant() function is still available on iOS 11.0 Safari, but it might be removed and become unusable in the future.

(2) constant() and env() as of Nov, 2017, and it causes errors if we write codes such as padding-left: calc(constant(safe-area-inset-left) + 10px); . So we always have to write fallback rules for those browsers. It is a bit hard to use.

(3) iOS 11.0 UIWebView has .

I recommend using raw values (Example: top=0, right=44, bottom=21, left=44) directly or via variables instead of depending on safe-area-inset-* for some time to avoid the risk explained above.

Using iPhone X Support Helper by UI Libraries

Some UI libraries have a feature which helps iPhone X support. Onsen UI which I chose at this time provides a feature to set appropriate margin and padding.

Adding onsflag-iphonex-landscape attribute to the html element enables and it changes margin and padding of each box which needs the fix.

Image for post
Image for post
After adding onsflag-iphonex-landscape attribute to the html element

Considering other iOS devices, theonsflag-iphonex-landscape attribute should be added only in iPhone X. To do that, it would be easier to use this.$ons.platform.isIPhoneX() :

beforeMount() {
const html = document.documentElement;
if (this.$ons.platform.isIPhoneX()) {
html.setAttribute('onsflag-iphonex-landscape', '');
}
},

Some UI libraries make it easy to solve the problem of setting margin and padding as I wrote above.


As well as Problem I, finally Problem II, which is the problem that page contents are hidden by the obstacles, has been fixed.

Summary of PART I

In PART I, we used the tab bar pattern as an example and explained Problem I (blank area problem) and Problem II (hiding page contents problem) followed by solutions for each problem.

By fixing Problem I and Problem II, iPhone X supports for Web apps have been solved.


In PART I, we mentioned the case of web apps.

But I think some of you are creating Cordova apps with the Cordova toolkit or Monaca. So I’d like to explain how to make your Cordova app compatible with iPhone X.

PART II — Creating Native-like Apps with Cordova for iPhone X

Image for post
Image for post

In the case of Cordova app, supporting iPhone X means supporting iPhone X WebView.

So let’s see what happens if we show Cordova apps in iPhone X WebView in the same way as PART I.

Set up a Cordova app

Let’s create a Cordova app with Vue.

The versions of software which we’ll use are shown below:

  • vue@2.5.2
  • onsenui@2.7.0 (Core package)
  • vue-onsenui@2.3.0 (Additional package for Vue)
  • cordova@7.1.0
  • cordova-ios@4.5.3
  • Xcode 9.0

(1) For existing Cordova + Vue projects, it can be installed with NPM or Yarn:

# NPM
npm install onsenui vue-onsenui --save-dev
# Yarn
yarn add onsenui vue-onsenui -D

Some necessary files must be included in the app:

import 'onsenui/css/onsenui.css'; // Webpack CSS import
import 'onsenui/css/onsen-css-components.css'; // Webpack CSS import
import VueOnsen from 'vue-onsenui';
Vue.use(VueOnsen);

(2) Otherwise, new projects can be . It can optionally add Vuex and some other features:

vue init OnsenUI/vue-cordova-webpack # For Cordova apps

(3) After setting up Cordova, Vue and OnsenUI, let’s create App.vue and NotesPage.vue with the following content as same as PART I and get the tab bar pattern implemented.

App.vue
NotesPage.vue

That’s it.

How about Problem I?

In PART I, we explained — white blank areas are automatically inserted on the both side by iPhone X Safari.

So let’s check if Problem I remains or not in iPhone X WebView.

cordova platform add ios
npm run build && cordova run ios --target="iPhone-X"
Image for post
Image for post
Tab bar pattern in iPhone X WebView (portrait mode)

Oh, in the case of Cordova apps, it seems that the blank areas appear even in portrait mode.

Then, what happens in landscape mode?

Image for post
Image for post
Tab bar pattern in iPhone X WebView (landscape mode)

Blank areas appeared on the left, right and bottom side in landscape mode.

It turned out that Problem I still happens in Cordova apps. But as same as PART I, this problem can be fixed by just setting viewport-fit to cover .

<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no, =cover">
Image for post
Image for post
After setting the value of viewport-fit to cover

iOS 11 has two WebViews: an old UIWebView (Cordova default, and not recommended by Apple) and a new WKWebView (recommended by Apple).

In UIWebView, because auto of the viewport-fit points to contain , we have to change it to cover . But in WKWebView, auto points to cover by default (confirmed by the author). It means that Problem I is already fixed in WKWebView and we no longer have to set viewport-fit=cover .

As WKWebView is a next-generation API, basically it works stably compared to UIWebView in several situations. If you are using Cordova, I recommend replacing UIWebView with WKWebView by using cordova-plugin-wkwebview-engine plugin. But please also keep in mind that WKWebView has some minor drawbacks.

Problem III

In the case of web apps, once Problem I is fixed, we can start working on Problem II — the notch, the rounded corners and the bottom bar can hide some part of the page contents.

But in the case of Cordova apps, even if Problem I is fixed we cannot work on Problem II right away, because there is another problem, .

Let’s see what is happening in the whole screen after Problem I is solved.

Image for post
Image for post
Cordova app after Problem I is solved (portrait mode)
Image for post
Image for post
Cordova app after Problem I is solved (landscape mode)

There are blank areas, in the top/bottom in portrait mode, and in the left/right and bottom in landscape mode. This is what I call .

Similar to Problem I, but the principle behind the problem is different. Problem III is caused by the specification of iPhone X that all apps which don’t satisfy a particular condition are automatically shown in the safe area. The condition is explained as follows:

Your app will run in Full Screen Display Mode on iPhone X if your project’s base SDK is set to iOS 11 and you have a Launch Storyboard or iPhone X launch image.

(Source: https://developer.apple.com/ios/update-apps-for-iphone-x/ )

I’d like to explain the quoted part more specifically. First of all, iOS has two methods to show splash screens: (1) an old method which (Cordova default, not recommended by Apple) and (2) a new method which based on a mechanism called storyboard (recommended by Apple).

In the case of (1), if the Cordova app does not contain , the app will be shown in the safe area. Adding the image with 1125 x 2436 px size fixes this problem and the app will be shown in full screen.

In the case of (2), .

But in order to use (2), we have to add cordova-plugin-splashscreen plugin into the Cordova app using the following command:

cordova plugin add cordova-plugin-splashscreen

And also the images which the splash screen consists of must be defined in <platform name="ios"> of config.xml :

<splash src="res/screen/ios/Default@2x~iphone~anyany.png" />
<splash src="res/screen/ios/Default@2x~iphone~comany.png" />
<splash src="res/screen/ios/Default@2x~iphone~comcom.png" />
<splash src="res/screen/ios/Default@3x~iphone~anyany.png" />
<splash src="res/screen/ios/Default@3x~iphone~anycom.png" />
<splash src="res/screen/ios/Default@3x~iphone~comany.png" />
<splash src="res/screen/ios/Default@2x~ipad~anyany.png" />
<splash src="res/screen/ios/Default@2x~ipad~comany.png" />

Of course the actual image files must be added. The size of each image should basically follow the document of cordova-plugin-splashscreen , and only for devices with Super Retina screen (@3x) which has 3x resolution, I recommend setting the image size to 2436 x 1242 px so that it covers the longest long side of iPhone X (2436px) and the longest short side of iPhone 8 Plus (1242px). Please note that and and does not affect the size of the app.

Default@2x~iphone~anyany.png (= 1334x1334 = 667x667@2x)
Default@2x~iphone~comany.png (= 750x1334 = 375x667@2x)
Default@2x~iphone~comcom.png (= 750x750 = 375x375@2x)
Default@3x~iphone~anyany.png (= 2436x2436 = 812x812@3x)
Default@3x~iphone~anycom.png (= 2436x1242 = 812x414@3x)
Default@3x~iphone~comany.png (= 1242x2436 = 414x812@3x)
Default@2x~ipad~anyany.png (= 2732x2732 = 1366x1366@2x)
Default@2x~ipad~comany.png (= 1278x2732 = 639x1366@2x)
(Please save the images into res/screen/ios/)

In both of the two methods (1) and (2), after setting up the app correctly, the app will be shown in full screen.

Image for post
Image for post
Cordova app shown in full screen (portrait mode)
Image for post
Image for post
Cordova app shown in full screen (landscape mode)

Problem III has been fixed. But at the same time, Problem II (page contents hidden by the obstacles) occurred. So now let’s fix Problem II.

Problem III need not always to be fixed because l Since Problem II takes some costs, it would be a good choice .

Fix Problem II

As we showed before, Cordova app causes Problem II in both of portrait mode and landscape mode.

As same as PART I, basically we can fix Problem II by setting appropriate values to margin and padding in order to prevent boxes are hidden by the notch, the corners and the bar.


Onsen UI provides a patch CSS for portrait mode as well as landscape mode. enables the patch CSS in both of portrait mode and landscape mode.

beforeMount() {
const html = document.documentElement;
if (this.$ons.platform.isIPhoneX()) {
html.setAttribute('onsflag-iphonex-portrait', '');
html.setAttribute('onsflag-iphonex-landscape', '');
}
}

The patch CSS works as follows:

Image for post
Image for post
After enabling the patch CSS (portrait mode)
Image for post
Image for post
After enabling the patch CSS (landscape mode)

Problem II in iPhone X WebView has been fixed.

Summary of PART II

In PART II, we explained that if we show Cordova apps in iPhone X WebView it causes below in addition to the problems in web apps:

  • White blank areasappear
  • by default ()

Moreover, I explained how the iPhone X support for Cordova apps is more complicated than that for Web apps.

However, those problems can be easily fixed by setting viewport-fit=cover and showing storyboard-based splash screen by using cordova-plugin-splashscreen.

Even if you are developing Cordova apps, you can smoothly support iPhone X considering and solving Problem I, II and III one by one.


Now, we can create Cordova apps like iPhone X native apps by implementing page transition by using Onsen UI components such as Action Sheet(v-ons-action-sheet ) and Navigator(v-ons-navigator ):

Image for post
Image for post
How v-ons-action-sheet and v-ons-navigator work

The source code of the example Cordova app above is like:

Example of iOS-like page transition (Source: https://github.com/asial-matagawa/vue-onsenui-cordova-iphonex )

The full source code of the app is available at this GitHub repo.

Conclusion

In this post, we talked about the iPhone X-specific problems of web apps () and those of Cordova apps (). Especially, we explained the following three problems and how to fix them:

  • — Blank areas on the edges of the screen, which can be fixed by viewport-fit=cover
  • — Page contents are hidden by the notch, the rounded corners and the bar, which can be fixed by setting appropriate margin and padding.
  • — Apps are not shown in full screen, which can be fixed by enabling storyboard-based splash screen.

The iPhone X support helper of Onsen UI (html[onsflag-iphonex-portrait] and html[onsflag-iphonex-landscape]) was also explained.

I hope this post helps you create amazing apps running on iPhone X. Happy coding!

What’s next

The Twitter account and the website of Onsen UI are here:

References

[css-variables] User Agent properties and variables · Issue #1693 · w3c/csswg-drafts
https://github.com/w3c/csswg-drafts/issues/1693

(Aug 4, 2017)

[CB-13273] Webview is sized incorrectly on iPhone X (Simulator) — ASF JIRA
https://issues.apache.org/jira/browse/CB-13273

(Sep 13, 2017)

Removing the White Bars in Safari on iPhone X
http://stephenradford.me/removing-the-white-bars-in-safari-on-iphone-x/
(Sep 14, 2017)

ios — Cordova app not displaying correctly on iPhone X (Simulator) — Stack Overflow
https://stackoverflow.com/questions/46232812/cordova-app-not-displaying-correctly-on-iphone-x-simulator/46232813#46232813

(Sep 15, 2017)

34518947: UIWebView safe area inset constants are not updated on rotation · Issue #18415 · lionheart/openradar-mirror
https://github.com/lionheart/openradar-mirror/issues/18415
(Sep 20, 2017)

Designing Websites for iPhone X | WebKit
https://webkit.org/blog/7929/designing-websites-for-iphone-x/
(Sep 22, 2017)

The Web Tub

Pushing the web current through hybrid mobile and PWA…

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store