Mobile Zone is brought to you in partnership with:

John regularly blogs about ColdFusion, JavaScript and other web technologies and contributes to several FOSS projects. His hobbies include writing in the third person. John is a DZone MVB and is not an employee of DZone and has posted 32 posts at DZone. You can read more from them at their website. View Full User Profile

Proof of Concept for Building Websites Mobile First

12.05.2013
| 5449 views |
  • submit to reddit

I've been thinking recently about techniques for building websites for multiple screen sizes. The common approach seems to be to use either a responsive website design or an adaptive website design (although there is some debate so to what adaptive web design means!) The Responsive website design approach (and one definition of adaptive website design) is based on the idea of 'reflowing' the page content and is great for making simple websites fit to different screen sizes - just look at how popular Twitter bootstrap is!

The problem I've found is that you may want to have different elements shown on different devices, or even the same elements, but in a different order. You can do this by having duplicate content and then hiding it or showing it using media queries, but it seems like a hack to me. There is also the problem that if you have a device with a small screen you don't want big images, whereas you do on a big screen. However, if you put this in your HTML <img src="http://placekitten.com/1024/400" style="display:none"> there is a good chance that the browser will still download that image even though it's not displayed - which means you're not really building a website optimized for the screen size.

This lead me to trying to think of a different approach to the problem - starting with a mobile first approach.

Now before I continue, I am not a front-end expert, particularly in media queries (and definitely not design!) so please consider this a proof of concept. OK, with that in mind - this is what I came up with...

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
  color: black;
}
article, div, nav, footer {
  border:1px dotted grey;
  background-color:yellow;
}
#bigisbest {
  background-color:lightblue;
}
#adverts {
  background-color:black;
  color:white;
}
@media screen and (max-width: 479px) {
  /* CSS for small screen */
  body {
    background-color: red;
  }
  #small {
    background-color: orange;
  }
}
@media screen and (min-width: 480px) and (max-width: 1023px) {
  /* CSS for medium screen */
  body {
    background-color: green;
  }
  #medium {
    background-color: hotpink;
  }
}
@media screen and (min-width: 1024px) {
  /* CSS for large screen */
  body {
    background-color: blue;
  }
  #large {
    background-color: purple;
    color:white;
  }
}
</style>
</head>
<body>

<!-- this is the 'mobile first' content -->
<article id="small">#small: <em>small screen</em></article>
<div id="adverts">#adverts: <em>The adverts go here</em></div>
<nav id="navigation">#navigation: <em>The navigation bar</em></nav>
<article id="content">#content: <em>The page content goes here</em></article>
<footer id="footer">#footer: <em>The page footer goes here</em></footer>
<div id="bigisbest">#bigisbest: <em>best viewed on large screen</em></article>
<!-- end of the 'mobile first' content -->

<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script>
// define the elements and order of the content of the page for each screen size
var layouts = {
  medium: {
    elements: ['medium','bigisbest','navigation','content','adverts','footer'],
    remove: ['small']
  },
  large: {
    elements: ['large','navigation','content','adverts','footer'],
    remove: ['small','bigisbest']
  }
};

jQuery(function ($){
  var device = getDevice(),
    $body = $('body'),
    i, 
    id,
    el,
    append;
  
  // see if there is a layout for this screen size
  if (layouts[device]){
  
    // loop backwards to build DOM for this screen size
    for (i=layouts[device].elements.length; i>0; i--){
      id = layouts[device].elements[i-1];
      el = document.getElementById(id);
      if (!el){
        console.warn(id + ' not found');
        break;
      }
      if (el.tagName==='SCRIPT'){
        // it's a template so append to DOM
        $body.prepend(el.innerHTML);
        console.info(id + ' template inserted');
      }else{
        // already on page so just move it
        $body.prepend(el);
        console.info(id + ' moved');
      }
    }
    
    // remove unwanted elements 
    if (layouts[device].remove){
      for (i=0; i<layouts[device].remove.length; i++){
        // on page but we don't want it
        id = layouts[device].remove[i];
        $('#'+id).remove();
        console.log(id + ' removed');
      };
    }
  }

  // simple function to detect screen size and give it a name
  function getDevice(){
    var viewportWidth = $(window).width();
    if(viewportWidth>=1024){
      return 'large';
    }else if(viewportWidth>=480){
      return 'medium';
    }else{
      return 'small';
    }
  }

});

// this is just here for IE...
if(!console) {console={}; console.log = function(){};}
</script>
    
<!-- 
HTML templates 
This is how the extra page 'elements' are defined ready to be applied to the simple layout above
Note that the script tag has a type of text/html
-->
<script type="text/html" id="large">
  <article id="large">
    #large <em>This is a large screen so huge image in here.</em><br>
    <img src="http://placekitten.com/1024/400">
  </article>
</script>

<script type="text/html" id="medium">
  <article id="medium">
    #medium: <em>This is a medium screen so show an image in here</em><br>
    <img src="http://placekitten.com/480/200">
  </article>
</script>
  
  
</body>
</html>

What I've got here is an HTML document which just has the elements I want on my small screen (mobile first) in the body as normal HTML. I also have some CSS which contains some simple media queries. The JavaScript starts by defining the other layouts and what elements I want and don't want on the page, it also specifies the order of the elements so I can use one element in my HTML markup but have it appear in different places depending on the screen size (rather than duplicating and using CSS to hide and show them). Next is the code to append / remove / insert elements (I've also got some console.log calls in there to demonstrate what is happening when you run it), and the last bit of the JavaScript is a function to detect the screen width and give it a name - which matches the layouts defined at the top of the JavaScript.

After the JavaScript I have defined some templates using a trick I stole from John Resig. To quote what he says:

Embedding scripts in your page that have a unknown content-type (such is the case here – the browser doesn’t know how to execute a text/html script) are simply ignored by the browser – and by search engines and screenreaders. It’s a perfect cloaking device for sneaking templates into your page. I like to use this technique for quick-and-dirty cases where I just need a little template or two on the page and want something light and fast.

As the code is ignored by the browser, I can have HTML in it I don't want to be rendered, and also the images, such as <img src="http://placekitten.com/1024/400"> are not downloaded until this template is added to the DOM.

So there you go, copy the script above, try resizing your browser and refreshing (I didn't bother to add JavaScript to detect a change in screen size so it only runs when the page loads) and see what you think. It was interesting to build even if it never gets used again!


Published at DZone with permission of John Whish, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)