RESS
RWD and Server Side Components

 

Sven Wolfermann | maddesigns

Sven Wolfermann (36)

Sven Wolfermann - freelancer for moder web development

www vs. m.
desktop vs mobile

desktop vs. mobile

dividing pages

large site (feature rich) vs. small size (performant)

desktop vs tablet vs mobile

dividing more pages?

large site vs. tablet vs. small size

vs. car vs. fridge vs. watch vs. …

Responsive Web Design

RWD Origin

A List Apart is responsive too now

Responsive Web Design

RWD

solves many things

moto.oakley.com

85.4MB, 471 HTTP requests!

THIS IS NOT RWD!

moto.oakley.com fail

ok, ok, Oakley does it better now:
JUST 14.2MB, 291 request (more than 70MB less)

with mobile user-agent? 6.7MB, 114 requests :/

RWD

has some issues

Guy Podjarny's RWD performance tests

sites have nearly same weight on mobile as on desktop

RWD is more

Performance

Browser Feature Detection

Testing browser features with Vanilla JS

Cutting the mustard

if('querySelector' in document
  && 'localStorage' in window
  && 'addEventListener' in window) {
    // bootstrap the javascript application
  }

if browser supports
'querySelector',
'localStorage'
and 'addEventListener'
do hot stuff

Modernizr

Client side feature detection

Modernizr is a JavaScript library that detects HTML5 & CSS3 features in the user's browser.

Modernizr

throw in <head>

<head>
  <script src="modernizr.js"></script>
</head>

Modernizr features test: geolocation

Modernizr.geolocation // true or false
if (Modernizr.geolocation) {
  navigator.geolocation.getCurrentPosition(show_map);
} else {
  // no native support; maybe try a fallback?
}

Modernizr

Modernizr can load different files based on tests

Modernizr.load({
  test: Modernizr.geolocation,
  yep : 'geo.js',
  nope: 'geo-polyfill.js'
});

Modernizr.load is not part of the "development" version

Modernizr adds classes to <html>

<html class="js flexbox canvas canvastext webgl no-touch geolocation 
postmessage hashchange history boxshadow cssanimations csscolumns
cssgradients csstransforms csstransforms3d csstransitions fontface
video audio localstorage svg inlinesvg">

Modernizr

Another Sample: datepicker

<script src="modernizr.js"></script>

<script>
Modernizr.load({
  test: Modernizr.inputtypes.date,
  nope: ['jquery.datepicker.js', 'jquery.datepicker.css'],
  complete: function () {
    $('input[type=date]').datepicker({
      dateFormat: 'yy-mm-dd'
    }); 
  }
});
</script>

load jQuery datepicker library for browsers that don't have native datepickers

Conditional loading

Conditional loading

Conditional loading

Conditional loading – window.matchMedia

Returns a new MediaQueryList object representing the parsed results of the specified media query string.

if (window.matchMedia("(min-width: 40em)").matches) {
  /* load secondary stuff */
}

matchMedia Polyfill

Modernizr.load and Picturefill uses matchMedia for example

Conditional loading – Modernizr.load

Modernizr loads scripts and CSS based on media queries

Modernizr.load([ 
  {
    test: Modernizr.mq("only screen and (min-width: 1051px)"),
    yep: '/js/large.js'
  },
  {
    test: Modernizr.mq("only screen and (min-width: 600px) and (max-width: 1050px)"),
    yep: '/js/medium.js'
  },
  {
    test: Modernizr.mq("only screen and (min-width: 320px) and (max-width: 599px)"),
    yep: '/js/small.js'
  }
]);

you can use EM in media queries too ;)

Conditional loading – pairing CSS & JS

holding CSS and JavaScript Breakpoints in sync

body:after {
  content: 'small';
  display: none;
}
@media (min-width: 650px) {
  body:after {
    content: 'middle';
  }
}
@media (min-width: 1200px) {
  body:after {
    content: 'large';
  }
}

Conditional loading – pairing CSS & JS

holding CSS and JavaScript Breakpoints in sync

var size = window.getComputedStyle(document.body,':after')
                 .getPropertyValue('content');
if (size == 'large') {
    // Load some more content.
}

Conditional loading – Ajax-include pattern

Replace:

<a href="..." data-replace="latest/fragment">Latest Articles</a>

Before:

<a href="..." data-before="latest/fragment">Latest Articles</a>

After:

<a href="..." data-after="latest/fragment">Latest Articles</a>

init with jQuery:

$("[data-replace],[data-before],[data-after]").ajaxInclude();

Browser-Sniffing

Browser-Sniffing

remember the old days? Not? You lucky guy!
UA-string history

Browser-Sniffing went wrong

Browser-Sniffing

is hard and unreliable

 

For example, Safari user agent string on an iOS7 iPhone:

Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X) 
AppleWebKit/546.10 (KHTML, like Gecko) Version/6.0 Mobile/7E18WD
Safari/8536.25

 

often browsers aims other browsers

detecting the "right" user agent is complicated

Parsing UA string is not a regex job

What?! UA-Sniffing is wild guessing

This is NOT a "mobile" detection!

if((navigator.userAgent.match(/iPhone/i)) || 
   (navigator.userAgent.match(/iPod/i))) {
   if (document.cookie.indexOf("mobile_redirect=false") == -1) {
     window.location = "http://m.yoursite.com/";
  }
}

more like this

// Check if UA is mobile (from http://detectmobilebrowsers.com/)
if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry
|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris
|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?
|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian
|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)
|xda|xiino/i.test(agent) {
  isUAMobile = true;
}

Device Detection

Device Detection Libraries

Device Detection Libraries

Problems

Client meets server

Client meets Server

set browser width cookie with JS

RESS = {};
 
RESS.writeCookie = function (name, value) { //cookie code }
 
//Store width in a cookie
RESS.storeSizes = function () {
    //Get screen width
    var width = window.innerWidth;
 
    // Set a cookie with the client side capabilities.
    RESS.writeCookie("RESS", "width." + width);
}
 
RESS.storeSizes();
        

Client meets Server

use cookie info in code

Setting a file path based on window.innerWidth

<?php 
  // grab the cookie value 
  $screenWidth = $_COOKIE['RESS']; 
  // set the img path var 
  if ($screenWidth <= 320) { 
    $imgPath = "320"; 
  } else if ($screenWidth < 960) { 
    $imgPath = "640"; 
  } else { 
    $imgPath = "960"; 
  } 
  // print out our image link 
  print "<img src='/rwd/images/".$imgPath."/car.jpg' alt='Car' />";
?>

Client meets Server

use cookie info in code

<?php
  if ($RESS["width"] >= 320 && $RESS["width"] <= 640) {
?>
  <div class="mobile-ad max-320">
    <?php include "/ads/320.php"?>
  </div>
<?php } ?>

Modernizr Server

Client features for the server

<?php
    include('modernizr-server.php');
    print 'The server knows:';
    foreach($modernizr as $feature=>$value) {
        print "
$feature: "; print_r($value); } ?> The server knows: canvas: 1 geolocation: 1 crosswindowmessaging: 1 indexeddb: 0 hashchange: 1 ...

RESS
Responsive Web Design + Server Side Components

RESS

In a nutshell, RESS combines adaptive layouts with server side component (not full page) optimization. So a single set of page templates define an entire Web site for all devices but key components within that site have device-class specific implementations that are rendered server side.
Luke Wroblewski @lukew

Sapient Nitro about RESS

Advantages of RESS

Disadvantages of RESS

RESS in the wild? -> Adaptive Images

Adaptive Images

Adaptive Images

Adaptive Images

  1. The HTML starts to load in the browser and a snippet of JS in the <head> writes a session cookie, storing the visitor's screen size in pixels.
  2. The browser then encounters an <img> tag and sends a request to the server for that image. It also sends the cookie, because that’s how browsers work.
  3. Apache receives the request for the image and immediately has a look in the website's .htaccess file, to see if there are any special instructions for serving files.
  4. There are! The .htaccess says "Dear server, any request you get for a JPG, GIF, or PNG file please send to the adaptive-images.php file instead."

Adaptive Images

  1. The PHP file looks for a cookie and finds that the user has a maximum screen size of 480px.
  2. It compares the cookie value with all $resolution sizes that were configured, and decides which matches best. In this case, an image maxing out at 480px wide.
  3. It then has a look inside the /ai-cache/480/ folder to see if a rescaled image already exists.
  4. We'll pretend it doesn’t - the PHP then goes to the actual requested URI to find the original file.
  5. It checks the image width. If that's smaller than the user's screen width it sends the image.
  6. If it's larger, the PHP creates a down-scaled copy and saves that into the /ai-cache/480/ folder ready for the next time it's needed, and sends it to the user.

Responsive Images
a topic for itself…

Detector

Detector (PHP RESS library)

combines UA-parsing and feature testing

no need for commercial device detection libraries

add your own feature tests and store the results using Modernizr's addTest() API

Detector

  1. HTTP request hits server
  2. Detector compares User-Agent with database
  3. if known, classify device and get back content
  4. if not, Modernizr makes feature detection, stores cookie
  5. reloads site, gives back specified content
  6. stores UA-String/features combination for later use

Detector device families

The default install of Detector will categorize browsers into one of three families.

// families.json
{
    "tablet": {
         "isTablet": true
    },
    "mobile-advanced": { 
         "isMobile": true,
         "features": ["cssanimations","localstorage","deviceorientation"]
    },
    "mobile-basic": { 
         "isMobile": true
    },
    "desktop": {
         "isComputer": true
    }
}

Detector sample

switch ads, basic sample

if ($ua->family == 'mobile-basic') {
  include "/ads/simple.php";
} elseif ($ua->family == 'mobile-advanced') {
  include "/ads/responsive-ads.php";
} else {
  include "/ads/desktop.php";
}

Detector video sample

if ($ua->video->h264 || $ua->video->webm) {
      print $html5Embed; // YouTube's <iframe> code
} else {
      print $simpleLink;
}

RESS examples

University of Notre Dame

West Virginia University

CNN

Scientiamobile

RESS isn't the holy grail (RWD isn't either)

RESS – further reading

Templating with Detector & Mustache for RESS

Is Adaptive Web Design Or RESS Better Than Responsive Design For SEO?

Adaptation: Why responsive design actually begins on the server

One more thing!

Client Hints

Client Hints is a new proposal by Ilja Grigorik and will allow clients to indicate a list of device and agent specific preferences. Spec Draft

(request)
GET /img.jpg HTTP/1.1
User-Agent: Awesome Browser
Accept: image/webp, image/jpg
CH: dpr=2.0

(response)
HTTP/1.1 200 OK
Server: Awesome Server
Content-Type: image/jpg
Content-Length: 124523
Vary: CH

(image data)

Client Hints

For example, given the following request header:

CH: dh=598, dw=384, dpr=2.0

The server knows that the client's screen height is 598px, width is 384px, as measured by density independent pixels on the device, and that the device pixel ratio is 2.0.

Client Hints

ReSrc.it can handle client hints now

Questions?

Thanks for your attention!

Sven Wolfermann | maddesigns

 

http://maddesigns.de/RESS/