Orientation Handling in Apache Cordova and CSS3

I am continuing my work towards learning Apache Cordova. One of the aspects that I want to cover is orientation handling. Mostly, this is for display purposes. Shockingly, there are actually three ways to handle orientation handling – one javascript method and two CSS3 methods. Today, I’m covering the two CSS3 methods.

Let’s start with my CSS3 I’m working on. I have some HTML code:

<!DOCTYPE html>
        <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
        <meta name="format-detection" content="telephone=no">
        <meta name="msapplication-tap-highlight" content="no">
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
        <link rel="stylesheet" type="text/css" href="css/index.css">
        <title>Cordova Quickstart</title>
        <script type="text/javascript" src="cordova.js"></script>
        <script type="text/javascript" src="js/index.js"></script>

This is fairly straight forward. Check out the header, section and footer. I want those stacked up, so that the header and footer are at the top and bottom of the screen respectively and are always the same size. The section fills the remaining space. To distinguish them I am going to make them different colors. I’m using SCSS to write my CSS code. My basic code looks like this:

$ht: 3%;

html, body {
    margin: 0;
    padding: 0;
    font-size: 12px;

body {
    position: fixed;
    left: 0; right: 0; top: 0; bottom: 0;
    display: flex;
    flex-flow: column nowrap;

    >header, >footer {
        display: block;
        flex-basis: $ht;
        height: $ht;
        background-color: #808080;

    >section {
        display: block;
        flex-grow: 1;

The problem is this. When I rotate the device, the header and footer are perceived to grow. That’s because they are a percentage of the height of the device, which is different in portrait vs. landscape mode.

Method 1: vmin and vmax

My first method is purely for measurements. There are several units that you can use in CSS3. The oft overlooked ones are vmin and vmax.

  • 1 vmin is 1% of the short edge of the display
  • 1 vmax is 1% of the long edge of the display

This means I can make $ht: 3vmax. The header and footer will always be 3% of the long edge of the device, which is a constant height.

As is normal in browser land, support for vmin and vmax varies widely so testing is critical. vw and vh (which are described next) are much more consistently implemented, so I recommend Method 2.

Method 2: Using media queries

I didn’t start using media queries until I started mobile development. Well, that’s not strictly true. I installed Bootstrap quite often and that uses media queries, but I didn’t understand them enough to use them myself.

There are two pieces of information in the media queries specification – a device type and an orientation – that are useful here. The device type is “screen”, “handheld”, “tv”, “print” (and others). The orientation only has two values – landscape and portrait. You can add further things into the media query. A common thing to add is a test for screen width or height, for instance. There are also media queries for color depth, resolution, and to identify support for specific facilities.

You can use the @media specifier in your CSS3 to identify a media query. For example:

@media (min-width: 768px) {
   /* Your Style goes here */

The style will only get applied when the media-query is satisfied. So, how do I adjust my code to use the orientation? In this case, I’m going to use either 3vh (when in portrait) or 3vw (when in landscape). vh is 1% of the height of the screen. vw is 1% of the width of the screen. Here is the code:

>header, >footer {
    display: block;
    @media screen and (orientation: portrait) {
        flex-basis: 3vh;
        height: 3vh;
    @media screen and (orientation: landscape) {
        flex-basis: 3vw;
        height: 3vw;
    background-color: #808080;

One caveat to this. The orientation is generally implemented by measuring the height and width of the viewport – if the width is bigger than the height, orientation is landscape. The viewport changes when you open a visual keyboard and that may result in an orientation change.

This is much more flexible than using vmin/vmax. You can also hide elements or show elements. A prime example is collapsing a menu structure down to a hamburger menu when in portrait. To do this, you create two menus – one for the hamburger menu and one for the top-bar. You hide the top-bar menu when in portrait and show the hamburger menu. When in landscape, you show the top-bar menu and hide the hamburger.

Final Thoughts

One thing I noted is that my header is overwritten by the regular phone items – signal strength, battery life, etc. – on an iPhone. There is no media query for a specific device. However, the user agent string does have that information. You can test that you are on an iPhone with the following:

if (navigator.userAgent.toLowerCase().indexOf("iphone") !== -1) {
   /* We are on an iPhone */

This can allow you to dynamically alter your HTML code if you need to. I’ve only tested my CSS3 on the simulator, so I have no idea if this happens on a real device. If this was a real project, I would definitely be testing on a real device.