Mastering SVG use for a retina web, fallbacks with PNG scriptSVGs (Scalable Vector Graphics) are the future graphics format of the web, they offer resolution-independent, fully scalable and crystal clear graphics. SVGs use XML to define paths and shapes, to create our graphic. Moving past JPG and PNG, SVG is the answer to Retina (HiDPI) displays, they even look better on standard display.
This Script has been updated, jQuery and Modernizr independent: 27.12.2012 – updated script
This tutorial explains how we can link an SVG through an image element, providing PNG fallbacks with Modernizr and jQuery/JavaScript supports.
Consider your options for SVG use, and then realise the full power of them; logos, icons, navigations, patterns, repeating backgrounds, all fully scalable to any size. This saves a bunch of time not having to create doubled-up graphics (@x2) for Retina. We will have to create a PNG version of our SVGs for fallbacks, but they’ll be the exact same size, not @x2 which saves resizing issues.
HTML5 and SVG
There are a few ways to use SVG, as an <object>, <embed>, <iframe>, <svg> and last but not least, the <img> tag – my favourite.
HTML5 spec allows for the use of an SVG inside the <img> tag, which makes it super easy and fast to get started using SVG, and this is where we’ll go in this tutorial. Here’s what our source code could look like using SVG inside an <img> tag:
<img src="logo.svg" alt="Logo">Pretty simple. And that’s it.
To create an SVG, you’ll need a vector graphics program like Adobe Illustrator. I recommend creating your SVG ‘to size’ – by this I mean that if your graphic needs to be 100×60 pixels, then use a canvas inside Illustrator at these dimensions, making sure your graphic fills the full width/height.
SVG Support
Usual story – IE9 does support SVG, but IE6/7/8 do not, and all modern browsers do. So what do we do for these browsers…
Modernizr Detection
First we need to know whether the browser can support SVG, and for this we’ll be using feature detection with Modernizr. We could test the features of a browser by doing the following:
if (Modernizr.svg) { // Supports SVG } else { // Doesn't support SVG (Fallback) }We declare SVG in our markup (logo.svg), so we don’t want to execute any functions if the browser does support SVG – it’s native. The only time we want to execute something is if it doesn’t support SVG.
Modernizr SVG Setup
There’s no point including an if or else function to provide a fallback for SVG, as we only want to execute a function if the browser doesn’t support, which is really the else part. Instead of declaring else, we can simply add an ‘!’ to invert the expression, and end up with:
if (!Modernizr.svg) { // Doesn't support SVG (Fallback) }This now essentially means, if the browser doesn’t support SVG, execute this.
SVG Fallback
Now we’ve setup our Modernizr to provide a fallback method, we need to replace the ‘.svg’ with ‘.png’ to provide an actual fallback solution.
I’ve put together a neat little jQuery script to do exactly that, and will swap all ‘.svg’ on the page with ‘.png’:
$('img[src*="svg"]').attr('src', function() { return $(this).attr('src').replace('.svg', '.png'); });First targeting an <img> element, and using a special CSS selector (that searches for any images that contain a source that includes ‘svg’). If so, we then run another function on the source attribute. We use jQuery’s .replace(); function to replace the ‘.svg’ in the filename with ‘.png’. And that’s the job done. All it means is that for any SVG you use, you’ll need to add a PNG fallback. It takes an extra minute at most per image.
Final Markup
<script src="jquery.js"></script> <script src="modernizr.js"></script> <script> if(!Modernizr.svg) { $('img[src*="svg"]').attr('src', function() { return $(this).attr('src').replace('.svg', '.png'); }); } </script>Without jQuery
If you’re not running jQuery, you can use this as a raw JavaScript alternative:
if (!Modernizr.svg) { var imgs = document.getElementsByTagName('img'); var endsWithDotSvg = /.*\.svg$/ var i = 0; var l = imgs.length; for(; i != l; ++i) { if(imgs[i].src.match(endsWithDotSvg)) { imgs[i].src = imgs[i].src.slice(0, -3) + 'png'; } } }CSS: SVG as Background
As far as I know, it’s impossible to detect and swap out an SVG as a background image, thankfully Modernizr has an alternative to running a script. When Modernizr loads, it adds all the browser supporting classes to the <html> tag. You’ll end up with something like this:
<html class="js flexbox canvas canvastext webgl no-touch geolocation postmessage websqldatabase indexeddb hashchange history draganddrop websockets rgba hsla multiplebgs backgroundsize borderimage borderradius boxshadow textshadow opacity cssanimations csscolumns cssgradients cssreflections csstransforms csstransforms3d csstransitions fontface generatedcontent video audio localstorage sessionstorage webworkers applicationcache svg inlinesvg smil svgclippaths">You’ll notice in there is ‘svg’. I’m using Chrome. If the browser didn’t support SVG, it would add the class ‘no-svg’ This allows us to create a CSS declaration for each, to provide a background fallback like so:
.background-class {} /* Shared properties for detected features */ .svg .background-class {background:url(img/graphic.svg);} /* SVG feature property */ .no-svg .background-class {background:url(img/graphic.png);} /* PNG feature property */Displaying broken images?
Some server setups support SVGs by default, if yours doesn’t, add this to your .htaccess file:
AddType image/svg xml svg svgz AddEncoding gzip svgzUPDATE: Custom SVG Feature Detection, Without Modernizr and jQuery
Here’s my SVG feature detection script, which creates an SVG from a NameSpace URI (w3.org/200/svg) and the qualifiedName. It’s entirely Modernizr and jQuery independent, so you can use it without either library. If the browser supports SVG, it adds an ‘svg’ class to the <html> tag. If SVG isn’t supported, you’ll get a ‘no-svg’ class complete with the fallback script to rip all the (.svg) extensions to (.png). I’ve optimised the JavaScript from the previous iteration too.
function supportsSVG() { return !! document.createElementNS && !! document.createElementNS('http://www.w3.org/2000/svg','svg').createSVGRect; } if (supportsSVG()) { document.documentElement.className += ' svg'; } else { document.documentElement.className += ' no-svg'; var imgs = document.getElementsByTagName('img'); var dotSVG = /.*\.svg$/; for (var i = 0; i != imgs.length; ++i) { if(imgs[i].src.match(dotSVG)) { imgs[i].src = imgs[i].src.slice(0, -3) + 'png'; } } }If you’re not fussed about the additional classnames, use this script, which inverts the expression (!) to run if the browser doesn’t support SVG.
function supportsSVG() { return !! document.createElementNS && !! document.createElementNS('http://www.w3.org/2000/svg','svg').createSVGRect; } if (!supportsSVG()) { var imgs = document.getElementsByTagName('img'); var dotSVG = /.*\.svg$/; for (var i = 0; i != imgs.length; ++i) { if(imgs[i].src.match(dotSVG)) { imgs[i].src = imgs[i].src.slice(0, -3) + 'png'; } } }Outputting from Illustrator
Once you've created your SVG from Illustrator, right-click it and open it inside a text-editor (Coda 2/Sublime Text 2/whatever) and remove the height and width that's generated. This will give you much more flexibility when working with your SVGs, all you'll need to do it add some styling to it instead with CSS.
The pieces you need to remove are the 'width' and 'height' attributes, and can be found on the opening <svg> tag (I've removed it from mine):
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 136 61" enable-background="new 0 0 136 61" xml:space="preserve">
FitText.js, a jQuery plugin for inflating web typeFitText makes font-sizes flexible. Use this plugin on your responsive design for ratio-based resizing of your headlines.
How it works
Here is a simple FitText setup:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script src="jquery.fittext.js"></script> <script> jQuery("#responsive_headline").fitText(); </script>Your text should now fluidly resize, by default: Font-size = 1/10th of the element's width.
The Compressor
If your text is resizing poorly, you'll want to turn tweak up/down "The Compressor". It works a little like a guitar amp. The default is 1.
jQuery("#responsive_headline").fitText(1.2); // Turn the compressor up (resizes more aggressively) jQuery("#responsive_headline").fitText(0.8); // Turn the compressor down (resizes less aggressively)This will hopefully give you a level of "control" that might not be pixel perfect, but resizes smoothly & nicely.
minFontSize & maxFontSize
FitText now allows you to specify two optional pixel values: minFontSize and maxFontSize. Great for situations when you want to preserve hierarchy.
jQuery("#responsive_headline").fitText(1.2, { minFontSize: '20px', maxFontSize: '40px' })CSS FAQ
- Make sure your headline has width!
- Use display: block; OR display: inline-block;+ a specified width (i.e. width: 100%).
- Tweak until you like it.
- Set a No-JS fallback font-size in your CSS.
- Fire
Changelog
- v 1.1 - FitText now ignores font-size and has minFontSize & maxFontSize options
- v 1.0.1 - Fix for broken font-size.
- v 1.0 - Initial Release
In Use:
If you want more exact fitting text, there are plugins for that for that! We recommend checking out BigText by Zach Leatherman or SlabText by Brian McAllister.
Download, Fork, Commit.
If you think you can make this better, please Download, Fork, & Commit. We'd love your see your ideas.
The Lowdown A lightweight, pure JavaScript library for responding to CSS media queries. Execute javascript callbacks for matching media queries Listen to browser resize and orientation change events to execute callbacks as media queries are matched (and unmatched!) Run one-time setup callbacks Unregister media queries and have a callback to perform any necessary cleanup Dependencies? None! Not even jQuery. The most you will need to do is provide a matchMedia polyfill if you wish to support old/incapable browsers. Use Cases Responsive Design — simplify altering your menu for use on small-screen devices. Mobile-first Design — to load in new content and resources for large-screen devices. Downloads & All That Jazz Latest Build Grab the latest code, ready to go, from one of the locations below: Development — unminified Production — minified If you wish to peruse/fork the source, feel free to do so over on GitHub. Install via Bower To install via the bower package manager, enter the following at the command line: bower install enquire Build From Source If you want build from source (and run all unit tests etc): git clone git://github.com/WickyNilliams/enquire.js.git cd enquire.js npm install grunt The Basics enquire.register The main method you will be dealing with is register. It's basic signature is as follows: enquire.register(mediaQuery /* string */, handler /* object || array || function */); query is the media query you wish to handle, and handler contains any logic to handle the media query. An example of usage is as follows: enquire.register("screen and (max-width:1000px)", { match : function() {}, // REQUIRED // Triggered when the media query transitions // *from an unmatched state to a matched state* unmatch : function() {}, // OPTIONAL // If supplied, triggered when the media query transitions // *from a matched state to an unmatched state*. setup : function() {}, // OPTIONAL // If supplied, a one-time setup function // triggered when the handler is first registered. deferSetup : true, // OPTIONAL, defaults to false // If set to true, defers execution the setup function until // the media query is first matched. Setup is still triggered just once. destroy : function() {} //OPTIONAL // If supplied, triggered when a hander is unregistered (covered later). // Enables you to provide lifecycle to responsive widgets. // Put cleanup logic here. }).listen(); // More on this next Responding To Queries You may have noticed the call to listen() in the last example, so let's talk about that. After you've registered your handlers you need to get enquire up and running. For this you have two options, fire or listen. A little note: the match or unmatch functions are called if, and only if, a media query's state has changed - that is, matched to unmatched, or unmatched to matched. This is true for both fire and listen. enquire.fire fire evaluates each of the registered media queries and handlers as they are at that point in time. This triggers the relevant callbacks for each of the media query's handlers, as per the conditions above. fire is handy if you don't care about browser events and want your handlers to be triggered just once on page load. enquire.listen listen registers event handlers for the browser's resize and orientationChange events. Each time one of these events is triggered, enquire makes a call to fire(), causing all media queries and handlers to be re-evaluated. To avoid spamming enquire with browser events (e.g. if the browser window is rapidly changing size), listen throttles events so that fire is only called if there have been no resize or orientation events in the last 500ms. This value can be altered by supplying a number of milliseconds as a parameter to listen: enquire.listen(10000); // 10 seconds, why not?! Delving Deeper Can I Haz More Than One Handlerz? You can indeed! It can be cumbersome to have all your logic in one handler, so you can also supply an array as the second parameter to register in order to support multiple handlers per media query: enquire.register("screen and (max-width:1000px)", [ { match : function() { console.log("handler 1 matched"); } }, { match : function() { console.log("handler 2 matched"); } } ]); Alternatively… You could, if you wish, achieve the same effect by calling register multiple times for the same media query: var query = "screen and (max-width:1000px)"; enquire.register(query, { match : function() { console.log("handler 1 matched"); } }); // later in code... enquire.register(query, { match : function() { console.log("handler 2 matched"); } }); Whilst the array pattern is generally preferred, this pattern of multiple calls to register is useful for when you don't want to register all handlers at one time. This won't overwrite any previous handler for the media query as enquire uses the media query itself as a lookup key on it's internal dictionary. Thus, the second handler is appended to the list of handlers already registered for that media query. Multiple Queries, Sir? As well as multiple handlers per media query, multiple media queries can be registered with enquire. Calls to register can be chained together for this purpose. enquire.register("screen and (max-width:1000px)", { match : function() { console.log("handler max-width 1000px"); } }).register("screen and (max-width:500px)", { match : function() { console.log("handler max-width 500px"); } }).listen(); Setup Supplying a setup callback with your query handler allows you to get all your expensive DOM manipulation out of the way up-front. The setup callback is called once and once only. By default it is called when the handler is first registered. You can defer setup until the first time the media query matches by setting the deferSetup flag to true. Unregister Handlers Sometimes you may wish to unregister a handler or group of handlers. For that we have the unregister method. enquire.unregister(mediaQuery /* string */, handler /* function || object */); The first parameter that ungreigster accepts is the media query, and the second is a reference to the specific handler you wish to unregister. The second parameter can be optionally excluded which unregisters all handlers for the supplied media query. When a handler is unregistered its destroy callback is executed. If a handler does not have a destroy callback then the unmatch callback is fired instead. Once a handler is unregistered it will no longer respond to changes to a media query's state. The following example shows how unregister can be used and the effects it has on handlers: var mediaQuery = "screen and (max-width:320px)", handler1 = { // handler1 has no destroy or unmatch callback, match : function() { // so nothing happens when it gets unregistered console.log("handler1 matched"); } }, handler2 = { // handler2 doesn't have a destroy callback, match : function() { // so unmatch is called as a fall back console.log("handler2 matched"); }, unmatch : function() { console.log("handler2 unmatched"); } }, handler3 = { // handler3 has both unmatch and destory callbacks, match : function() { // destroy will be called when it is unregistered console.log("handler3 matched"); }, unmatch : function() { console.log("handler3 unmatched"); }, destroy : function() { console.log("handler3 destroyed"); } }; enquire.register(mediaQuery, [ handler1, handler2, handler3 ]); enquire.unregister(mediaQuery, handler3); // unregister just handler3 // logs "handler3 destroyed" enquire.unregister(mediaQuery); // unregister all handlers for this media query. // logs "handler2 unmatched" Mobile-First If you're taking a mobile-first approach you will typically run into issues with incapable legacy browsers not understanding CSS3 media queries, meaning that browsers such as IE8 will be served the mobile versions of the site. Again, enquire has you covered here! register can accept an optional third parameter, shouldDegrade. When this is passed as true (it defaults to false) it signifies to enquire that if the browser is incapable of understanding CSS3 media queries, then always consider this query a match. enquire.register("screen and (min-width:900px)", function() { //execute some code for large-screen devices }, true); // note the `true`! Because this only affects incapable browsers, modern browsers will respect the media query and behave as you would expect. This allows you to adopt the mobile-first paradigm, whilst still serving a desktop experience to incapable browsers. Legacy Support enquire relies on the matchMedia API, which isn't universally supported in browsers. Fear not, using a matchMedia polyfill is more than sufficient for enquire's purposes. If you are using Modernizr (and you should be!) it's as easy as this: Modernizr.load([ //first test need for polyfill { test: window.matchMedia, nope: "/path/to/polyfill.js" }, //and then load enquire "/path/to/enquire.js" ]); This is the approach that this site adopts. License Licensed under the MIT License.
I use these on most of my sites to ensure the type is appropriately kerned, smoothened and doesn't bold funny when going through a transition or opacity change (you can see an example of such weirdness by hovering over the links right here on Coderwall). Most of them are CSS3 and many are Webkit-only, so I can't completely recommend them for your site or application, but try them out for fun.
1. Subpixel-Antialiasing (and Antialiasing too)
-webkit-font-smoothing: subpixel-antialiased; font-smoothing: subpixel-antialiased;Smooths out rough edges but causes type to look thicker. If you're working with type that is weighted to begin with, you may prefer to go the plain antialiased; route. Note that if you're working with subpixel-antialiasing and have animations, opacity changes or anything else that uses the browser's hardware acceleration, it will switch to antialiasing; during the transition. You can either set that element to antialiased; to begin with or utilize the translate3d method (#4 below) .
2. Optimize Legibility (Kerning)
text-rendering: optimizeLegibility;Better aligns each character against its siblings. For additional letter-spacing tweaking, you'll get the most precision out of using ex instead of em's or worse - decimated pixels (this doesn't actually work). -0.08ex to -0.045ex are some examples straight from my CSS so you can see how delicate it is (or how OCD I am).
3. Transparent Text-Shadow
text-shadow: 0 0 0 rgba(0,0,0,0);This isn't super necessary, and you might find it more useful to add to ::selection, but it ensures that the text doesn't get a shadow when highlighted.
4. Stop Aliasing Changes during CSS3 Animations, Opacity Changes & Transitions ()
-webkit-transform: translate3d(0,0,0); -moz-tranform: translate3d(0,0,0); transform: translate3d(0,0,0);Applied to an element that animates or otherwise transitions, this will override the browser's natural tendency to use its hardware acceleration's antialiasing setting. Unfortunately it has a side-effect of thinning out all text on a page even if it's buried deep in the DOM, so you may need to adjust the weight of your type or switch entirely to [-webkit-]font-smoothing: antialiased;.
5. Better Antialiasing on Rotated Elements (Try Both, Pick One)
-webkit-backface-visibility:hidden; -webkit-transform-style: preserve-3d;So this isn't for type, but if you're going to be messing around with transitions, you may end up needing it. I've only tested them on a simple rotated object, but both of them seem to achieve the same effect of better smoothing the rough edges. Like the above properties, applying these to an element produced thinned out all text on the page when I used them.
6. Additional Suggestions (aka Windows ClearType'd)
If you know the element is going to be on a solid background, you can further refine the way it looks by adding one or two text-shadows that are slightly lighter than the text color itself.
7. General Advice
Sometimes, despite putting these properties within html {} or body {}, it won't affect certain texts (admittedly I've not been paying attention to commonality between elements when this happens). Instead of having to paste it all over again, I'd suggest using LESS/SCSS to create a mixin so you can just call it when you need to.
Base width Fluid and fixed (724px, 940px, 1170px; below 767px are single column and vertically stacked) Fluid (max-width 1200px) Fluid (max-width 100%) 960px Columns 12 12 12-24 with customizer 16 Single column class syntax .span1 .one.columns .one.column .one.column Two column class syntax .span2 .two.columns .two.columns .two.columns Container syntax <div class="container> or <div class="container-fluid"> <div class="container"> Not available <div class="container"> Row syntax <div class="row"> <div class="span4">...</div> <div class="span8">...</div> </div> <div class="row"> <div class="four columns">...</div> <div class="eight columns">...</div> </div> <div class="row"> <div class="four columns">...</div> <div class="eight columns">...</div> </div> <div class="row"> <div class="four columns">...</div> <div class="eight columns">...</div> </div> Nested column syntax <div class="row"> <div class="span6"> <div class="row"> <!-- nested columns add up to parent total --> <div class="span3">...</div> <div class="span3">...</div> </div> </div> </div> <div class="row"> <div class="six columns"> <div class="row"> <!-- nested columns add up to 12 --> <div class="six columns">...</div> <div class="six columns">...</div> </div> </div> </div> <div class="row"> <div class="six columns"> <div class="row"> <!-- nested columns add up to 12 --> <div class="six columns">...</div> <div class="six columns">...</div> </div> </div> </div> <div class="row"> <div class="six columns clearfix"> <!-- nested columns add up to parent total --> <div class="three columns alpha">...</div> <div class="three columns omega">...</div> </div> </div> Offset column syntax <div class="row"> <div class="span4">...</div> <div class="span4 offset4">...</div> </div> <div class="row"> <div class="four columns">...</div> <div class="four columns offset-by-four">...</div> </div> <div class="row"> <div class="four columns">...</div> <div class="four columns offset-by-four">...</div> </div> <div class="row"> <div class="four columns">...</div> <div class="four columns offset-by-four">...</div> </div> Centered syntax Not available <div class="row"> <div class="three columns centered">...</div> </div> <div class="row"> <div class="three columns centered">...</div> </div> Not available Ordering syntax Not available <div class="row display"> <div class="two columns push-ten">first in mobile/last in desktop</div> <div class="ten columns pull-two">first in desktop/last in mobile</div> </div> <div class="row"> <div class="two columns push-ten">first in mobile/last in desktop</div> <div class="ten columns pull-two">first in desktop/last in mobile</div> </div> Not available Four column mobile syntax Not available <div class="row display"> <div class="three phone-one columns">...</div> <div class="nine phone-three columns">...</div> </div> <div class="row display"> <div class="three mobile-one columns">...</div> <div class="nine mobile-three columns">...</div> </div> Not available Block grids syntax Not available <ul class="block-grid two-up"> <li>Two-up element</li> <li>Two-up element</li> <li>Two-up element</li> <li>Two-up element</li> <li>Two-up element</li> </ul> <ul class="block-grid two-up"> <li>Two-up element</li> <li>Two-up element</li> <li>Two-up element</li> <li>Two-up element</li> <li>Two-up element</li> </ul> Not available Visibility class syntax Device based: .visible-desktop .visible-tablet .visible-phone .hidden-desktop .hidden-tablet .hidden-phone Device based: .show-on-desktops .show-on-tablets .show-on-phones .hide-on-desktops .hide-on-tablets .hide-on-phones Screen size based: .show-for-xlarge .show-for-large .show-for-large-up .show-for-medium .show-for-medium-down .show-for-small .hide-for-xlarge .hide-for-large .hide-for-large-up .hide-for-medium .hide-for-medium-down .hide-for-small Landscape based: .show-for-landscape .show-for-portrait Touch based: .show-for-touch .hide-for-touch Print based: .print-only .hide-on-print Not available Media queries syntax /* Landscape phones and down */ @media (max-width: 480px) { ... } /* Landscape phone to portrait tablet */ @media (max-width: 767px) { ... } /* Portrait tablet to landscape and desktop */ @media (min-width: 768px) and (max-width: 979px) { ... } /* Large desktop */ @media (min-width: 1200px) { ... } /* Mobile wide */ @media handheld, only screen and (max-width: 1023px) { ... } /* Mobile narrow */ @media handheld, only screen and (max-width: 767px) { ... } /* Desktop wide */ @media only screen and (max-width: 1280px) and (min-width: 768px) { ... } /* Desktop narrow */ @media only screen and (max-width: 767px) { ... } /* Very large display targeting */ @media only screen and (min-width: 1441px) { ... } /* Medium display targeting */ @media only screen and (max-width: 1279px) and (min-width: 768px) { ... } /* Small display targeting */ @media only screen and (max-width: 767px) { ... } /* Small display targeting */ @media only screen and (max-width: 767px) { ... } /* Landscape orientation targeting */ @media screen and (orientation: landscape) { ... } /* Portrait orientation targeting */ @media screen and (orientation: portrait) { ... } /* Mobile styles */ @media only screen and (max-device-width: 1280px) { ... } @media only screen and (max-width: 1279px) and (min-width: 768px) { ... } /* Smaller than standard 960 (devices and browsers) */ @media only screen and (max-width: 959px) {} /* Tablet Portrait size to standard 960 (devices and browsers) */ @media only screen and (min-width: 768px) and (max-width: 959px) {} /* All Mobile Sizes (devices and browser) */ @media only screen and (max-width: 767px) { ... } /* Mobile Landscape Size to Tablet Portrait (devices and browsers) */ @media only screen and (min-width: 480px) and (max-width: 767px) { ... } /* Mobile Portrait Size to Mobile Landscape Size (devices and browsers) */ @media only screen and (max-width: 479px) { ... }
What’s your device’s min-device-pixel-ratio?If you have a device that isn’t listed below and has a min-device-pixel-ratio that’s not 1, please let me know and I’ll add it to the list. I’m @marcedwards on Twitter and @marc on App.net.
Devices with min-device-pixel-ratio 1All non-Retina Macs
All non-Retina iOS devices
All PCs running Windows prior to Windows 8?
Acer Iconia A500
Samsung Galaxy Tab 10.1
Samsung Galaxy SDevices with min-device-pixel-ratio 1.3
Google Nexus 7
Devices with min-device-pixel-ratio 1.5
Google Nexus S
Samsung Galaxy S II
HTC Desire
HTC Incredible S
HTC Velocity
HTC SensationDevices with min-device-pixel-ratio 2
iPhone 4
iPhone 4S
iPad (3rd generation)
MacBook Pro with Retina display
Google Galaxy Nexus
Samsung Galaxy S III
Sony Xperia S
HTC One XBelow is an additional test using min-resolution and dpi instead of min-device-pixel-ratio. This seems to be the way Internet Explorer handles pixel density.
EventSource pattern to mantain the connection to the server open
Create rapid and logical page layout and app prototypes with Gumby Framework, a responsive CSS framework based on the 960 grid you already know.
![]()
![]()
Off Canvas What Now?
If you've used Facebook's iPhone app (or Path, or any number of apps that now follow this convention) then you've seen an off canvas panel in a native app. You hit a button and a panel slides in from the left (or depending on how you look at it, the main panel slides out of the way). Luke Wroblewski, author of Mobile First, mentioned this style of layout in his roundup of mobile layout patterns.
He and Jason Weaver then worked to create a batch of layouts, which they published to demonstrate how layouts like this could work on the Web. We were so impressed that we wanted to make that style of layout available for Foundation users, and the four layouts below are a few different examples of off-canvas layouts created specifically for Foundation. Download these not just to see how a layout like this works (it's pretty crafty), but also to get a sneak peek at Foundation 3, which these were built with.
Four Layouts, No Waiting
We've put together four different layouts, each with specific functionality and code for you to check out and download. Be sure to check these out on different devices, or resize your browser down to see the mobile device presentation.
![]()
This layout moves the nav menu to the bottom on mobile, and enables a sliding sidebar.
View this layout →![]()
This layout has a sliding top nav as well as a sliding sidebar.
View this layout →Download the Code including Foundation 3.0![]()
A very different layout, this has full-width panels stacked on desktops but enables a tabbed panel layout on mobile.
View this layout →![]()
This layout moves the navigation to the sidebar on mobile only.
View this layout →How to Use These Layouts
The download below includes everything you need to play with these layouts and use them on your own site or app. You'll find a few things in the download:
- Foundation 3.0, the release version of Foundation 3. We originally developed this with an alpha release, but have updated to he 3.0 release. This includes the new grid, changes to the structure and CSS (like box-sizing), new modular-scale based typography, new elements, and a lot more.
- CSS and SCSS — if you've used Sass and Compass before everything is included to check out the SCSS implementation. You'll need the Compass, Linguistics, and Modular-Scale gems to run this. Note: You do not need to use or know Sass/SCSS to use these layouts
- Four off-canvas layouts — we modified or built four layouts after the work done by Luke and Jason, each showing different ways of setting up an off-canvas layout. There are four test files included (offcanvas-1.html, etc) so you can check them out on any kind of device.
- offcanvas.css, offcanvas.js — the four layouts require these two files to function.
Each of these layouts has specific requirements for syntax and order, so pay close mind to how these examples are put together. You'll need a solid understanding of HTML and CSS (and JS / jQuery) to pick these layouts apart.
Repurpose, Rebuild, Reuse
These are examples, but they are durable, tested code. Feel free to use these as any other Foundation core or add-on component, MIT licensed and freely available. At ZURB, we're passionate about multi-device design (just like Luke and Jason) and we want these to be powerful and simple to use. The CSS involved is pretty crafty so you'll need to dig in a little, but it's well worth it.
Device Compatibility
We tested this on modern desktop browsers as well as iOS, Android and Windows phone.
Works with Foundation
This technique was designed in and for Foundation. Check out Foundation to see what else you can do with a responsive framework.
Available on GitHub
Find the latest code on Github, or go there to log / search through any issues. You can pop it open right in GitHub for Mac, here »
Thoughts?
Read our blog post for more background on why we developed this, to see what others are saying, or to let us know what you think.
Responsive Design
Built for all devices big and small, base has got you covered.
Foundation Styles
Custom styles for headings, tables, blockquotes forms and much more.
Accessibility in mind
Works with screen readers in mind and has comes with JS fallbacks.
The Lowdown A lightweight JavaScript library for handling CSS media queries. Deal with your media queries being matched (and even unmatched!) Respond to browser events with aplomb And if you want to get really fancy, run one-time setup routines Dependencies? None! Not even jQuery. The most you will need to do is provide a matchMedia polyfill if you wish to support older browsers. Use Cases Responsive Design Mobile-first Design Assist older browsers with media queries Downloads & All That Jazz Grab the code, ready to go, from one of the locations below: Development — unminified Production — minified If you wish to peruse/fork the source, feel free to do so over on GitHub. The Basics enquire.register The main method you will be dealing with is register. It's basic signature is as follows: enquire.register(query /* string */, handler /* object || array */); query is the media query you wish to handle, and handler is an object containing any logic to handle the query. An example of usage is as follows: enquire.register("screen and (max-width:1000px)", { match : function() {}, // REQUIRED // Triggered when the media query transitions // *from an unmatched to a matched state* unmatch : function() {}, // OPTIONAL // If supplied, triggered when the media query transitions // *from a matched state to an unmatched state*. setup : function() {}, // OPTIONAL // If supplied, triggered once immediately upon registration of the handler deferSetup : true // OPTIONAL, defaults to false // If set to true, defers execution the setup function // until the media query is first matched. still triggered just once }); Delving Deeper Can I haz more than one handlerz? You can indeed! It can be cumbersome to have all your logic in one handler, so you can also supply an Array as the second parameter to register to support multiple handlers per query: enquire.register("screen and (max-width:1000px)", [ { match : function() { console.log("handler 1 matched"); } }, { match : function() { console.log("handler 2 matched"); } } ]); Alternatively… You could, if you wish, achieve the same effect by calling register multiple times for the same query: var query = "screen and (max-width:1000px)"; enquire.register(query, { match : function() { console.log("handler 1 matched"); } }); // later in code... enquire.register(query, { match : function() { console.log("handler 2 matched"); } }); Whilst the array pattern is generally preferred, this pattern of multiple calls to register is useful for when you don't want to register all handlers at one time. This won't overwrite any previous handler for the query as enquire uses the media query itself as a lookup key on it's internal dictionary. Thus, the second handler is appended to the list of handlers already registered for that query. Multiple Queries, Sir? As well as multiple handlers per query, multiple queries can be registered with enquire. Calls to register can be chained together for this purpose. enquire.register("screen and (max-width:1000px)", { match : function() { console.log("handler max-width 1000px"); } }).register("screen and (max-width:500px)", { match : function() { console.log("handler max-width 500px"); } }).listen(); //read on for info on listen() Setup Supplying a setup function with your query handler allows you to get all your expensive DOM manipulation out of the way up-front. The setup function is called once and once only. By default it is called when a query is first registered. You can defer setup until the first time the media query matches by setting the deferSetup flag to true. Get The Show On The Road You may have noticed the call to listen() in the last example, so let's talk about that. After you've registered your handlers you need to get enquire up and running. For this you have two options, fire or listen. A little note: the match or unmatch functions are called if, and only if, a query's state has changed - that is, matched to unmatched, or unmatched to matched. This is true for both fire and listen. enquire.fire fire evaluates each of the registered media queries at that time, triggering the relevant functions for each of the query's handlers, as per the conditions above. fire is handy if you don't care about browser events and want your handlers to be triggered just once on page load. enquire.listen listen registers event handlers for the browser's resize and orientation change events. Each time one of these events is triggered, enquire will iterate over each media query calling the relevant methods as per the conditions above. To avoid spamming enquire with browser events (e.g. if the browser window is rapidly changing size), listen delays evaluation of media queries until there have been no resize or orientation events in the last 500ms. This value can be altered by supplying a parameter to listen: enquire.listen(10000); // 10 seconds, why not?! listen also contains an implicit call to fire, so you do not have to do this manually - one call to listen will have you covered now and in future. Legacy Support enquire relies on the matchMedia API, which isn't universally supported in browsers. Fear not, using a matchMedia polyfill is more than sufficient for enquire's purposes. If you are using Modernizr (and you should be!) it's as easy as this: Modernizr.load([ //first test need for polyfill { test: window.matchMedia, nope: "/path/to/polyfill.js" }, //and then load enquire "/path/to/enquire.js" ]); This is the approach that this site adopts. License Licensed under the MIT License.
The US presidential race is heading into full swing, which means we’ll soon see the candidates intensely debate the country’s hot-button issues. While the candidates are busy battling it out, the Web design world is entrenched in its own debate about how to address the mobile Web: creating separate mobile websites versus creating responsive websites.
It just so happens that the two US presidential candidates have chosen different mobile strategies for their official websites. In the red corner is Republican candidate Mitt Romney’s dedicated mobile website, and in the blue corner is incumbent Barack Obama’s responsive website.
We’re going to see how well their mobile Web experiences stack up. But before we do, we need to ask a few questions.
Why Bother With Mobile?
Why are the candidates attempting to create mobile-optimized Web experiences? Well, the US population is sitting at around 311 million. Of those 311 million people, about half of US adults own a smartphone. On top of that, for a whopping 28% of Americans, a mobile device is their primary way of accessing the Web. So, for a candidate looking to reach potential voters, mobile provides a tremendous opportunity to connect with their constituents.
What’s more is that people are arriving to the mobile Web through more diverse channels than ever before. In addition to direct and referral traffic, candidates are using social networks, email campaigns, SMS campaigns, search and more. Because these activities are increasingly happening on mobile, creating Web experiences optimized for mobile makes even more sense for the candidates.
These are just a few channels that drive people to the Web on mobile devices.The candidates see mobile as a big opportunity to turn visitors into voters. We can see the candidates’ incentive, but now we must ask another important “Why” question.
Why Would Anyone Visit A Candidate’s Website?
Who is visiting these candidates’ websites? What are they looking for? Why might they want on a mobile device?
Visitors are generally either looking for information on the candidates or looking to take action.
The Information-Oriented Visitor
The information-oriented user might be looking for basic information about the candidate, such as his biography, background or stance on issues. They might also be interested in regularly updated information such as news, locale-specific blog posts and information like myth busting (where the candidate tries to dispel nasty rumors circulating in the media). The official websites give the candidates a chance to deliver information straight from the horse’s mouth, free from news media bias and inaccuracies that arise from crowd-sourced information.
The Action-Oriented Visitor
The action-oriented user is looking to support the candidate in some way, shape or form. Both websites prominently feature calls to action asking visitors to donate money to the campaign and to sign up for their email newsletter. Action-oriented users might also want to connect with the candidates on social media channels, volunteer their time at an event, make calls on the candidate’s behalf or shop for merchandise.
The candidates have accounted for these use cases in their Web experiences. Let’s look at how they execute on mobile.
Criteria For Judging: Layon’s Theory of Mobile Motivation
The effectiveness of Romney and Obama’s positions on the economy, foreign policy, social issues and other important subjects depends on certain criteria. Likewise, we need to establish a set of criteria to determine the effectiveness of the candidates’ mobile Web experiences.
Mobile Web designer Kristofer Layon has a clever way of looking at the hierarchy of mobile needs. His “theory of mobile motivation” is based on Maslow’s hierarchy of needs, a psychological theory that identifies the various levels of human needs.
Kristofer Layon has applied that theory to the needs of mobile Web users, where primary access and navigation are the most essential aspects of an experience, and at the top of the pyramid are HTML5 enhancements (such as offline storage and a boatload of other features).
Layon’s hierarchy of mobile needs.Let’s apply a simplified version of Kristofer’s hierarchy to evaluate how well each candidate’s website holds up.
My simplified version of Layon’s hierarchy of mobile needs.Access
First and foremost, users need to be able to access an experience. The most beautiful design in the world will accomplish nothing if people can’t view it. Historically, the mobile Web has been viewed as the Web Lite™, whose users get served only a subset of content and functionality. However, a whopping 28% of US residents use a mobile device as their primary way to access the Web. With more people relying on their mobile devices to access the Web, achieving content parity and giving users access to a full experience regardless of their device or configuration are more important than ever. Let’s see how the presidential candidates’ mobile Web experiences hold up.
Barack Obama
Barack Obama’s “mobile” website has no “full site” link because it shares the same code base as the “desktop” website. Content on a responsive website lives under one roof, which gives the website a better chance of achieving content parity. And while responsive designers can (and do) hide content from small-screen users, responsive design affords less opportunity to fork the content and create disparate experiences, which would deprive certain users of valuable information and features.
Mitt Romney
Mitt Romney’s website uses device detection to route mobile users to a separate dedicated website. Creating this separate experience allows the designers to tailor the mobile Web experience, but a separate design and subdomain also opens the door to some serious problems.
The main problem with Mitt Romney’s mobile website is that only a fraction of the full website’s features are included.
Only some of the features from the full website have made it onto the mobile-specific website.It’s a myth that mobile users don’t want access to all of the information and functionality available to desktop users. The absence of key content on Romney’s mobile website leaves a lot of serious questions unanswered for potential supporters, such as “Who is this guy, anyway?,” “Where does he stand on issues?,” “What’s his plan for the economy?,” “What can he do for my state?” and “Where can I shop?”
Another common problem with separate mobile websites is URL management. Because desktop and mobile content live at separate URLs, device detection is required to route users to the appropriate site. Unfortunately, many websites don’t go deep enough in their URL redirection, so desktop users will get sent to mobile content and vice versa. This becomes apparent when mobile content gets shared by mobile users on social networks and then gets accessed by desktop users:
Issues arise when a mobile URL is accessed from a desktop.As we can see, having Web content all under the same roof and URL definitely makes it easier to give visitors access to the content they’re looking for, regardless of the device they happen to be using.
Interact
Basic access to a website is essential, but what happens once the visitor is on the website? They need to be able to interact with the content and get around the website. Let’s start with one of the most common and important interactions: navigation.
Navigation
Navigation, especially on mobile, should be like a good friend: there when you need it, but considerate enough to give you your space. When navigation takes up a ton of real estate, it gets in the way and becomes that annoying friend who won’t leave you alone. When it’s inaccessible, hidden or just hard to reach, it becomes that friend who’s conveniently absent when you’re looking for help to move to your new apartment.
Barack Obama
Obama’s website serves navigation at the top for large screens and then transforms it into a left fly-out menu for screens narrower than 1024 pixels.Obama’s website has Facebook-esque left fly-out navigation for small screen resolutions. Among popular responsive techniques, this one is relatively complex and opens the door to problems. As Stephanie Rieger points out in her post “A Plea for Progressive Enhancement,” Obama’s navigation fails on a whole load of mobile devices: “And the menu failed. Never even opened. Suddenly, the site was without navigation… at all.”
These situations, regardless of approach, can be avoided using proper progressive-enhancement techniques, but it’s a good example of the challenges that arise when creating adaptive experiences.
Mitt Romney
Romney’s mobile website has a dashboard home page and “Back” and “Home” links for inner pages. The full website has top navigation.Romney’s relatively simple mobile navigation contrasts starkly with Obama’s navigation. It sits as a dashboard on the home page, and all inner pages simply include a “Back” button and a logo that links back to the home page.
This navigation technique certainly solves the problem of limited real estate and avoids complexity, but it creates other issues. Requiring a full page refresh just to jump to another section of the website isn’t very efficient. A logo as a button doesn’t exactly scream “Click me for navigation!” And the “Back” button does nothing if the visitor arrives at the website on a page other than the home page. It’s also worth noting that mobile browsers already have their own back buttons, so duplicating that functionality in the header could be regarded as wasted space.
Scrolling
Scrolling is an interesting interaction on mobile devices. The “fold” as a set pixel value is a myth, but users still need to be able to access the core content as quickly as possible.
Mitt Romney
Romney’s mobile website has an acceptable page length. Not much chrome or clutter before you get to the core content, and for the most part the user doesn’t have to scroll much to find what they need.
Barack Obama
Obama’s pages contain a massive amount of content, often introducing entirely new sections far down in the flow. The result is extremely long pages that have serious problems.
Scrolling through disparate content types is not a good experience. How do users figure out that other content exists? Finding what they’re looking for becomes a scavenger hunt. While they might be all right with sifting through one or two content types (for example, a blog’s main article and subsequent sidebar), a lot of disparate types makes the content unfindable and the page impractical.
While content parity is essential for mobile users, that doesn’t mean websites have to be one size fits all. Techniques like lazy loading and conditional loading enable Web creators to provide access to full content without having to stuff it all on the page at the same time. And while those techniques can be extremely effective, there’s no substitute for subtracting supplementary content everywhere to focus on core content.
In addition to the annoyance caused by having to scroll through so much content, these massively long pages have another downside: terrible performance.
Perform
Performance has gotten the short end of the stick. Web creators have assumed too much about the user’s context (“Of course, the user has a fast connection!” “Of course, their machine is powerful!”). As a result of these convenient assumptions, the average page now weighs a whopping 1 MB.
One MB might not seem like a big deal until we look at the mobile user’s expectations. 71% of mobile users expect mobile websites to load as fast, if not faster, than desktop websites, and 74% of mobile visitors will abandon a website if it takes more than 5 seconds to load. In other words, you have 5 seconds to get someone’s attention. Make it count.
To evaluate how well the candidates’ websites perform, we’ll use the excellent Blaze.io mobile performance test to capture performance results on real devices.
Mitt Romney
A typical page on Romney’s mobile website is about 687 KB and, as a result, takes about 8.75 seconds to load. While that’s over the 5-second mark, the pages still weigh less than the average size.
Barack Obama
A typical page on Obama’s responsive website is a massive 4.2 MB, resulting in a 25-second loading time.
Despite the fact that only the most patient of visitors would wait 25 seconds for a page to load, such a large payload creates real accessibility problems. Some devices (such as my cousin’s company-issued BlackBerry) won’t even render the page because it’s too large.
While some of this is RIM’s or my cousin’s employer’s doing, it’s a legitimate constraint that we need to be mindful of.
Unfortunately, poor performance is prevalent among the current crop of responsive designs in the wild. Guy Podjarny, chief product architect at Akamai and CTO of Blaze.io, discovered that only 3% of small-screen versions of responsive websites are significantly lighter than their large-screen counterparts. This is all the more reason to focus on performance as a key component of adaptive Web design.
Enhance
We’ve talked about content parity and the importance of providing access to information and functionality regardless of device or configuration. But that doesn’t mean we have to settle on serving a one-size-fits-all experience. Many mobile devices and browsers can do things that desktops cannot. Making the most of these wonderful features will take the mobile experience to the next level.
Mobile Communication
Obama’s designers have implemented one huge enhancement: the ability to make calls on the candidate’s behalf directly from a phone. We tend to forget that mobile phones are, at root, voice-based communication devices and that mobile browsers can initiate a call when the user clicks a tel link. By exploiting this enhancement, Obama is able to mobilize his mobile users into action, which could have a big impact on the campaign.
Obama’s call functionality enables users to make calls on the candidate’s behalf, right from their phones.Besides enabling phone calls to be initiated from the browser, there are many other opportunities for mobile enhancement. Here are just a few ways that both websites could enhance the experience and make the most of the mobile Web.
Simple Form Enhancements
The great thing about form enhancements is that they require barely any effort. One enhancement for many mobile browsers is to specify an HTML5 input type to pull up the appropriate virtual keyboard for the user. While this enhancement isn’t particularly mind-blowing, anything that allows the user to complete their task more quickly certainly helps and could lead to more conversions.
Setting these forms to input type=number would pull up the appropriate virtual keyboard, thus saving the user an extra step.Geolocation
Detecting location is an extremely powerful way to provide users with contextually relevant information. Imagine dynamically displaying blog posts, news and upcoming events relevant to the user’s location. Obama’s website smartly allows users to choose their state; perhaps they could take it further and add geolocation as a way to identify it. Geolocation can also save steps when filling out forms, and it creates opportunities for innovative new features.
Touch Events
The beauty of touchscreens is that they give users a way to interact directly with content and can add a layer of fun to the experience. These websites could leverage touch events to allow users to swipe through photos in a gallery or to thumb through a quick overview of the candidates’ stances on important issues.
Many More
This is just a small sampling of enhancements. Support for a ton of features can be detected, and a ton of use cases emerge from the plethora of devices that access the Web. Ask questions. “Can I offer features that are useful to users on the go?” “How might I use offline storage to improve the experience?” “How can I take advantage of touch events?” Lay a solid foundation, and look for opportunities to enhance.
So, Who Wins?
If there’s one lesson to learn from analyzing these websites and techniques, it’s that this stuff is genuinely hard. A lot goes into making a great mobile Web experience, and I’m personally thrilled that the candidates have taken the important first steps toward making their websites mobile-friendly. Viewing the mobile web as a wonderful journey and not as a destination is absolutely essential. As we step into the deep end of multi-device Web design, we must strive to continually improve our websites and services in order to better serve our users — wherever they may be.
While the design of a candidate’s website might not determine the outcome of the presidential election, it will certainly influence how the world perceives the candidate. And for a Web-savvy voter like myself, a website’s design might just sway my vote. I know who I’m voting for in November!
(al)
- By David Bushell
- January 16th, 2012
- CSS
In this article, we’ll look at Scalable Vector Graphics (SVG), one of the most underused technologies in website development today.
Before diving into an example, let’s consider the state of the Web at present and where it is going. Website design has found new vigor in recent years, with the evolving technique of responsive design. And for good reason: essentially, responsive website design moves us away from the fixed-width pages we’ve grown accustomed to, replacing them with shape-shifting layouts and intelligent reflowing of content. Add to that a thoughtful content strategy and mobile-first approach, and we’re starting to offer an experience that adapts across devices and browsers to suit the user’s context.
When we look at the breadth of Web-enabled devices, responsive design is sure to provide a better user experience. Scrolling horizontally, panning and zooming the viewport have their place in user interface design, but forcing the user to do these things just to navigate a website quickly becomes tedious. Fitting the website to the viewport is about more than just layout: it’s also about resolution. In this article, I’ll demonstrate why SVG is a perfect addition to future-friendly Web development.
Introducing SVG
SVG offers a truly resolution-independent technique for presenting graphics on the Web. SVG is a vector graphics format that uses XML to define basic properties such as paths, shapes, fonts and colors, and more advanced features such as gradients, filters, scripting and animation. Create the file once and use it anywhere, at any scale and resolution.
Consider the use cases: UI and navigation icons, vector-style illustrations, patterns and repeating backgrounds. For all of these, a scalable graphic is the perfect solution from a visual standpoint, and yet fixed-resolution images are still the norm. In the example below, we’ll show you how to expand on a common development technique to take advantage of SVG.
A Case Study: CSS Sprites
We all know about the CSS sprites technique. (If you don’t, then have a quick read through Sven Lennartz’ article. And Louis Lazaris points out its pros and cons.) In the example below, we’ll show how seamlessly SVG replaces normal raster images. If this technique is not for you, you can certainly imagine a whole array of similar situations in which to use SVG.
Vector icons play a big role in user interface design. Pictures express concepts with vivid clarity, whereas their textual counterparts might carry ambiguity. In UI design, where space is scarce, a simple illustrated icon could be greatly welcome.
I’ve mocked up the following example:
I’ll be first to admit that this row of icons won’t win any design awards, but it will suffice for the sake of this article! Let’s look at the HTML:
<div class="actions"> <a class="a-share" href="#">Share</a> <a class="a-print" href="#">Print</a> <a class="a-tag" href="#">Tag</a> <a class="a-delete" href="#">Delete</a> </div>I’ve kept the HTML to a minimum for clarity, but in practice you’d probably want to mark it up with an unordered list. And you’ll almost certainly want to replace those hashes with real URLs (even if JavaScript provides the functionality, having a fallback is nice). Let’s look at the CSS:
.actions { display: block; overflow: auto; } .actions a { background-image: url('sprite.png'); background-repeat: no-repeat; background-color: #ccc; border-radius: 5px; display: block; float: left; color: #444; font-size: 16px; font-weight: bold; line-height: 20px; text-decoration: none; text-shadow: 0 -1px 2px #fff; padding: 10px 20px 10px 40px; margin-right: 5px; } .a-share { background-position: 10px 0; } .a-print { background-position: 10px -40px; } .a-tag { background-position: 10px -80px; } .a-delete { background-position: 10px -120px; }Note the fixed-pixel sizing and the PNG background, which we can see below framed in full Photoshop production glory:
This implementation of a CSS sprite is basic, and at today’s standard, it’s not good enough! How can we enhance this? First, let’s consider the following issues:
- We’ve rasterized the image at a very early stage. Even at full size, icons in which points sit between pixels, such as the one for “Print,” have blurred.
- If we zoom in, the image will blur or pixellate even more; there is no additional data to re-render the image at larger sizes.
- Everything has a fixed size, which is neither good for responsive design nor good for accessibility, because the browser’s default font size is ignored.
As you’ve probably guessed by now, we’ll show you how SVG solves these problems. But first, let’s reiterate each point thoroughly to understand the issues at large.
1. Rasterization
Devices such as modern smartphones have a very high pixel density; some already surpass the 300 pixels-per-inch (PPI) mark that is assumed to be the limit of the human eye’s ability to distinguish fine details. A pixel has no real-world equivalent in size until it sits on a screen of fixed dimension (say, 3.5 inches diagonally) and fixed resolution (say, 640 × 960 pixels). At this scale, text with a font size of 16 pixels would be incredibly small to the eye. For this reason, devices simply cannot translate 1 CSS pixel unit to 1 device pixel; instead, they double up. Thus, a 16-pixel font size actually takes over 32 pixels when rendered.
The same applies to images; but they are already rasterized, so doubling up the pixels has no benefit. In our example, each icon has been rasterized at around 25 × 25 pixels (the whole sprite being 30 × 160), so they cannot take advantage of the double pixel ratio. One solution is to use CSS media queries to detect the pixel ratio. This is already implemented in Webkit- and Gecko-based browsers.
To improve our example, we can add the following CSS declaration:
@media only screen and (-webkit-min-device-pixel-ratio: 2) { .actions a { background-image: url('sprite@2x.png'); background-size: 30px 160px; } }The alternate background image supplied in the code above has been saved at 60 × 320 pixels (i.e. double the original dimensions). The background-size property tells CSS to treat it smaller. Significantly, now the device has the additional data to render a better image (if capable).
This solution isn’t bad, but it doesn’t solve the problems we’ll run into in points 2 and 3 below. It also requires that we maintain multiple files of increasing size: a potential burden on bandwidth and a real hassle. For non-vector images, such as photography in JPG format, we can’t do much more than that.
2. Zooming
At their default size, our rasterized icons look acceptable, at least on low-pixel-density screens. However, should the user zoom in on the Web page, these little UI delights will degrade very quickly.
Zooming is a common action when users find a website too small for comfortable viewing. Or, to put it another way, websites that are designed too small are very common. There is really no “perfect” size, because almost everyone has at least some level of visual impairment, since our eyes inevitably deteriorate with age. Secondly, with the rapid increase in touchscreen devices, pinch-to-zoom has become the standard way to enlarge fixed-sized content designed for larger screens (i.e. much of the Web today).
We should develop websites in a way that minimizes the need for user input — that’s where responsive design comes in (see point 3 below) — but zooming is here to stay. There’s simply no way to provide pre-rasterized images for every level of zoom (in theory, an infinite scale). Scalable graphics are the solution, and we’ll show you how to enhance our example. But first, a related word on fixed sizing.
3. Fixed Sizes
Presenting page elements at fixed sizes forces many users to zoom, but it also disables a very useful browser feature. Users can set their preferred font size (the default in browsers is 16 pixels). By sizing everything in pixels, we override this preference. Sizing elements based on this default is much better, so that, if the text is bigger, everything adjusts to match. This essentially mimics the zooming effect but happens without the user having to manually do it on every visit. Ethan Marcotte has written a great article that explains relative font sizes.
Let’s re-implement our sprite example with a solution to these three issues.
A Scalable Implementation
Here is the HTML again. We don’t need to change anything here.
<div class="actions"> <a class="a-share" href="#">Share</a> <a class="a-print" href="#">Print</a> <a class="a-tag" href="#">Tag</a> <a class="a-delete" href="#">Delete</a> </div>The updated CSS is where the magic happens:
body { font-size: 100%; } .actions { display: block; overflow: auto; } .actions a { font-size: 1em; line-height: 1.25em; padding: 0.625em 1.25em 0.625em 2.5em; margin-right: 0.3125em; border-radius: 0.3125em; background-image: url('sprite.svg'); -webkit-background-size: 1.875em 10em; -o-background-size: 1.875em 10em; -moz-background-size: 1.875em 10em; background-size: 1.875em 10em; /* styles carried over from the original implementation */ background-repeat: no-repeat; background-color: #ccc; color: #444; display: block; float: left; text-decoration: none; text-shadow: 0 -1px 2px #fff; } .actions-em .a-share { background-position: 0.625em 0; } .actions-em .a-print { background-position: 0.625em -2.5em; } .actions-em .a-tag { background-position: 0.625em -5.0em; } .actions-em .a-delete { background-position: 0.625em -7.5em; }In this version, we’ve made the following changes:
- The background-image is now an SVG file.
- All sizes are based on the default of 16 pixels, or 1 em. If the user’s default is larger or smaller, then everything will scale relatively. (If you multiple each em size by 16, you’ll get the number of pixels used in our initial fixed-size example.)
- The background-size is very important. By setting this in em units, we’re telling the browser to scale the sprite relative to everything else. You’ll notice that 1.875 × 10 em multiplied by 16 becomes 30 × 160 — the base size at which we produced the sprite in pixels.
- The background-position of each sprited icon is also based on relative units.
Now that we’re using SVG and relative sizes, we have solved the three big issues highlighted above. A scalable graphic can be rasterized on demand to perfectly suit any device resolution and any zoom level. By using relative sizes, we can continue implementing a responsive design, minimizing as much as possible the need for the user to zoom. We’re also respecting the browser’s default font size, and enabling our design to adapt accordingly.
I actually produced the SVG sprite first and the PNG version from that. (I imported the SVG in Photoshop before exporting it as a PNG — Illustrator’s PNG export had very poor rasterization.) Below is the header in my SVG file. Notice the same 30 × 160 initial size.
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="30px" height="160px" viewBox="0 0 30 160" enable-background="new 0 0 30 160" xml:space="preserve">You can see that the attributes for width and height are set in pixels (width="30px" height="160px") in the opening svg tag (as generated by Adobe Illustrator). This actually causes it to render early in Firefox, before the graphic has scaled to match the em sizes in background-size. Webkit-based browsers seem to scale the SVG perfectly, regardless. I’ve found that editing the SVG file to use em units in these two attributes fixes any rendering issues in Firefox.
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="30em" height="160em" viewBox="0 0 30 160" enable-background="new 0 0 30 160" xml:space="preserve">I don’t know which browser actually implements this scaling correctly, but let it be noted that extra care is needed to ensure cross-browser perfection. Mozilla MDN has an excellent in-depth article, “Scaling of SVG Backgrounds,” which explores more practical examples. For more ideas, see Alex Walker’s article “A Farewell to CSS3 Gradients.”
Here’s a super-close screenshot showing the SVG sprite:
The sprite scales beautifully. (Sadly, the same can’t be said for my tacky text-shadow effect.)
It’s best to experience the joys of scalable graphics and relative sizing firsthand. I’ve uploaded a side-by-side live demo demonstrating a combination of all the techniques mentioned above.
Browser Support
At the start of this article, I said that SVG was underused. I believe that has generally been the case due to poor browser support. But things are different now! Browser support for SVG has blossomed over the last year to the point where implementing it is a viable use of development time.
According to the website When Can I Use?, support for SVG across multiple implementations is as follows (I’ve combined support for both CSS’ background-image and HTML’s img source — the most useful attributes):
- Internet Explorer 9+
- Firefox 4+
- Chrome 4+
- Safari 4+
- Opera 9.5+
Mobile browser support is also pretty much across the board. If a workable fallback exists for older browsers, then SVG is a very viable solution.
For some of the new additions to Web standards, we can implement them safe in the knowledge that old browsers will simply ignore them and that they aren’t even required. We call this “progressive enhancement”: better browsers get a progressively better experience. SVG is slightly different, because for most practical purposes, it simply replaces other images in CSS backgrounds and HTML elements. The image format — be it SVG, PNG, JPG or GIF — is either supported or it isn’t. We can’t simply follow the practice of progressive enhancement here, because an image failing to render is not an acceptable experience.
Browser Sniffing or Feature Detection?
We could make an educated guess and say that we need to worry only about users of Internet Explorer 6 to 8. In this case, the conditional comments technique for IE-only styles enable us to re-apply a second CSS background-image of a supported format such as PNG, instead of the default SVG background.
Browsing sniffing is always a dangerous game. While Internet Explorer tends to be the main offender, we can never assume it is the only one.
The safer and highly recommended option is to detect SVG support and use it only if it’s found. I suggest using Modernizr if you need to detect multiple features. Modernizr applies a class of svg to your root html element if detected (to which you can apply SVG as a background-image). If you’re using SVG as the source of an image element in HTML, then implementation is a little harder. You’ll have to write more JavaScript to find and replace all sources once support has been established.
The problem with these methods is that the browser will download the fallback image before SVG is detected — the only exception being the conditional comments technique for IE. Users will also likely see a flash of re-styled content when the source image changes. This shouldn’t be the case for long; but at least for now, these problems may be enough to hold you off on SVG usage.
File Size
In our sprite example, the raw SVG file was 2445 bytes. The PNG version was only 1064 bytes, and the double-sized PNG for double-pixel ratio devices was 1932 bytes. On first appearance, the vector file loses on all accounts, but for larger images, the raster version more quickly escalates in size.
SVG files are also human-readable due to being in XML format. They generally comprise a very limited range of characters, which means they can be heavily Gzip-compressed when sent over HTTP. This means that the actual download size is many times smaller than the raw file — easily beyond 30%, probably a lot more. Raster image formats such as PNG and JPG are already compressed to their fullest extent.
Performance
Rendering performance is a concern with SVG, especially on mobile devices, whose hardware is limited. Raster images can be rendered pixel for pixel after decompression and de-encoding. Vector graphics need to be rasterized at a specific resolution every time they’re viewed.
SVG has consistently proved slower than Canvas as a platform for animating vector graphics; but our concern here is basic rendering, not manipulation a thousand times per second, and if that is possible, then simple rendering shouldn’t be a concern. The more intensive SVG features are things like clipping masks and filter effects. These are unnecessary for many practical purposes (like our sprite example), but, if required, the best way to check performance is by testing. A lot of Web development is supported in theory, but in practice results are far from perfect.
Alternative Methods
Hopefully you agree that SVG is extremely useful but not always the ideal solution to resolution independence. Ultimately, the trick is to avoid raster images while maintaining the scalability of visual styles. Below are a few more ideas to think about.
CSS3
You’ve probably already started combining CSS3 properties such as linear-gradient, text-shadow and box-shadow to create more complex styles. Web developer Lea Verou curates a CSS3 pattern gallery that shows off the impressive potential of gradients alone.
In his article “Mobile Web in High Resolution,” Brad Birdsall introduces a technique to maintain pixel perfection for high-resolution displays using the pixel-ratio property.
Then there are pure CSS “icons,” which Faruk Ateş rightly points out as being absolute “madness” — certainly so if you’re using CSS to create a logo! But you could argue the benefits of a small handful of very specific techniques, such as CSS triangles, as demoed by Chris Coyier.
Web Fonts
Dingbat Web fonts and look-a-like Unicode glyphs are two interesting alternatives for vector icons, both with accessibility and semantic challenges. Jon Hicks has a write-up of perhaps the best practice for this. SVG seems a more appropriate technique for icons, but both have an immediate visual impact at high resolutions — and we’ll be paying increasing attention to that in coming years.
Looking Forward
As you can see, SVG usage is very much a possibility, and browser support and performance will only improve in future. What’s important to note from this article is that we really should be building websites that are as resolution-independent as possible.
Consider the “one Web” philosophy and the vast range of devices we use to access it — there is no single user experience. The more we can do to stay device-agnostic, the better. Responsive website design addresses many of these needs and certainly provides many benefits. Using vector graphics may not be as apparent, but its little improvements really do make a difference.
With today’s level of support, many users can experience the beauty of crisp scalable graphics… or perhaps that’s the wrong way to think about it. Most users won’t say “Wow! Kudos on the vectors.” To our dismay, they probably wouldn’t even consider them (and certainly wouldn’t recognize the effort required to craft them). And that’s a good thing; each time we improve the user’s experience, we don’t necessarily need to make a song and dance about it. Letting things continue to grind away under-appreciated is OK. It’s the lack of such things that gets recognized and sniffed at. Raise the user’s expectations in visual aesthetics, and they’ll start to notice the websites that do look shoddy. If you don’t do it, others will.
(al)
18 Free jQuery Plugins for Responsive Web DesigningAdvertisementNowadays, one of the most in-demand things in web designing is responsive layouts. Responsive layouts boast some really cool elements which can help designers achieve great results and thus create unique and exclusive websites. These responsive layouts are extremely eye-catching so they can easily attract viewers.
Another great feature of these responsive layouts is that they give the designers the ability of offering particular and optimized screen sizes depending on various devices, such as PCs, cell phones and tablets etc. Because of the fast development in technology, everyone wants a responsive website so that their viewers can easily browse their websites from any device. The popularity of responsive layouts can be attributed to the fact that they offer a lot of amazing features and flexibilities. When a website is browsed from devices like mobile phones and tablets etc the entire website is needed to be optimized – from navigation, photos, sliders, forms and carousels etc.
A plethora of jQuery plugins for responsive web designing are available out there, but not all of them are good, efficient and strong enough to allow full optimization of websites. So in order to help you find some of the best plugins out there, today we have a list of 18 Amazing jQuery Plugins for Responsive Web Designing. These plugins were made especially to help you make a website more responsive, thus making it extremely easy to navigate and enhancing the visitor’s experience.
The plugins in this list have especially been handpicked and both professional and amateur designers will find these plugins useful, so check them out and pick the ones you like the best.
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
10 Responsive Navigation Solutions and TutorialsAugust 29, 2012 No CommentsAs responsive design rapidly increases in popularity, we felt we would take a look at some of the varied solutions and techniques that are being adopted for managing the navigation/menu on smaller screened devices.
Planning and building your menu for mobiles will perhaps be the trickiest aspect of your responsive layout, not just with the coding but also having to decide what will stay and what will have to go to fit everything into the smaller screen. It is a juggling act between both readability and the desire to show as much on the screen as possible.
Hopefully the solutions we have for you below will help get you on your way.
This tutorial, from Smashing Magazine, takes you through the steps for coding your navigation using a little forethought and considering the principles of progressive enhancement from the beginning and applying some responsive practices at the end, allowing your navigation to easily accommodate less-capable browsers and modern browsers in both desktop and mobile environments.
Progressive And Responsive Navigation →Demo →
With this tutorial you will learn how to code a simple and effective responsive navigation menu, with a grid layout, that you will be able to easily modify and reuse in your own projects.
Responsive Navigation Menu →Demo →
TinyNav.js is a tiny jQuery plugin (362 bytes minified and gzipped) that converts <ul> and <ol> navigations to a select dropdowns for small screens. It also automatically selects the current page and adds selected="selected" for that item.
The code for this menu is based on the famous Suckerfish Dropdown menu, restyled to make it responsive. It will work great in all modern desktop browsers without Javascript.
Responsive Drop Down Navigation Menu →Demo →
HorizontalNav is a jQuery plugin that spans a horizontal navigation to fit the full width of it's container. It comes with an option to make it responsive, allowing the navigation to auto-adjust when the window is resized.
This tutorial demonstrates how to develop a complex responsive navigation menu using the "Mobile-First Approach". The aim is to present mobile users with a pseudo-native, touch-conducive and interactive interface that enables them to navigate the website with ease.
Responsive, Mobile-First Navigation Menu →Demo →
SelectNav.js is a JavaScript plugin that lets you convert your website navigation into a <select> drop-down menu. Used together with media queries it helps you to create a space saving, responsive navigation for small screen devices.
Convert a Menu to a Dropdown for Small Screens →Demo →
This tutorial takes a typical desktop menu and shows you how to, using Modernizr, jQuery and media queries, convert it to a small menu button for smaller screens that only appears when pressed, and pressing it again will retract it.
Mobile Menu is a jQuery plugin that turns your site's navigation into a dropdown (<select>) when your browser is at mobile widths. It comes with a handful of options, including the really useful "combine", that allows you to convert multiple navigation lists into a single dropdown.
Further Reading & Resources…
- Responsive Navigation Patterns →
Top and left navigations are typical on large screens, but lack of screen real estate on small screens makes for an interesting challenge. This detailed article, from Brad Frost, takes a look at the various ways of handling navigation for small screen sizes and discusses how mobile navigation must strike a balance between quick access to a site’s information and unobtrusiveness.- Scalable Navigation Patterns in Responsive Web Design →
Here are some of the lessons learned by Michael Mesker, from palantir.net, while working on a recent real-life, large-scale project. Specifically, this post focuses on how they chose to deal with deep navigation in the landscape of a templated environment.- 7 Responsive Navigation Patterns →
You might also like…
10 HTML5-Ready Blank, Bare-Bones and Naked Themes for WordPress →
15 Free WordPress Themes with a Responsive Layout →
25 jQuery Plugins to help with Responsive Layouts →
15 Free HTML5 and CSS Templates →Comments and Reactions
Freetile is a plugin for jQuery that enables the organization of webpage content in an efficient, dynamic and responsive layout. It can be applied to a container element and it will attempt to arrange it's children in a layout that makes optimal use of screen space, by "packing" them in a tight arrangement. Freetile has been the layout engine behind Assemblage and Assemblage Plus for almost two years, and now it becomes available as an independent Open Source project.
Features
Freetile is inspired by similar, existing efforts such as Masonry, vGrid and Wookmark. However, it differs from these solutions in some aspects:
It allows for any size of elements to be packed without using a fixed-size column grid, so you don't have to worry about specifying a column width appropriate to the size of your elements.
The algorithm that evaluates each possible insertion position is easily customizable, allowing for different preferences to be expressed, e.g. a preference to left- or right-alignment of elements, or proximity between certain elements.
Additionally, Freetile has the following key features:
A smart animation routine allows distinguishing between elements that is meaningful to be animated and ones that are not (e.g. elements that have been just added to the arrangement, or those that are not visible). Special classes allow for explicitly limiting animation to select elements.
It has been battle-tested through it's use in the many hundreds sites that make use of the Assemblage and Assemblage Plus templates. Furthermore, it has been used for layout in projects such as Properietary Polymers and Reffffound.
Usage
Default usage:
$('#container').freetile();Enable animation, with an element delay of 30ms:
$('#container').freetile({ animate: true, elementDelay: 30 });Specify a custom element selector:
$('#container').freetile({ selector: '.thumbs' });License
Freetile is licensed under the BSD License.
Get it!
Head over to the Freetile GitHub project page for more info and downloads, or to the Freetile discussion page at the forum, if you have any questions.
Animated Responsive Image GridCycling through a set of images in a responsive grid.
Demo 1 Demo 2 Demo 3Demo 3: Random animations / 100% container width / max. 2 images switch at a time / 2s between switching
- By Reda Lemeden
- August 20th, 2012
- CSS, HTML
With the recent announcement and release of the Retina Macbook Pro, Apple has brought double-density screens to all of the product categories in its current lineup, significantly paving the way for the next wave of display standards. While the fourth-generation iPhone gave us a taste of the “non-Retina” Web in 2010, we had to wait for the third-generation iPad to fully realize how fuzzy and outdated our Web graphics and content images are.
In the confines of Apple’s walled garden, popular native apps get updated with Retina graphics in a timely fashion, with the help of a solid SDK and a well-documented transition process. By contrast, the Web is a gargantuan mass whose very open nature makes the transition to higher-density displays slow and painful. In the absence of industry-wide standards to streamline the process, each Web designer and developer is left to ensure that their users are getting the best experience, regardless of the display they are using.
Before diving into the nitty gritty, let’s briefly cover some basic notions that are key to understanding the challenges and constraints of designing for multiple display densities.
Device Pixels
A device pixel (or physical pixel) is the tiniest physical unit in a display. Each and every pixel sets its own color and brightness as instructed by the operating system, while the imperceptible distance between these tiny dots takes care of tricking the eye into perceiving the full image.
Screen density refers to the number of device pixels on a physical surface. It is often measured in pixels per inch (PPI). Apple has coined the marketing term “Retina” for its double-density displays, claiming that the human eye can no longer distinguish individual pixels on the screen from a “natural” viewing distance.
CSS Pixels
A CSS pixel is an abstract unit used by browsers to precisely and consistently draw content on Web pages. Generically, CSS pixels are referred to as device-independent pixels (DIPs). On standard-density displays, 1 CSS pixel corresponds to 1 device pixel.
<div height="200" width="300"></div>This would use 200 × 300 device pixels to be drawn on screen. On a Retina display, the same div would use 400 × 600 device pixels in order to keep the same physical size, resulting in four times more pixels, as shown in the figure below.
On a Retina display, four times as many device pixels are on the same physical surface.The ratio between device pixels and CSS pixels can be obtained using the following media query and its vendor-specific equivalents:
device-pixel-ratio, -o-device-pixel-ratio, -moz-device-pixel-ratio, -Webkit-device-pixel-ratio { … }Or you can use their future-proof siblings:
device-pixel-ratio, -o-min-device-pixel-ratio, min--moz-device-pixel-ratio, -Webkit-min-device-pixel-ratio { … }In Javascript, window.devicePixelRatio can be used to obtain the same ratio, although browser support is still relatively limited. Both of these techniques will be discussed in depth later in this article.
Bitmap Pixels
A bitmap pixel is the smallest unit of data in a raster image (PNG, JPG, GIF, etc). Each pixel contains information on how it is to be displayed, including its position in the image’s coordinate system and its color. Some image formats can store additional per-pixel data, such as opacity (which is the alpha channel).
Beside its raster resolution, an image on the Web has an abstract size, defined in CSS pixels. The browser squeezes or stretches the image based on its CSS height or width during the rendering process.
When a raster image is displayed at full size on a standard-density display, 1 bitmap pixel corresponds to 1 device pixel, resulting in a full-fidelity representation. Because a bitmap pixel can’t be further divided, it gets multiplied by four on Retina displays to preserve the same physical size of the image, losing detail along the way.
Each bitmap pixel gets multiplied by four to fill the same physical surface on a Retina display.The Tool Chest
Even though we are still in the early stages of this major shift, several approaches to optimizing Web graphics for Retina displays have sprung up, and more are popping up as we speak. Each method makes some degree of compromise between performance, ease of implementation and cross-browser support. As such, choosing a tool should be done case by case, taking into account both quantitative and qualitative factors.
HTML And CSS Sizing
The most straightforward way to serve Retina-ready Web graphics is to halve the size of your raster assets using CSS or HTML, either manually or programatically. For instance, to serve a 200 × 300-pixel image (remember, those are CSS pixels), you would upload an image with a bitmap resolution of 400 × 600 pixels to your server, then shrink it by exactly 50% using CSS properties or HTML attributes. On a standard-resolution display, the result would be an image rendered with four times fewer pixels than its full bitmap size — a process commonly referred to as downsampling.
A CSS-sized image gets its dimensions halved during the rendering process.Because the same image would use four times as many physical pixels on a Retina screen, every physical pixel ends up matching exactly 1 bitmap pixel, allowing the image to render at full fidelity once again.
CSS-sized images regain their full-detail glory on Retina displays.There are several ways to achieve this:
Using HTML
The easiest way to apply CSS sizing would be by using the width and height attributes of the img tag:
<img src="example@2x.png" width="200" height="300" />Please note that, even though specifying height is optional, it allows the browser to reserve the space required for the image before loading it. This prevents the page layout from changing as the image loads.
What to use it for? Single-page websites with few content images.
Using Javascript
The same result can also be obtained using Javascript by targeting all Retina-ready content images in the document and halving their sizes. With the help of jQuery, this would look like this:
$(window).load(function() { var images = $('img'); images.each(function(i) { $(this).width($(this).width() / 2); }); });What to use it for? Websites with few content images.
Using CSS (SCSS)
If you want to keep all of the presentation code in your CSS files, then the most common technique involves setting the image as the background of another HTML element, usually a div, then specifying its background-size property. You could either set explicit width and height values for the background image or use the contain value if the dimensions of the HTML element are already specified. It is worth noting that the background-size property is not supported in IE 7 or 8.
.image { background-image: url(example@2x.png); background-size: 200px 300px; /* Alternatively background-size: contain; */ height: 300px; width: 200px; }You could also target a :before or :after pseudo-element instead:
.image-container:before { background-image: url(example@2x.png); background-size: 200px 300px; content:''; display: block; height: 300px; width: 200px; }This technique works just as well with CSS sprites, as long as the background-position is specified relatively to the CSS size (200 × 300 pixels in this case):
.icon { background-image: url(example@2x.png); background-size: 200px 300px; height: 25px; width: 25px; &.trash { background-position: 25px 0; } &.edit { background-position: 25px 25px; } }When using image sprites, consider any OS-specific limitations.
What to use it for? Websites that make limited use of the background-image property, such as those that rely on a single-image sprite.
HTML and CSS Sizing: Pros
- Easy to implement
- Cross-browser compatible
HTML and CSS Sizing: Cons
- Non-Retina devices have to download larger assets.
- Downsampled images might lose some of their sharpness on standard-density screens, depending on the algorithm used.
- The background-size property is not supported in IE 7 or 8.
Querying Pixel Density
Perhaps the most popular way to serve Retina-ready graphics on the Web is by querying the device for its pixel density and then serving assets accordingly. This can be done using either CSS or JavaScript.
Using CSS Media Queries
As of this writing, almost every major browser vendor has implemented a prefixed variant of device-pixel-ratio and its two siblings, min-device-pixel-ratio and max-device-pixel-ratio. These media queries can be used in conjunction with the background-image property to serve Retina-ready assets to high-density devices:
.icon { background-image: url(example.png); background-size: 200px 300px; height: 300px; width: 200px; } @media only screen and (-Webkit-min-device-pixel-ratio: 1.5), only screen and (-moz-min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3/2), only screen and (min-device-pixel-ratio: 1.5) { .icon { background-image: url(example@2x.png); } }By using a ratio of 1.5 instead of 2, you can target other non-Apple devices with the same query.
What to use it for? Any website or app that uses the background-image property for graphic assets. Not suitable for content images.
CSS Querying: Pros
- Devices download only those assets that target them.
- Cross-browser compatible
- Pixel-precise control
CSS Querying: Cons
- Tedious to implement, especially on large websites.
- Displaying content images as backgrounds of other HTML elements is semantically incorrect.
Using Javascript
The pixel density of the screen can be queried in Javascript using window.devicePixelRatio, which reports the same value as its CSS counterpart. Once a higher-density screen is identified, you can replace every inline image with its Retina counterpart:
$(document).ready(function(){ if (window.devicePixelRatio > 1) { var lowresImages = $('img'); images.each(function(i) { var lowres = $(this).attr('src'); var highres = lowres.replace(".", "@2x."); $(this).attr('src', highres); }); } });Retina.js is a Javascript plugin that implements roughly the same technique as described above, with some additional features, such as skipping external images and skipping internal images with no @2x counterparts.
Lastly, it is worth noting that devicePixelRatio is not entirely cross-browser compatible.
What to use it for? Any website with content images, such as landing pages and blogs.
Javascript Querying: Pros
- Easy to implement
- Non-Retina devices do not download large assets.
- Pixel-precise control
Javascript Querying: Cons
- Retina devices have to download both standard- and high-resolution images.
- The image-swapping effect is visible on Retina devices.
- Does not work on some popular browsers (such as IE and Firefox).
Scalable Vector Graphics
Regardless of the method used, raster images remain inherently constrained by their bitmap resolution; they were never meant to be infinitely scalable. This is where vector graphics have the advantage, being a future-proof way to “Retinize” your Web graphics.
As of this writing, the vector XML-based SVG format has cross-browser support of more than 70% and can be used in several ways on the Web. SVG images can be easily created in and exported from a number of vector-graphic editors, such as Adobe Illustrator and free alternatives such as Inkscape.
As far as Web design goes, the most straightforward way to use SVG assets is with the HTML img tag or with the CSS background-image and content:url() properties.
<img src="example.svg" width="200" height="300" />In the example above, a single SVG image can be used as a universal asset, scaling infinitely up or down as required. This not only saves precious bandwidth (most SVG files tend to be smaller in size than standard-resolution PNGs), but also makes your graphic assets much easier to maintain. The same would apply if used in CSS:
/* Using background-image */ .image { background-image: url(example.svg); background-size: 200px 300px; height: 200px; width: 300px; } /* Using content:url() */ .image-container:before { content: url(example.svg); /* width and height do not work with content:url() */ }If you have to support IE 7 or 8 or Android 2.x, then you will need a fallback solution that swaps SVG images with their PNG counterparts. This can be easily done with Modernizr:
.image { background-image: url(example.png); background-size: 200px 300px; } .svg { .image { background-image: url(example.svg); } }For best cross-browser results and to avoid some rasterization headaches in Firefox and Opera, make each SVG image at least the size of its parent HTML element.
In HTML, you can implement a similar fallback solution by adding a custom data attribute to your img tag:
<img src="example.svg" data-png-fallback="example.png" />Then, handle the rest with jQuery and Modernizr:
$(document).ready(function(){ if(!Modernizr.svg) { var images = $('img[data-png-fallback]'); images.each(function(i) { $(this).attr('src', $(this).data('png-fallback')); }); } });This HTML and JavaScript route, however, would not prevent browsers with no SVG support from downloading the SVG assets.
What to use it for? Any website or app. Suitable for icons, logos and simple vector illustrations.
SVG: Pros
- One universal asset for all devices
- Easy to maintain
- Future-proof: infinitely scalable vector graphics
SVG: Cons
- No pixel precision due to anti-aliasing
- Unsuitable for complex graphics due to large file sizes
- No native support in IE 7 and 8 or early Android versions
Icon Fonts
Popularized by Twitter’s Bootstrap, the technique of using @font-face with icon-based fonts has garnered a following of its own as a resolution-independent alternative to bitmap icons. The technique consists of using a custom Web font that replaces the alphabet with monochrome glyphs, which can be styled using CSS, just like any other text on the website.
There is no shortage of comprehensive, good-quality icon fonts that would cover most of your needs. That being said, importing a large font in half a dozen formats only to use a small subset of the icons is a bad idea. Consider building your own custom font with free tools such as Fontello, Font Builder or even Inkscape.
The most common way to use icon fonts on websites is by assigning an .icon or .glyph class to a particular HTML element — most often a <span> or an <i> — and then using the letter corresponding to the desired icon as its content:
<span class="icon">a</span>After having imported your custom font using @font-face, you would declare it:
.icon { font-family: 'My Icon Font'; }Another technique consists of using the :before pseudo-element and the content property, with a unique class for each icon:
<span class="glyph-heart"></span>[class^="glyph-"]:before { font-family: 'My Icon Font'; } .glyph-heart:before { content: 'h'; }What to use it for? Websites or apps with a high number of icons, and for rapid prototyping.
Icon Fonts: Pros
- Future-proof: infinitely scalable glyphs
- Cross-browser compatible
- More flexible than graphic assets: can be used in placeholder text and other form elements, etc.
Icon Fonts: Cons
- No pixel precision due to subpixel anti-aliasing
- Hard to maintain: changing a single icon requires regenerating the whole font.
- Relies on semantically incorrect markup (unless used with :before or :after pseudo-elements).
Favicons
Favicons are getting their fair share of attention, being increasingly used outside of browser chrome as an iconic representation of our websites and apps. To make your favicons Retina-ready, export an .ico file in both 16- and 32-pixel versions. If you are using a Mac, you can create your own .ico files with Apple’s Icon Composer (included in the Graphic Tools in Xcode) or with Icon Slate, a paid third-party application.
A Glimpse Of The Future
Besides the techniques covered above, several other efforts are being made independently by organizations and individuals alike, not the least of which is Apple’s own -Webkit-image-set, introduced last spring. This proposal allows for multiple variants of the same image to be provided in one CSS declaration:
.image { background-image: -Webkit-image-set(url(example.png) 1x, url(example@2x.png) 2x); background-size: 200px 300px; }This technique does not, however, cover images inside img tags, and it is Webkit-only as of this writing.
Another notable effort is Scott Jehl’s Picturefill, an HTML and Javascript solution that makes heavy use of data attributes and media queries to serve different images in different media contexts.
<div data-picture> <div data-src="example.png"></div> <div data-src="example@2x.png" data-media="(min-device-pixel-ratio: 1.5)"></div> <!-- Fallback content for non-JS browsers --> <noscript> <img src="example.png" > </noscript> </div>Even if the markup puts you off, it is a good cross-browser solution to consider if you are dealing with few content images.
Last but not least, the ambitious picture element proposal aims to bring responsive images to the Web using a markup-only approach for multiple image sources, coupled with media queries that route each device to the right asset.
Closing Words
Like other major shifts the Web is currently undergoing, attaining resolution independence will be a long journey. As Web designers and developers, either we can sit down and wait passively for a convention to be standardized, or we can immediately start offering a pleasurable viewing experience to our users. Let’s get to work.
(al)
Foundation by ZURB is the most advanced responsive front-end framework in the world.
We have been using a mobile-first approach to responsive web design for quite a while now: This means using CSS media queries to create responsive layouts and JavaScript to deal with the more complex matter of responsive images. We also frequently noticed cases where we needed JavaScript functions to be called if the window is wider than a given width, because some things can not be solved with CSS. Being the perfectionists that we are, we wanted this to work when resizing the browser and also to be able to revert the change when the window becomes smaller again. One example is to move certain elements into a sidebar on wider windows or move the navigation from the footer into the header. Another example is asynchronously loading some JavaScript files in wide windows. relocate So we came up with this function call: var sidebarElements = document.getElementsByClassName("sidebarEl"); var sidebar = document.getElementById("sidebar"); // here is the function call: relocate(600, sidebarElements, sidebar); Now the sidebarElements can be mixed into the regular layout of the page on mobile devices and they are automatically relocated into the sidebar on screens wider than 600 pixels. demo Check out the demo to see it in action. HTML elements can be moved around on the page depending on the width of the screen.minwidth The relocate function is a special case of a function which is called when the browser window is or becomes wider than a minimum width. This is implemented in the minwidth function. minwidth takes at least two parameters, the first one is the width, the second on is the function which is called when the window becomes wider than the given width or if it initially is wider than that. The third parameter is the function that is called when the screen becomes smaller than this width again, you can use this to undo the changes from the first function. The implementation of relocate looks something like this: function relocate(width, elements, targetElement) { minwidth(width, moveElementsToTarget, moveElementsBack); } The minwidth function can be used in cases where a script needs to be loaded only on wide screens. Loading a script with the fantastic $script.js, which we use to asynchronously load more scripts, looks like this: function loadFacebook() { $script("http//connect.facebook.net/en_US/all.js#xfbml=1"); }; minwidth(600, loadFacebook); In the rare case, that you need to enhance the mobile experience, but not the desktop version you can pass in a fourth parameter and it will cause the the function to work in desktop-first fashion: It calls the second function if the window is initially smaller than the given width, but nothing if the screen is wider than that: minwidth(480, null, enhanceMobile, true); The source code for the minwidth and the relocate functions can be found on github. Notes We decided to implement this without using jQuery or any other library, because we wanted to load those asynchronously later on, but at the same time wanted to relocate the elements in a synchronous script at the head of the page to avoid elements visibly jumping around. Because getElementsByClassName is not available in some browsers we support, we came up with our own little polyfill which combines the best approaches to this problem. If elements were only retrieved using getElementById, this would not be necessary. It's small: minified it's less than a kilobyte, gzipped even less. Tweet
Mobile web design gallery with resources about mobile web development and the latest mobile web news.
Automatic Conditional Retina ImagesOne line of JavaScript and a few mod_rewrite rules and we have no fuss Automatic Conditional Retina Images. No DOM crawling. No redundant requests. No server-side scripts. No cookies? No problem, they just get the original image. The only change you might need to make to your workflow is explicitly defining image width and height in HTML (you should really be doing this already) and background-size in your CSS. And of course, creating retina images. If your original image is named circle.png the retina version should be circle@2x.png If you forget a retina image the original image will be served, even on retina devices. Check the caveats.
The JavaScript
if((window.devicePixelRatio===undefined?1:window.devicePixelRatio)>1) document.cookie='HTTP_IS_RETINA=1;path=/';I think this must be placed inline in the head (not included in an external JavaScript file) and before any external CSS or images in order for the cookie to be set before any images are requested but I'd be happy to be wrong. Add it to a template or at the very least use some sort of server-side include in case you need to update this in the future.
The Mod Rewrite
Add this to an .htaccess file in the directory where you keep your images:
<IfModule mod_rewrite.c> Options -MultiViews RewriteEngine on RewriteCond %{HTTP_COOKIE} HTTP_IS_RETINA [NC] RewriteCond %{REQUEST_FILENAME} !@2x RewriteRule ^(.*)\.(gif|jpg|png)$ $1@2x.$2 # if @2x isn't available fulfill the original request RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)@2x\.(gif|jpg|png)$ $1.$2 </IfModule>In HTML
Be sure to specify width and height of the original (non-retina) image. eg.
<img src="circle.png" width="240" height="240" alt="">Or in CSS
Be sure to specify the background-size property using the width and height of the original (non-retina) image. eg.
background-image:url(circle.png); background-size:240px 240px;Prior Art & Caveats Pointed Out Post Posting
Lots of reports of future browsers preloading images before the cookie can be set. I'm not seeing this on the iPad 3, 4th generation iPod touch, or the retina MacBook Pro, which are my current primary concerns but I respect they may not be yours. Apparently IE9 does not block while it processes inline JavaScript (currently moot since it doesn't run on a retina device). Firefox 14.0.1 on a retina MacBook Pro does not load the @2x images because it does not support window.devicePixelRatio and checking min-resolution with window.matchMedia().matches seems wonky.
Shaun Inman might have been crazy mid-2012.
Creating a Mobile Web Application with Meta TagsAdvancing trends for the mobile web are slowly blurring the line between Internet websites and native applications. Lately there have been many updates to mobile operating systems and web browsers with more capable rendering engines. This means we can work openly with webkit CSS3 effects and even many bits of jQuery code.
However a lot of the customization for mobile web apps is done in the document header. Meta tags are slowly being recognized as the best way to push data out to many different mobile platforms. iOS has Mobile Safari and Android users are rendering on the Webkit or Gecko engines. But ideologies are simply not enough – and the fastest way to learn is by trying out some new code.
What Makes a Mobile Webapp?
If you write a typical HTML4/XHTML/HTML5 webpage it will render pretty well on mostly all the modern cell phones. However it will be displayed as a website where users can generally pinch and zoom into areas. This is perfectly acceptable for most instances, except for responsive websites and mobile web applications.
Additionally you need to offer your visitors a quick way to access your webapp. Mobile Safari is always an option – but what about launching from the homescreen? All of the App Store applications will launch from their home icon, and this is also possible inside a mobile web app. Although we can run through a few of the required tags first.
Device Viewport
Whether your layout is built flexible or hard-coded to a set width(ex: 320px for iPhone) does not ultimately matter. To generate a webapp view we need the meta viewport tag added in-between your website’s <head></head> section. This can setup any number of important options for how our webpage is rendered on a mobile screen.
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">This example above should be perfect for any typical boilerplate application. It will set all the default views to 1.0 scale and the user cannot re-size any part of the site, although they can still scroll vertical and horizontal. Within the content attribute are many other values you can toy around with. The Mozilla dev team has written an article on the viewport tag with full explanations and a couple of examples.
If anything, it’s super important to set your width value the same as device-width. This will force the layout to adjust as your visitors may switch from portrait into landscape view. It’s also necessary if you’re running JavaScript which parses for the current window size.
Mobile Safari Tags
The Apple online documentation section has a piece for Safari mobile apps. This includes a reference to each of their proprietary meta tags and how they should be used on your website. But in truth there are really only 2 more aside from the viewport.
<meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">By setting the web-app-capable meta tag Safari can detect that your website is able to run as an application. So when users go to save your website onto their device it will launch without the URL bar or any other Safari trimmings.
If you are familiar with iOS apps you’ll also recognize the top bar section of the device screen. By default this is setup with a white/gray gradient, but you may also choose between black and black-translucent. Neither of these values should affect your webapp in any major way other than the color scheme for the top toolbar.
iOS App Icons
There are two important pieces you can mimic in relation to a native iOS app. The first is a home screen icon, and the second is a featured launch png image. The code is very sensitive and you’ll need to use these exact values for rel and sizes. Although feel free to rename your image files anything(or even .jpg should work fine).
<link rel="apple-touch-icon" sizes="72x72" href="/apple-touch-icon-72x72.png"> <link rel="apple-touch-icon" sizes="114x114" href="/apple-touch-icon-114x114.png"> <link rel="apple-touch-icon" href="/apple-touch-icon-57x57.png"> <link rel="apple-touch-startup-image" href="/splash-startup.png">Although it isn’t stated outright the sizes variable only accepts these two values. 114px is for iPhone retina and 7px for iPad displays. As far as I know there is no new size value for iPad retina displays.
The startup splash image should be sized exactly 320×460 pixels. For some reason the Apple guidelines do not offer a retina version of this splash screen. I have tried setting sizes=”640×920″ and the whole splash image feature just stops working! So this attribute appears to be very touchy, and I’m hoping Apple will touch up some of these features soon.
Quirks with Internet Explorer
Internet Explorer has surprisingly been getting a lot better with web standards. The developers at Microsoft have been adapting with new Internet technologies both on desktop and with their mobile phones. Meta tags for setting the rendering engine are common – using the MS http-equiv value for example.
But a recent tag X-UA-Compatible had caught my attention. It’s useful for setting browser engines back to keep your current code backwards-compatible. This is usually the case the Internet Explorer, although in some cases you can reset an older IE to the latest version. That would be using this code below:
<meta http-equiv="X-UA-Compatible" content="IE=edge">There have been some validation issues when checking your code against an HTML/XHTML parser. I believe this tag is setup through Microsoft and has been slowly leaked throughout the mobile web. This is really a personal choice to work with or not. If you’d like to learn more check this MSDN Blog post regarding X-UA-Compat and pick up on the details of the syntax.
Other Important Tags
There are some other meta tags you do not need to include, but certainly wouldn’t hurt anything if you did. Unfortunately there are just so many standards it would be impossible to list all the options. But you may consider working with just a couple more tags.
<meta name="HandheldFriendly" content="true">HandheldFriendly was originally created by Palm and BlackBerry devices for managing mobile websites. It is still somewhat useful although not exactly the highest market share among mobile devices. I’ve found a small blog post discussing this meta tag and the viewport content.
There is also mention of another tag called MobileOptimized. This was originally designed for mobile Internet Explorer and will be carried over for WMP. It’s also known as the meta layout tag from the Microsoft developer docs.
<meta name="MobileOptimized" content="width">Note that “width” should be changed to whatever your natural display should be on Windows Mobile Phone. This can be tricky to setup, and it may be worthwhile to ignore this tag altogether. The suggested default is 240 pixels for tablet PC and mobile IE devices. But there are definitely other tags related to IE which serve a greater purpose.
Conclusion
I hope these tricky meta tags can be of use to any interested mobile web developers. iPhones and Android devices have changed the way we access the Internet and modern-era websites. And now webmasters are forced to adapt their layouts to suit a changing marketplace.
This is not an exhaustive list of mobile-based meta tags. But it does cover all of the big boys you’ll need in a typical webapp. This should get you started on the right path for mobile web dev, and you can even setup a blank HTML5 template with many of these meta tags initialized. If you have similar ideas or questions on the code please share with us in the post discussion area.
You might also like…
Working with Property Lists in Xcode 4.2 →
Getting Started Building iPhone Apps in Xcode 4.2 →
Creating Pixel-Perfect UI for iPhone Applications →
Tips for Wireframing a Usable Mobile App Interface →
Ultimate Collection of Printable Mobile Sketching Templates →
Showcase of Beautiful and Unique iPhone Apps →
30 Brilliant iOS Applications for Freelance Designers and Developers →Comments and Reactions
Response is a jQuery plugin that helps optimize cross-device performance by enabling progressive enhancement of content via HTML5 data.
TinyNav.js is a tiny jQuery plugin that automatically converts UL and OL navigation to a tiny select box on small screen.
A jQuery plugin to help ease the transition to responsive images
Hammer.js A javascript library for multi-touch gestures View Hammer.js on GitHub Download source It's just 2kb (minified) You can touch me... Bust a few moves... Why use Hammer.js? easy implementation of touch events in your website lightweight with only 2kb (minified and gzip), easy to dig into focused javascript library, only for multi-touch gestures completely standalone, and a jQuery plugin is available Gesture supported by Hammer.js Tap Double Tap Swipe Hold Transform Drag View Hammer.js on GitHub Download source It's just 2kb (minified)