Responsive design and server-side code

Update

This post has been completely re-written to describe a better way of making server-side code responsive. Instead of posting the variable through Ajax, it uses GET to load a fully-responsive page. A few code tweaks make the technique both user- and search-engine friendly.

Update 2: In screensize.php, changed window.location.href = $sizeurl; to window.location.replace($sizeurl); to fix back-button issue in IE.

Introduction

Responsive design — where the display of a web page responds to the size of the screen or browser window being used to view it — is awesome. It lets designers adjust the display of their website so it’s appropriate to the context, without having to maintain multiple versions of the site or design for specific devices.

But responsive design has one major drawback. Because it’s all done with client-side code (CSS, Javascript), it merely shows or hides content based on screen size. It does very little to reduce the amount of data actually being downloaded.

Put another way, responsive design changes the presentation of the data, but not the data itself.

What I’m going to show you in this post is a way to make your server-side code responsive, so that your website only serves the data that is actually needed for the user’s screen size.

The reason responsive design is done client-side is because server-side scripts have no way of detecting the user’s browser window size. A browser’s HTTP request doesn’t contain that information, and since server-side scripts don’t operate on the client’s machine, they can’t go and measure it for themselves. The two methods for detecting window size — javascript and CSS media queries — are both client-side methods.

What we’re going to do is use a very lightweight javascript to detect the screen size and load the page with the screen-size passed as a GET variable. Then we’ll throw in some instructions to search-engine crawlers to make the site SEO-friendly.

Details are below, using PHP and jQuery. You can see the demo here.

screensize.php

The first thing we’ll build is this file, which will be included at the top of every page of the site. It’s the code snippet that detects the screen size. We’ll discuss it below the code.

<?php
//Get size of screen
$size = $_GET['s'];
$size = empty($size) ? 800 : $size;
//Get page URL and strip off existing variables
$url="http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
$url = explode('?', $url);
$url = $url[0];

?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>

<script type="text/javascript">
 <!--
         $size = $(window).width();
        if($size != '<?php echo $size; ?>') {
            $sizeurl = '<?php echo $url; ?>?s=' + $size;
            window.location.replace($sizeurl);
        }
 //-->
</script>

This file contains the opening code (doctype, html) for all pages. But before any of that we have set PHP to do two things:

  1. listen for a GET variable named $size;
  2. if $size doesn’t exist, assign it a default value of 800 pixels. This makes the page friendly to search-engine crawlers, which don’t use javascript: any visitor with javascript disabled will see the 800-pixel version of the page.
  3. Calculate the current full URL minus any attached variables. This will be used for loading the responsive page.

Take a closer look at the Javascript. It does two things:

  1. Detects the width of the browser window;
  2. if the detected size is different from the currently recorded size, it takes the current page URL and adds a size variable, then reloads the page using the new URL.

The result is a URL that looks something like this:

http://mysite.com/index.php?s=1311

That lets your PHP script build the page knowing that the browser window is 1311 pixels wide. The “if” statement in the javascript can detect differences between the claimed width and the actual width, so that if a user follows the above link but has a browser window that is only 650 pixels wide, they will be served a version suitable for 650 pixels.

test.php

<?php include('screensize.php'); ?>

<title>Steven Ray: Server-side responsive design</title>

<link rel="canonical" href="http://<?php echo $url; ?>?s=800"/>

<link href="../demo.css" type="text/css" rel="stylesheet" />

<style type="text/css">
    img {max-width:100%;}
</style>

</head>
<body>

    <div id="content">
        <h1>Making server-side code responsive</h1>
           <p>Resize the window and reload the page to see it change. This paragraph displays regardless of window size.</p>

        <?php if($size > 480) { ?>
        <div id="desktop">
            <h2>Your screen size is <?php echo $size; ?> pixels. You are using a browser window that is greater than 480 pixels wide. So this text and image are large.</h2>
            <img src="venice_burano.png" alt="really large picture" title="really large picture of Burano, Venice, Italy" />
        </div>
        <?php } if($size > 0 && $size <= 480) { ?>
        <div id="mobile">
            <p>Your screen size is <?php echo $size; ?> pixels. You are using a browser window that is less than 480 pixels wide. So this text and image are small.</p>
            <img src="venice_burano_small.png" alt="small picture" title="Smaller version of picture of Burano, Venice, Italy" />
        </div>

    <?php } ?>

    </div>
</body>
</html>

The actual page itself contains the rest of the page’s HTML. Note the following features:

  1. At the top of the page, the include for screensize.php;
  2. A dynamically-generated canonical link with a screen width of 800 pixels. This is another way to persuade search-engine crawlers to see a particular version of the page. It’s optional, as crawlers should see the 800 pixel version anyway thanks to the default value for $size that we put into screensize.php.
  3. Two divs wrapped in “if” statements. If the browser window is wider than 480 pixels, the user is served a div with  large text and a giant picture. If it’s smaller than 480 pixels, they get the div with smaller text and a smaller picture. Because we’re handling this server side, the unneeded div is never sent to the user’s browser, so it doesn’t slow down page load times.
  4. The mobile div has “$size > 0” as a parameter. That keeps the mobile div from downloading when the page is first loaded and before $size has been set. Without that, non-mobile views would still try to download the mobile data.
  5. Anything not wrapped in a $size-aware “if” statement is served regardless of screen size.

You can confirm this by using Firebug or something similar on the demo page. If your window is wider than 480 pixels, you are served the giant picture but not the small one. If your window is 480 pixels wide or less, you’re served the small picture but not the giant one. The full-desktop version in the demo can take 6 or 7 seconds to download thanks to the nearly 4 megabyte photo; the “small screen” version usually loads in less than a second, thanks to the much smaller (250k) image.

This arrangement is infinitely flexible. Because $size is the screen size in pixels, you can cut your responsive gradations as fine as you want.

You can also make images responsive the way I did (by having separate <img> tags) or use a single <img> tag and write the “src” path dynamically based on $size. You could add or remove classes based on $size. And so on.

Limitations

There are some limitations to this technique:

  1. You have to ensure that the screen-size detection script is the very first thing to execute when the page is loaded. This might not be easy or even possible in complex sites that use a lot of javascript.
  2. Because this is server-side, the responsiveness only works once — when the page is served to the browser. If the user resizes their browser window without refreshing the page, the content won’t automatically adjust the way it does with client-side responsive design. So you’ll want to use this technique in conjunction with traditional client-side responsive design to get the best results. I’ve done that on the demo page by applying a “max-width:100%;” to the image so that it resizes a bit.
  3. Sample code would need tweaking to work with other GET variables. As written, the sample code strips out all variables from the URL when generating a size-aware URL. If your site passes other variables through URLs, you’d need to tweak the code that builds $url to strip out just the $size variable and to write an appropriate canonical link.

In summary: by using this method, you can responsively decide what data a user gets on the server side, and then responsively style it on the client side using CSS media queries.

Categories: Customer Experience.