How to Make Any Website Responsive with Restive.JS


By

According to Verisign’s Domain Name Industry Brief for 2013, it is estimated that 85% of all .com and .net TLDs (top-level domains) have websites: that’s over 100 million websites [being that .com and .net domains collectively number over 120 million]. Now, that is a lot of websites! So how exactly are we going to make them all responsive?

If you have an existing website that is not responsive, I’m sure you’ve probably given some thought to how you would make it mobile-friendly. It’s really hard to argue against the mobile trend these days with Mobile Web Traffic now at about 25% of all Internet Traffic, and sales of mobile devices (Phones & Tablets) currently surpassing traditional personal computers by over 6 to 1. Let’s face the facts: It doesn’t depend anymore, your website needs to be mobile-friendly.

Building a responsive website from scratch today is easier than it has ever been as a result of improved frameworks and techniques. However, with all those non-responsive websites out there, we have to find ways to quickly and gracefully retrofit them with responsive enhancements. In this article, I’ll introduce a step-by-step process for making any website responsive using a responsive web design framework called Restive.JS, and using a very real and very popular website as our specimen.

The Specimen

To get started, we need a website that would be our ‘guinea pig’ of sorts. I felt it would be best to use a website that was pretty popular, but wasn’t natively responsive. So for this tutorial, I decided to use to use the AirBnB website because – believe it or not – it’s not natively responsive (it redirects mobile devices to a dedicated mobile subdomain).

When I visited airbnb.com using a Google Galaxy Nexus, I was redirected to m.airbnb.com where I got served a list of search results I didn’t specifically search for, plus a number of action links like ‘Sign Up’, ‘Log In’, and a very prominent link to download the app for Android (which I already had on my phone). Some of the interesting things on the original website like ‘Neighborhood Guides’ as well as the social network links a la Facebook, Twitter, etc. were absent.

No offense against AirBnB, but I would have loved to see a responsive version of the original website, and then decide for myself if I wanted to download the app. I would have loved it so much, that I’m going to create a responsive version of the AirBnB website.

Disclaimer: This tutorial is in no way endorsed or authorised by AirBnB. It is meant to serve as a guide for how to retrofit existing websites to make them responsive, and is nothing more than that. The final result is merely for testing purposes only and should never be used as a substitute for the original AirBnB website, which remains at www.airbnb.com.

The Tools

Google Chrome

No disrespect to the other browsers out there – especially Mozilla Firefox – but Google Chrome is awesome if you’re a web developer, especially because it sports a built-in Mobile Emulator which I view as essential. For this exercise I’ll be using Chrome exclusively for the development side of things. However, you can as well use any browser that has good developer tools, and then test using your preferred mobile emulation environment.

A Text Editor

We are going to make some changes to HTML and CSS files so you’ll need a text editor for this, any one will do.

Introducing Restive.JS

Restive.JS is the cornerstone of this operation. It is a jQuery Plugin [or Framework if you like] that helps you add responsive features to a website almost instantly. The premise behind Restive.JS is simple: Go Responsive with Less Code and Less Hassle. It has quite a lot of features [that you can explore in your own time].

A major benefit of using Restive.JS is that it lets you define all your responsive CSS markup inline, unlike media queries which splits your responsive markup into distinct ‘markup realms’ that you have to manage separately.

So basically, with Restive.JS I can write CSS like this:

#my-element-id {/* Styles */} //my desktop style rule
.phone #my-element-id {/* Styles */} //my general smartphone device style rule
.tablet #my-element-id {/* Styles */} //my general tablet device style rule

As opposed to this:

#my-element-id {} //my desktop style rule

@media only screen and (min-width : 320px) and (max-width : 480px) {
/* Styles for some mobile devices */
}

@media only screen and (min-width : 321px) {
/* Styles for some other mobiles  */
}

/** ...And yet more Media Query Directives **/

The Process

Step 1: Download the AirBnB Website

To download the AirBnB website, I simply open the web address in my web browser, and then I save the whole web page. If you’re using a browser like Firefox or Chrome you can save the complete web page, including all images, CSS, Javascript, and the like. I used Firefox to do mine.

I created a new folder on my desktop, then I saved the complete web page in this folder. I then created a copy of the original index.html file, and named it index.orig.html; this is just so we can compare changes later if we need to.

Next, I created three new folders called ‘js’, ‘css’, ‘img’; affectionately referred to by me as The Three Amigos, although they are nowhere near as entertaining. And I think it’s pretty clear what these folders are going to be holding so we’ll move on to the next thing.

Step 2: Install Restive.JS

Installing Restive.JS is a snap. We do need to find out if the AirBnB home page uses jQuery; I suspect it does, but just for the sake of argument let’s make double sure.

To do this I open the local index.html [that I saved previously] in my browser, and I ‘View Page Source’. On the resulting page, I do a quick search using .js as the keyword and the browser immediately shows me where all the link-referenced Javascript files are. Going through each one I see this file reference…

<script src="https://a2.muscache.com/airbnb/static/libs_jquery_2x-4c61948b1a5fa686ed70f7b9bf4a18c9.js" type="text/javascript"></script>

…which looks like it could be jQuery. After opening it I see that it is, so we can conclude that conclude that jQuery is indeed active on this page.

All we need to do now is load Restive.JS sans jQuery, and we’ll add the code & markup directly below the above jQuery script reference thus:

<script src="index_files/libs_jquery_2x-ba3075998163c02622926b9556bc93aa.js" type="text/javascript"></script>

<!-- Install Restive.JS -->

<script type="text/javascript" src="js/restive.min.js"></script>
     
<!-- Configure Restive.JS -->
<script>
    $( document ).ready(function() {
        $('body').restive({
            breakpoints: ['10000'],
            classes: ['nb'],
            turbo_classes: 'is_mobile=mobi,is_phone=phone,is_tablet=tablet,is_portrait=portrait,is_landscape=landscape'
        });
    });
</script>

You can grab Restive.JS via Github, and simply store it in the ‘js’ directory.

Restive.js has the basic format of most jQuery plugins. In the above code & markup, we have defined 3 options, ‘breakpoints’, ‘classes’, and ‘turbo_classes’ and I’ll just briefly explain what they do.

breakpoints and classes are the primary options in Restive.js. What they do is setup declared breakpoint ranges, and then apply classes to the given selector as the viewport width of the device on our website matches that specific range. So if we had defined breakpoints: ['240', '320'], and classes: ['240-css', '320-css'], the plugin would setup the breakpoint ranges of 0 to 240 pixels, and 241 to 320 pixels, and then it would add the class 240-css to the <body> tag (which is our selector) if the device viewport width fell between 0 and 240 pixels, and it would add 320-css if the viewport width was between 241 and 320 pixels. This is pretty much how these two options work hand-in-hand.

turbo_classes is a special feature of Restive.js that adds classes [in addition to those defined in the classes option] to our <body> tag when certain pre-defined conditions are met e.g. when the device is a mobile device, when the device is a tablet, etc. There are about 9 specific conditions in all. Right now, we’re using 5 because that’s all we need. So for example, is_landscape=landscape will tell the plugin to add the class landscape to the <body> tag if the device is in landscape orientation, and being that Restive.js is stateful, this class will also be removed if the device switches to portrait orientation.

In our particular circumstance, we’re not overly concerned with conventional breakpoints, as we are focused primarily on form-factors. Hence we will simply define breakpoints: ['10000'], and classes: ['nb'], to create a range from 0 to 10,000 pixels that will match all devices. Then we simply use turbo_classes to apply specific classes pertinent to our aspirations.

What this means is that if you have a phone, and you visit our updated website, Restive.JS will make sure to add the class mobi phone portrait to the <body> tag, because the device is a mobile device, it’s a phone, and it’s in portrait mode. If you switch to landscape mode, Restive.JS will update the class to mobi phone landscape in realtime. If you were using a tablet instead, you’ll see mobi tablet portrait. The importance of all this will be clearer a little later.

Step 3: Define Responsive Enhancements

Now that we have everything setup and almost ready to run, let’s decide on the responsive enhancements we would like to add to our website. It’s very important to have a clear focus beforehand on what needs to change on the website.

AirBnb website Screenshot

I made some annotations to the screenshot of the AirBnB website that you can access if you need to; it contains some strategy notes regarding how we’re going to make these responsive enhancements.

First, we break down the layout of the web page into five zones: (1) Header, (2) Hero, (3) Content – Level 1, (4) Content – Level 2, (5) Footer. Then we determine all the general responsive enhancements [as Tasks] that will be required to make our website Mobile-friendly. They are all clearly itemized in the above annotations: One page has the layout zone breakdown, and the second page has the responsive enhancements for mobile devices.

Step 4: Implement Responsive Enhancements

All the Responsive Enhancements we are going to make going forward will be done via inline CSS. So we create a file called restive.css; this file will go in the ‘css’ directory. For now this file is blank, and we’ll add to it as we go. We then create a link reference to this CSS file on the index.html page.

<head>
    <!-- ALL THE OTHER MARKUP INSIDE HEAD TAG -->
    <link href="css/restive.css" media="all" rel="stylesheet" type="text/css" />
</head>

Note: It’s important that our CSS file load after every other similar file, so we link to it just before the closing <head> tag.

Also, we have to change the existing viewport meta tag from what it currently is now [‘<meta name="viewport" content="width=1000,maximum-scale=1.0">‘] to a mobile-friendly one. So replace the existing viewport meta tag to what you have below:

<meta name="viewport" content="width=device-width, initial-scale=1">

And before we get started, let’s agree on a few conventions. Within the Developer Tools interface it’s very easy to see all the code, but copying and pasting all the HTML here will be overkill. Because the markup is long, I’ll show snippets of markup [or code] like below:

<!-- HEADER ZONE -->
<div>
    <div class="name">
        <!-- MARKUP TRUNCATED --> 
    </div>
</div>

I’ll only depict the operative element. Any markup within it that is not immediately relevant will be truncated [it’s still there but I just won’t show it] and replaced with the HTML comment with caption ‘MARKUP TRUNCATED’ [I’ll also do the same for Javascript code with caption ‘CODE TRUNCATED’]. In addition, only the direct parent of the operative element will be shown, as this ought to be enough to give a good idea where the snippet is so you can find it inside the Developer Tools interface. I’ll also indicate what Layout Zone we are looking at using another HTML comment on the first line of the code snippet.

So the basic M.O. is that I’ll describe the goal of the Task required to enable the desired responsive enhancement, then next comes the HTML markup, and then finally the CSS Markup.

Note: If you’re not familiar with Chrome Developer Tools, there are a lot of resources that you can find only to help you. I also wrote a blog post on Testing Responsive Websites that could also be helpful.

Task 1:

The first task is concerned with resetting any major fixed width elements so that nothing breaches the viewport width of a mobile device. For example, the <div> with class container-full-width has a min-width of 995px; we’re going to need to reset this property and force a fluid width instead.

<!-- HEADER ZONE -->
<div class="navbar-inner">
    <div class="container container-full-width page-container">
    <!-- MARKUP TRUNCATED --> 
    </div>
</div>
.mobi #header .container-full-width {position: relative; min-width: 10px; min-height: 44px; width: 100%; margin: 0; padding: 2px 0 0 0;}
.mobi .page-container {width: 100%; padding-left: 15px; padding-right: 15px;}

Task 2:

The second task is concerned with making the header zone fixed for mobile devices, so that whether we scroll up or down, the navigation bar always remains in place. We’ll also set a new minimum height for this navigation bar.

<!-- HEADER ZONE -->
<div id="header" class="navbar navbar-top">
    <div class="navbar-inner">
        <!-- MARKUP TRUNCATED --> 
    </div>
</div>
.mobi #header {width: 100%; position: fixed; z-index: 10000;}
.mobi #header .navbar-inner {min-height: 44px;}

Task 3:

Now this task is a real doozy. We’re going to need to enable two different navigational systems, one for the original website, and the other for the mobile website. However, they have to consume the same markup space.

So we need to add some HTML markup i.e. div#nav-left and div#nav-right that will hold the navigational system for mobile; this needs to be hidden on devices that are non-mobile. Likewise, on mobile devices, we need to hide the navigational system of the original website. We also add id tags to certain elements for easy jQuery access later. Finally, we create an image sprite for the icons needed for our mobile navigation UI.

<!-- HEADER ZONE -->
<div class="container container-full-width page-container">
    <div id="nav-left" class="nav-new">
        <ul>
            <li><a href="#" id="nav-button-browse" class="nav-new-button"><img class="nav-sprite icon-browse" src="img/transp.png"></a></li>
        </ul>
    </div>
    <a href="/" class="brand airbnb">Airbnb</a>
    <div id="nav-right" class="nav-new">
        <ul>
            <li id="nav-new-search"><a href="#" id="nav-button-search" class="nav-new-button"><img class="nav-sprite icon-search" src="img/transp.png"></a></li>
            <li><a href="#" id="nav-button-actions" class="nav-new-button"><img class="nav-sprite icon-actions" src="img/transp.png"></a></li>
        </ul>
    </div>
    <ul class="nav">
        <li id="header-search">
            <!-- MARKUP TRUNCATED -->
        </li>
        <li id="header-browser" class="dropdown item_explore">
            <!-- MARKUP TRUNCATED -->
            <ul id="header-browse-sub" class="dropdown-menu dropdown-bordered">
                <!-- MARKUP TRUNCATED -->
                <li class="wide"><a href="/locations"><i class="icon icon-product-neighborhoods icon-map-marker blue"></i> Neighborhoods</a></li>
                <!-- MARKUP TRUNCATED -->
            </ul>
        </li>
    </ul>
    <ul class="nav pull-right help-menu" style="margin-left:0;">
        <li id="header-actions-1" class="dropdown" data-dropdown-sticky="true">
            <!-- MARKUP TRUNCATED -->
        </li>
        <li id="header-actions-2" class="list-your-space">
        <!-- MARKUP TRUNCATED -->
        </li>
    </ul>
    <ul class="nav pull-right logged-out">
        <li id="sign_up">
            <!-- MARKUP TRUNCATED -->
        </li>
        <li id="login">
            <!-- MARKUP TRUNCATED -->
        </li>
    </ul>
    <!-- MARKUP TRUNCATED -->
</div>
#header .nav-new {display: none;}
.mobi #header .nav-new {display: block; position:absolute;}
.mobi #header #nav-left {top: 0; left: 0;}
.mobi #header #nav-right {top: 0; right: 0;}
.mobi #header .nav-new ul {margin: 0; padding: 0;}
.mobi #header .nav-new ul li {display: inline-block; width: 44px; height: 44px; margin: 0 auto; text-align:center; padding: 12px 0 0 0;}
.mobi #header #nav-right ul li {padding: 9px 0 0 0;}
.mobi #header .nav-new img.nav-sprite {background-image:url(../img/nav_sprite.png); background-repeat:no-repeat; background-position: 0 0; vertical-align:middle;}
.mobi #header .nav-new #nav-new-search {display: none;}
.mobi #header .nav-new img.icon-search {background-position: -10px -10px; width: 24px; height: 23px;}
.mobi #header .nav-new img.icon-browse {background-position: -10px -50px; width: 24px; height: 18px;}
.mobi #header .nav-new img.icon-actions {background-position: -10px -90px; width: 24px; height: 25px;}
.mobi #header .nav {display: none;}

Task 4:

This task is somewhat complimentary to the previous task. Because we’re going to have two different UI systems for navigation, and because there isn’t enough space to enable the dropdown menu features of the original website, we’re going to have to create another content area below the main navigation bar; a sub-navigation bar or sorts. We can then use Javascript/jQuery to activate functionality for this.

<!-- HEADER ZONE -->
<div class="container container-full-width page-container">
    <!-- MARKUP TRUNCATED -->
</div>
<div class="navbar-sub">
    <div class="navbar-sub-item" id="navbar-sub-search"><ul></ul></div>
    <div class="navbar-sub-item" id="navbar-sub-browse"><ul></ul></div>
    <div class="navbar-sub-item" id="navbar-sub-actions"><ul></ul></div>
</div>
#header #navbar-sub {display: none; /**position:absolute; top: 0;**/ height: 40px; padding: 0 10px; border-top: 1px dashed #A8E2FF; z-index: 9900;}
.mobi #header .navbar-sub-item ul{margin: 0; padding: 0; list-style-type: none;}
.mobi #header #navbar-sub-browse li{float: left; width: 28%; height: 40px; line-height: 40px; vertical-align: middle;}
.mobi #header #navbar-sub-browse li.wide{width: 44%;}
.mobi #header #navbar-sub-browse li.meetups, .mobi #header #navbar-sub-browse li.groups{float: left; display: none;}
.mobi #header #navbar-sub-actions li{float: left; width: 28%; height: 40px; line-height: 40px; vertical-align: middle;}
.mobi #header #navbar-sub-actions li#login{width: 23%;}
.mobi #header #navbar-sub-actions li#header-actions-1{width: 15%;}
.mobi #header #navbar-sub-actions li.list-your-space{width: 34%;}
.mobi #header #navbar-sub-actions li.list-your-space #list-your-space{margin-left: 0px; font-size: 0.8em; margin-top: 0;}
.mobi #header #navbar-sub-actions li#header-actions-1 a .caret{display: none;}

The Javascript code for enabling this sub-navigation bar functionality will go after our Restive.JS code. You can find the full code for this by looking at the final index.html file at the end of this tutorial.

<!-- Configure Restive.JS -->
<script>
    $( document ).ready(function() {
        $('body').restive({
            /** CODE TRUNCATED **/
        });
        /**
         * Sub Navbar Functionality Code Goes Here
         */
    });
</script>

Task 5:

The fifth task is concerned with re-aligning the AirBnB logo. On the original website, it is aligned to the left of the header zone. However, we’re going to need to have it centered.

<!-- HEADER ZONE -->
<div class="navbar-inner">
    <div class="container container-full-width page-container">
        <!-- MARKUP TRUNCATED -->
        <a href="/" class="brand airbnb">Airbnb</a>
        <!-- MARKUP TRUNCATED --> 
    </div>
    <!-- MARKUP TRUNCATED --> 
</div>
.mobi .navbar .brand {float: none; text-align: center; margin: 0 auto;}

Task 6:

For this task, we’re going to be enabling some responsive enhancements for the ‘hero’ zone. However, for this tutorial we are going to disable the “Sliding Background Image” feature. We can make this responsive, but just to simplify things we’ll skip that so we don’t make this exercise any longer. Instead we’ll take one of the existing images and fix that to the layout. To do this we replace ul#slideshow with div#slideshow-new and delete a.slideshow-scroll.slideshow-scroll-prev and a.slideshow-scroll.slideshow-scroll-next. We’ll also make some preliminary layout modifications to div.search-area.

<!-- HERO ZONE -->
<div id="hero" style="display:block;" data-native-currency="USD" class="">
    <div id="slideshow-new"></div>
    <!-- MARKUP TRUNCATED -->
</div>
img{max-width: 100%;}
.mobi #hero {height: 320px; width: 100%;}
#hero #slideshow-new {width: 100%; height: 500px; padding: 36px 0 0 0; background-image:url(../img/hero_background.jpg); background-repeat:no-repeat; background-position: 0 0; vertical-align:middle; background-size: 100% auto;}
.mobi #hero #slideshow-new {width: 100%; height: 320px; padding: 44px 0 0 0; background-position: -100px 0; background-size: auto 320px;}
.mobi #hero .row {display: block; width: 100%; margin-left: 0; margin-right: 0;}
.mobi #hero .col-11 {display: block; width: 100%; float: none; padding-left: 0; padding-right: 0;}
.mobi #hero .search-area {height: auto; padding-top: 60px;}
.mobi #blob-bg {width: 100%; height: 50%; background-size: 100%; top: 0; left: 0; right: 0; margin-left: 0; margin-top: 0; opacity: 1;}
.mobi .search-area h1 {font-size: 28px; text-shadow: 1px 2px 3px rgba(0, 0, 0, 1);}
.mobi .search-area h2 {font-size: 16px; text-shadow: 1px 1px 2px rgba(0, 0, 0, 1);}

Task 7:

This task is saddled with the responsibility of tweaking the main search bar. As is evident, it’s quite long and it won’t fit within the viewport of a phone device, but it probably will if we collapse its elements gracefully. And to make this happen, we need to make a few updates to some HTML components of the form, which will enable us to target them specifically via CSS

<!-- HERO ZONE -->
<form action="/s" id="search_form" class="custom show-search-options position-left form-inline">
    <div id="searchWrapper" class="input-wrapper">
        <!-- MARKUP TRUNCATED -->
    </div>
    <!-- MARKUP TRUNCATED -->
    <div id="guestWrapper" class="input-wrapper">
        <!-- MARKUP TRUNCATED -->
    </div>
    <!-- MARKUP TRUNCATED -->
</form>
.mobi #hero .form-inline {float: none; width: 100%;}
.mobi #hero .form-inline #searchWrapper{width: 100%; margin-right: 0; margin-bottom: 5px;}
.mobi #hero .form-inline #searchWrapper #location{width: 100%; height: 36px;}
.mobi #hero .form-inline #checkinWrapper{clear: left; width: 49%; margin-right: 2%; margin-bottom: 5px;}
.mobi #hero .form-inline #checkoutWrapper{width: 49%; margin-right: 0; margin-bottom: 5px;}
.mobi #hero .form-inline .checkin, .mobi #hero .form-inline .checkout{width: 100%; height: 36px; margin: 0;}
.mobi #hero .form-inline #guestWrapper{clear: left; width: 65%; margin-right: 5%;}
.mobi #hero .form-inline #guestWrapper select{width: 100%; min-width: 80%;}
.mobi #hero .form-inline #submit_location{width: 30%;}

Task 8:

This task is primarily concerned with the ‘Neighborhood Guides’ section. The section contains some text and an array of images laid out in a tile format.

I found this to be the most complicated of all the responsive enhancements because not only do we have to collapse the image tiles gracefully, they also have to remain responsive. Unfortunately, the images in the tiles were created from a sprite [not individual images via img tag], so the ol’ img{max-width: 100%;} trick isn’t going to work. However, I did manage to find some tips on making background image sprites responsive as well as resizing a div while maintain aspect ratios; I used that logic to get the result I wanted.

We do have to add some HTML to the <li> elements that serve as containers for the array of images. This dummy <div> element will be used to maintain the aspect ratio of the background image sprite.

<!-- CONTENT ZONE – LEVEL 1 -->
<div id="content-1" class="panel panel-dark row-space-4">
    <!-- MARKUP TRUNCATED -->
    <ul class="city-tiles list-unstyled two-wide-city-tiles">
        <li class="city-tile">
            <div class="dummy"></div>
            <div class="media-photo city-tile city-tile-mexico-city"></div>
            <!-- MARKUP TRUNCATED -->
        </li>
        <li class="city-tile">
            <div class="dummy"></div>
            <div class="media-photo city-tile city-tile-tokyo"></div>
            <!-- MARKUP TRUNCATED -->
        </li>
        <li class="city-tile">
            <div class="dummy"></div>
            <div class="media-photo city-tile city-tile-ny"></div>
            <!-- MARKUP TRUNCATED -->
        </li>
        <li class="city-tile">
            <div class="dummy"></div>
            <div class="media-photo city-tile city-tile-paris"></div>
            <!-- MARKUP TRUNCATED -->
        </li>
    </ul>
    <div class="referrals-tile">
        <div class="dummy"></div>
        <div class="referrals-tile-background">
            <!-- MARKUP TRUNCATED -->
        </div>
    </div>
    <!-- MARKUP TRUNCATED -->
</div>
.mobi #content-1 ul.city-tiles {float: none; width: 100%;}
.mobi #content-1 ul.city-tiles li {float: none; display:inline-block; position: relative; width: 100%; height: auto; margin: 0 0 15px 0;}
#content-1 ul.city-tiles li .dummy {display: none;}
.mobi #content-1 ul.city-tiles li .dummy {display: block; margin-top: 52%;}
.mobi #content-1 ul.city-tiles li a {position: absolute; top: 0;}
.mobi #content-1 ul.city-tiles li a h3 {padding-top: 55px;}
.mobi #content-1 ul.city-tiles li .city-tile{margin: 0 auto; width: 100%; height: 100%; /**padding-bottom: 52%;**/ background-size: 700%; }
.mobi #content-1 .city-tile-mexico-city {background-position: 16.66667% 0; background-size: 700%;}
.mobi #content-1 .city-tile-tokyo {background-position: 100% 0; background-size: 700%;}
.mobi #content-1 .city-tile-ny {background-position: 0 0; background-size: 700%;}
.mobi #content-1 .city-tile-paris {background-position: 50% 0; background-size: 700%;}
.mobi #content-1 .referrals-tile {float: none; clear: both; display: inline-block; position: relative; width: 100%; height: auto; background-size: 100%; }
.mobi #content-1 .referrals-tile h3 {padding-top: 45px;}
#content-1 .referrals-tile .dummy {display: none;}
.mobi #content-1 .referrals-tile .dummy {display: block; margin-top: 113%;}
.mobi #content-1 .referrals-tile .referrals-tile-background {position: absolute; top: 0;}
.mobi #content-1 .col-12 {float: none;}
.mobi #content-1 .row-space-6 {margin-top: 15px; margin-bottom: 30px;}

Task 9:

This task deals with the content just before the footer zone i.e. where we have ‘Travel’, ‘Host’, and ‘Trust and Safety’ headings. This is a pretty straightforward collapse operation where we make the elements arrange themselves in a vertical fashion as opposed to horizontally. We also added id tags to the zone <div> as an identifier.


<!-- CONTENT ZONE – LEVEL 2 -->
<div id="content-2" class="page-container page-container-fixed">
    <!-- MARKUP TRUNCATED -->
</div>
.mobi #content-2 .row {margin-left: 0; margin-right: 0;}
.mobi #content-2 .row .col-4 {padding-left: 0; padding-right: 0; width: 100%; margin: 0 0 15px 0;}

Task 10:

This is the final task – Phew! – and it deals with the footer exclusively. Again, a simple task of collapsing the layout. And we didn’t need to make any HTML additions or updates here.


.mobi #footer.row {margin-left: 0; margin-right: 0;}
.mobi #footer .col-3 {padding-left: 0; padding-right: 0; width: 100%; margin: 0 0 15px 0;}

Step 5: Upload and Run

So now that we’re done, we can test it all out.

View the Old Non-Responsive SiteView the New Responsive Site

I would encourage you to try both out using first your desktop browser and then your mobile browser [via the emulator]. You may also want to use your actual smartphone if you can, or at the very least BrowserStack if you’ve got it.

Download the Source Files

The Results

AirBnB Mobile website Screenshot

Being that I used the Mobile Emulator on Google Chrome DevTools the whole time, it was pretty easy to see how the updated AirBnB website looks in a simulated phone environment. However, I have two mobile devices at hand: an iPod Touch [4th Generation] and a Google Galaxy Nexus and I tested it on each one with virtually identical results on each one. How does it look on your own smartphone?

This tutorial lumped mobile devices into one big basket and that’s why we used the .mobi CSS rule prefix exclusively [even though we could be more specific]. With a little more effort, we can hone the website further to look a little different on tablets, being that tablets have much more room to work with, especially in landscape.

In Closing but Moving Forward

So we’ve taken a perfectly fine website that wasn’t natively responsive, and we’ve made it responsive in a number of steps that should be routine for most web designers. The whole process took me about 4 to 5 hours from start to finish, and required a few innocuous HTML markup updates and a total 70 lines of additional CSS markup.

Using Restive.JS:

  • Responsive web design workflows become significantly optimized because all responsive CSS markup is inline and more intuitively accessible, eliminating the divided attention challenges inherent with using media queries.
  • Testing updated websites on various mobile devices is no longer necessary; once it works on one mobile device, it’ll pretty much work on all of them.
  • Thanks to the Turbo Classes feature, you can make responsive enhancements specific to form-factor and orientation inline using CSS rule prefixes like .mobi.tablet [for tablets], .mobi.phone.landscape [for phones in landscape orientation], and so on.
  • Maintaining your responsive CSS markup will be much easier because it’s all in one place. No need to refactor markup in multiple ‘markup realms’ as you would probably have to do using media queries.

Responsive web design has to become a much more efficient process if it’s going to get the massive adoption we expect it to. A good way of achieving this is via a better and faster design workflow. A Web that is natively responsive will be a good thing for everyone, especially mobile users. One website down… a couple gazillion more to go!


Top
This page may contain affiliate links. At no extra cost to you, we may earn a commission from any purchase via the links on our site. You can read our Disclosure Policy at any time.