Accessible Websites For Everyone

17 May 2013

As digital workers we live in an extremely exciting time. New innovations are being developed every day, and they can be used to create incredible experiences for our users. There are endless amounts of fantastic open source projects on Github, and as many tutorials as you can walk through on sites like Nettuts and Smashing Magazine. Easy implementation of previously complex techniques have given rise to an abundance of sites using parallax, draggable elements, CSS animations, the list goes on.

With all of these possibilities, it can be tempting to throw them all into our web pages in the name of creating 'cutting edge' experiences. However, many developers are getting caught up in these temptations and losing sight of the real goal of our websites and webapps: to distribute our content to as many users as we can. As fancy as we can make our experiences, in the end we are still information disseminators and it is important to put on the blinders and make this a priority.

Recently, eyewear company Oakley released a site that did too good of a job at showcasing this lack of focus. On his WTF Mobile project, Brad Frost posted the Oakley site and the shocking 80mb download it required before it rendered. Phil Hawksworth was brave enough to attempt to access the site and wrote a follow up post on his blog that went into greater detail about the "experience".

<blockquote>
  <ul>
    <li>85.4MB page weight</li>
    <li>471 HTTP requests</li>
    <li>2 minutes 45 seconds until loading screen replaced with content</li>
    <li>4 minutes 10 seconds minute onLoad event</li>
  </ul>
</blockquote>

He was also nice enough to save us all from the same fate and posted his viewing to Vimeo, which unsurprisingly is 60mb smaller than the website itself.

This is an almost comically exaggerated example, but there are many websites that are attempting similar effects and doing a huge disservice to their users.

Scott Jehl from Filament Group has a great talk that goes into great detail about this, and his experiences in rural Asia drive home the impact that oversights like this can have. Two minute downloads for a single website is bad enough on broadband or fiber, but the problems become even more obvious when thinking about the accessibility not just by us few that are lucky enough to have fast computers and connections, but those that don't have the means to have more than a dial up type connection.

After spending the past eight days in India, I have been able to see many of these problems first hand. The company I work for has a team in Pune, and the time difference requires us to visit each other once in awhile to get through big projects face to face. Working in one of the upcoming IT hubs in a country brimming with young technologists and programmers, the problems with the way many websites are developed come into focus more than ever.

<img src="http://www.jasondemeuse.com/system/images/articles/accessibility/workstation.png"/>
Workstation In Pune

Most of my coworkers here are single, and they are all in their mid to early twenties, speak great English, and have well paying jobs that affords them disposable income. Not only that, but they know computers better than most of the people I know in the west and they all own smartphones. Unfortunately, the electricity and internet here is spotty at best. There are frequent rolling blackouts that cause the building to go dark and the internet to reset for a few minutes at a time, and the ISPs are unreliable enough that constant router and modem resets are a daily ritual. Keep in mind, this is in a brand new technology park housing beautiful office buildings. Many of the situations in Scott's talk appear here, and websites with a much smaller load than Oakley's can still be too large to be rendered properly. There are over 3.1 million people in Pune, and this is a **small** city compared to others like Mumbai, Delhi, and Bangalore. That sounds to me like an Internet marketer's dream, and certainly not a market that you would want to overlook.

Brand new office building going up across the street

Considering the purpose of adding these features is to bring new users to see your content, all of these bloating features start to seem extremely unproductive. In an era of fast advancement of the web, this is an area where we have taken a huge step backward. There are a few main problems showing up consistently in today's websites.

<h1>HTTP Requests</h1>

One of the most overlooked and potentially damaging issues with website reliability is the amount of HTTP requests the website needs to load. Every single asset including individual images, external stylesheets, and JavaScript files require a separate request from your computer to the server before the entire website will render.

A bare minimum website done for a client may look contain something like the following.

<ul>
  <li>5 HTML files
  <li>Stylesheet</li>
  <li>Reset stylesheet</li>
  <li>Main JavaScript file</li>
  <li>JavaScript library (jQuery, MooTools, Prototype, etc.)</li>
  <li>3 images on the front page</li>
  <li>Background image</li>
  <li>2 web fonts</li>
  <li>20 images in gallery</li>
</ul>

That's thirty five http requests on a simple website, and there are few times a client would ask for less than this. Now keep in mind that modern browsers can run about eight concurrent requests at a time and that they each represent a point of failure for a user trying to access your content. The statistics kept at the http archive showcase the problems with many modern websites.

<img src="http://www.jasondemeuse.com/system/images/articles/accessibility/totaltransfer.png" alt="total transfer stats">

In May, the average website had to make 91 requests in order to load fully. That's a huge burden for a slow connection, and an avoidable option when there are other sites that will reliably load.

<h3>What You Can Do</h3>

All of the sample files in our bare minimum website can be optimized to cut down on requests.

<h4>Sprites</h4>

With web designers leaning towards using icons along with titles in their menus, adding tens or hundreds of icon images can increase requests quickly. Using sprites is an easy way to cut these down to one request for a single image.

In the age of table layouts and Photoshop to HTML conversions, it was common to slice up a website design and then stick the pieces back together in the HTML. Though loading them seperately (and visually seeing them load individually when the page is loading), made the page appear to be quicker, it was also creating far more requests and increasing the amount work that had to be done before the content was fully loaded. Because we have the ability to display only certain parts of an image using positioning, we can simply place all of our small icons and image in one PNG and only show the area that makes sense.

For example, if we wanted to show an icon before the titles in our navigation using the pseudo :before element, we could do the following.

<pre>
  &lt;!-- Create a simple unordered list to house our navigation --&gt;
    &lt;ul&gt;
      &lt;li id = "profile"&gt;Profile &lt;/li&gt;
      &lt;li id = "print"&gt;Print &lt;/li&gt;
      &lt;li id = "calendar"&gt;Calendar &lt;/li&gt;
      &lt;li id = "bookmark"&gt;Bookmark &lt;/li&gt;
      &lt;li id = "findus"&gt;Find Us  &lt;/li&gt;
      &lt;li id = "trash"&gt;Trash &lt;/li&gt;
    &lt;/ul&gt;
</pre>

Normally, we would add the images seperately.

<pre>
  #profile:before {
    background:url(profile_icon.png);
  }
</pre>

Instead, let's combine the icons into a sprite image.

<img src="http://www.jasondemeuse.com/system/images/articles/accessibility/iconsprite.png" alt="icons condensed into sprite image">

<p>We know that each icon is 50px by 50px, and we know the location of each of them.</p>

<p>The profile icon is 0px from the top and 0px from the left, so we'll show it as such.</p>

<pre>
  #profile:before {
    background:url(iconsprite.png) 0px 0px;
  }
</pre>


<p>We can do the same with all of the other icons as well, then style them so the images don't run behind the titles.  You must also be sure to include the width and height dimensions to specify how much of the sprite image to show.</p>

<pre>
  // Icons

  #profile:before {
    background:url(iconsprite.png) 0px 0px;
  }

  #print:before {
    background:url(iconsprite.png) 0px -116px;
  }

  #calendar:before {
    background:url(iconsprite.png) 0px -174px;
  }

  #bookmark:before {
    background:url(iconsprite.png) 0px -232px;
  }

  #findus:before {
    background:url(iconsprite.png) 0px -290px;
  }

  #trash:before {
    background:url(iconsprite.png) 0px -50px;
  }

  // Style each to include dimensions

  li:before {
    content:"";   // Blank content as we're using background images
    width:50px;   // Icon is 50px wide
    height:50px;  // Icon is 50px tall
    float:left;
    margin: 0 10px 0 0;
  }
</pre>

<a href="https://github.com/jasondemeuse/accessibility-sample-code/tree/master/sprite">View On Github</a> | <a href="http://www.designkindle.com/2011/10/07/build-icons/">Icon Credit</a>

<p>If you don't want to deal with making these sprite images yourself, there are several quality tools that will do most of the work for you.</p>

<p><a href="http://csssprites.com/">CSS Sprites</a> is a service that allows you to upload your individual images and icons, and it will generate a complete sprite sheet for you along with the image positions that you can copy and paste into your style.</p>

<img src="http://www.jasondemeuse.com/system/images/articles/accessibility/csssprite1.png" alt="css sprite screen cap 1">

<img src="http://www.jasondemeuse.com/system/images/articles/accessibility/csssprite2.png" alt="css sprite screen cap 1">

<p><a href="http://spriteme.org/">SpriteMe</a> is a bookmarklet that will make a sprite image out of the images it deems to be spritable on your site.  It's especially nice because it finds background images and groups everything for you, and generates a sheet similar to the CSS Sprites image without as much work on the user's end.</p>

<img src="http://www.jasondemeuse.com/system/images/articles/accessibility/spriteme.png" alt="sprite me screen cap">


<h4>Combine and Concatenate</h4>

<p>Combining your webfonts into one link means only one request to retrieve them.  Google does this for you.</p>

Instead of copy and pasting them seperately...

<pre>
  &lt;link href='http://fonts.googleapis.com/css?family=Domine' rel='stylesheet' type='text/css'&gt;
  &lt;link href='http://fonts.googleapis.com/css?family=Fjalla+One' rel='stylesheet' type='text/css'&gt;
</pre>

<p>Combine them into one link.</p>

<pre>&lt;link href='http://fonts.googleapis.com/css?family=Domine|Fjalla+One' rel='stylesheet' type='text/css'&gt;</pre>

<p>You can do the same thing with your CSS and JavaScript files, by concatenating them into one file each.  The as you organize and modularize your stylesheets, this increase in extra requests can start to add up.  Luckily, this is done easily while compressing stylesheets, which we'll dig into later.</p>



<h1>Asset Size</h1>

Taking another look at the total transfer chart from earlier, there is another obvious problem. The asset size of an average website is 1.4mb, which is bulky especially when considering those who buy mobile data by the megabyte. Constantly testing on amazing connections can make us take things like download speed for granted, but viewing any of these "average" sites on a mobile connection in a rural area will show you immediately why this trend is a problem. Like the issue of http requests, this is a common problem that already has many possible solutions.

<h3>Custom Builds</h3>

One of the complaints against many of the new JavaScript libraries like jQuery is that they are too bulky to be used efficiently. There is certainly a lot of functionality packaged inside these libraries, much of which will not be used depending on the site's functionality. Luckily, many of these libraries offer custom builds of their libraries so you can keep your users from requesting and downloading unnecessary code.

<p>To get a custom jQuery build, you only have to run a few simple commands.

First you'll need to get the newest copy of jQuery going, so clone a copy of the main jQuery repo by using the following git command.

<pre>git clone git://github.com/jquery/jquery.git</pre>

Next install grunt.js by running

<pre>npm install -g grunt-cli</pre>

Now enter the jQuery directory using

<pre>cd jquery</pre>

and make sure all of your Node dependencies are installed.

<pre>npm install</pre>

If you use <pre>grunt</pre> right now, you'll get a JSLinted and minified copy of jQuery.  You still want to exclude modules that you don't plan on using, so run

<pre>git pull; git checkout $(git describe --abbrev=0 --tags)</pre>

to checkout the latest stable version of jQuery.  Now you can use the grunt:custom command to exclude dependencies.  For instance, if I know I'm not going to need the "effects" module, which contains the .animate() shorthands like .fadeIn() and .slideDown().  I can use the following grunt command to remove it from the build

<pre>grunt custom:-effects</pre>

Removing a module will also remove it's dependencies.  As an example, removing the .dimensions() command will remove .width() and .height() as well.  View the entire modules list and a more complete walkthrough of the installation process on the <a href="http://github.com/jquery/jquery">jQuery Github page</a>.

The jQuery UI project includes a Download Builder directly on it's download page. jQuery UI Builder Simply piece together your ideal build eliminate the need for unnecessary bulk. jQuery UI is a great example of a framework that has a lot of great potential, but applying it all to your website when it is unused or unnecessary can result in a lot of added load time. MooTools has a similar Download Builder page for your convenience.

If your favorite library doesn't have a custom builder, RequireJS is a widely popular module loader that services a similar purpose, and is extremely beneficial if you are using multiple libraries and plugins or have your own spread of JavaScript files that are each used in different locations. All you need to do is link to the require.js file in your markup, then use require() to dynamically load your JavaScript modules as you need them.

<pre>
  &lt;script data-main="scripts/main" src="scripts/require.js"&gt;&lt;/script&gt;
</pre>

And in your app.js

<pre>
requirejs.config({

    baseUrl: 'js/lib',

    paths: {
        app: '../app'
    }
});

requirejs(['jquery', 'canvas', 'app/sub'],
function   ($,        canvas,   sub) {

  // Apply your jQuery/canvas code

});
</pre>

Requirejs has <a href="http://requirejs.org/docs/api.html">fantastic API documentation</a> if this is a route that would be beneficial to you.

<h3>Responsive Images and Picturefill</h3>

<p>One of the future solutions to the problem of serving high resolution images to those that can handle it and low quality images to those who need them is the picture element.  It is not yet a standard specification (and may not be for awhile), but it shows the possible direction that may be taken to handle responsive and responsible images.  You can view the work in progress spec at the <a href="http://www.w3.org/TR/html-picture-element/">W3C</a> or at the <a href="http://picture.responsiveimages.org/">Unofficial Draft site</a>.</p>

<p>The goal of the picture element is to have embedded media rules depending on the current screen it is being viewed on.  This works the same way as one would write <a href="http://www.w3.org/TR/css3-mediaqueries/">media queries</a>, and would ensure that the user would only be served the image that makes sense for their machine.

An example of this could be a gallery image on a website.  We want those with a large screen to be able to view the large high resolution images, but those on a mobile browser to view a smaller version that would take a lot less time to download.  Rather than letting the browser resize it by changing the width or height via the CSS, we'll serve two completely seperate images so the mobile user doesn't need to use extra bandwidth on downloading unnecessarily large files.  We can also use a &lt;img src&gt; as a backup for legacy browsers.

<pre>
  &lt;picture width="500" height="500"&gt;
     &lt;source media="(min-width: 45em)" src="large.jpg"&gt;
     &lt;source media="(min-width: 18em)" src="med.jpg"&gt;
     &lt;source src="small.jpg"&gt;
     &lt;img src="small.jpg" alt=""&gt;
     &lt;p&gt;Accessible text&lt;/p&gt;
  &lt;/picture&gt;
</pre>

It is easy to see the massive potential of this new spec, but it isn't something that can be used in production yet. Because of this, Scott Jehl created Picturefill, a polyfill that expands the picture element idea but uses currently supported <div>s instead. This allows the same responsive image techniques to be used right now. The following sample markup is given as a starting point.

<pre>
    &lt;div data-picture data-alt="A giant stone face at The Bayon temple in Angkor Thom, Cambodia"&gt;
        &lt;div data-src="small.jpg"&gt;&lt;/div&gt;
        &lt;div data-src="medium.jpg"     data-media="(min-width: 400px)"&gt;&lt;/div&gt;
        &lt;div data-src="large.jpg"      data-media="(min-width: 800px)"&gt;&lt;/div&gt;
        &lt;div data-src="extralarge.jpg" data-media="(min-width: 1000px)"&gt;&lt;/div&gt;

        &lt;!-- Fallback content for non-JS browsers. Same img src as the initial, unqualified source element. --&gt;
        &lt;noscript&gt;
            &lt;img src="external/imgs/small.jpg" alt="A giant stone face at The Bayon temple in Angkor Thom, Cambodia"&gt;
        &lt;/noscript&gt;
    &lt;/div&gt;
</pre>

Notice that instead of the proposed source attribute, the polyfill uses the <a href="http://html5doctor.com/html5-custom-data-attributes/">HTML5 data attribute</a> of the each &lt;div&gt; to house the seperate images and the media queries, and includes the same fallback using noscript.  Combining this technique with sprites and compression, we can serve the best image per user without a lot of extra bulk.</p>


<h4>Icon Fonts</h4>

<p>Icon fonts are another solution to the issues of size and request amount caused by using many icons on a website.  Similar to the ideas of <a href="http://en.wikipedia.org/wiki/Dingbats_(Unicode_block)">Dingbats</a>, <a href="http://en.wikipedia.org/wiki/Wingdings">Wingdings</a>, and <a href="http://en.wikipedia.org/wiki/Webdings">Webdings</a>, icon fonts allow a developer to replace image icons with similar looking fonts.  There are several ways that this helps keep assets lean.</p>

<ul>
  <li>One http request to access the font</li>
  <li>The size of a text file can be much smaller than any images that would be uploaded.</li>
  <li>Much like sprites, once the file is downloaded, all of the icons will be shown.</li>
  <li>Using a lot of text icons is not any heavier than a paragraph of text</li>
</ul>

There are several ways to host and access these icon fonts.  As an example I'll use <a href="http://drewwilson.com/">Drew Wilson's</a> <a href="http://pictos.cc/">Pictos</a>, which has easily been my favorite and most used icon web font.

<p>First, you can download and host them yourself, and use @font-face to show them.  @font-face has it's quirks, especially with old versions of Internet Explorer, but Paul Irish as a fantastic in-depth blog post that analyzes these quirks and explains the best ways to avoid them.  The generally accepted best practice is to use his "Bulletproof @font-face Syntax" or <a href="http://www.fontspring.com/">Fontspring's</a> updated syntax.

<pre>
  // Bulletproof
  @font-face {
    font-family: 'Pictos';
    src: url('pictos.eot');
    src: local('Pictos'), local('Pictos'),
           url('Pictos.otf') format('opentype');
  }

  // Fontspring
  @font-face {
    font-family: 'Pictos';
    src: url('Pictos.eot?') format('eot'), url('Pictos.woff') format('woff'), url('Pictos.ttf') format('truetype');
  }
</pre>

Many of these IE issues come from the lack of support for the file types other than EOT.  The question mark in the Fontspring syntax keeps IE from reading the rest of the line, therefore keeping it from throwing an error at the unreadable font files.


If you are using the Pictos font, Drew created the <a href="http://pictos.cc/server/">Pictos server</a> as a way to host these icons easily without having to worry about them on your own server.  This is especially useful if you do not have full access to your backend through FTP or SSL.  <a href="http://weloveiconfonts.com/">We Love Icon Fonts</a> is a completely free and open source service that does a similar thing as the Pictos server, but with the huge bonus of using completely free icons.  After winning lifetime hosting by domainFactory, these icons should stay free and open for a long time.

<h3>Compression</h3>

<p>Compressing your assets is one of the easiest and most efficient ways to make your websites leaner and easier to access.  Images, stylesheets, and scripts can all be compressed and minified to save a surprising amount of space.</p>

<h4>Image Compression</h4>

<p>There are many free tools available that will compress your images for you, so this can be extremely beneficial with a limited amount of work.  An example of one of these tools is <a href="http://www.smushit.com/ysmush.it/">Smush.it</a> on the <a href="http://developer.yahoo.com/">Yahoo! Developer Network</a>.  Simply upload your images, and it will give you a ZIP to download that will contain the smushed versions.  They also give you information on the amount of space you save through the compression.

<img src="http://www.jasondemeuse.com/system/images/articles/accessibility/smush_uploader.png" alt="smush uploader">
<br/>
<img src="http://www.jasondemeuse.com/system/images/articles/accessibility/smush_uploaded.png" alt="smush successful upload">


There are other options available online that will achieve the same effect, like <a href="http://tinypng.org/">TinyPNG</a>, as well as native applications like <a href="http://imageoptim.com/">ImageOptim</a> for Mac.</p>

<h4>CSS and JavaScript Compression</h4>

<p>As stylesheets become larger, the impact of compressing them grows exponentially.  If you work with Ruby and/or <a href="http://sass-lang.com/">Sass</a>, your styles are already compressed for you when they are turned into a CSS file.  If you would like the same type of treatment with your vanilla CSS, there are tools like <a href="http://www.minifycss.com">MinifyCSS</a> that will compress it for you.  Using the <a href="https://github.com/h5bp/html5-boilerplate">HTML5 Boilerplate CSS</a>, let's compare how it would look normal vs. compressed.  Simply upload or copy and paste your code into the generator and let it do its work.  The results of the compression show how useful it is.

<ul><a href="https://github.com/jasondemeuse/accessibility-sample-code/blob/master/compression/uncompressed.css">Uncompressed</a>
  <li>300 lines</li>
  <li>5.677 kb</li>
</ul>

<ul><a href="https://github.com/jasondemeuse/accessibility-sample-code/blob/master/compression/compressed.css">Compressed</a>
  <li>1 line</li>
  <li>1.593 kb</li>
</ul>

That is a significant difference in a stylesheet, especially one that is meant as a baseline.  Putting this into use on large CSS files that could be ten times bigger only increase the value of CSS compression.  The same things can be done for you JavaScript files as well.  <a href="https://github.com/mishoo/UglifyJS">UglifyJS</a> is a NodeJS tool that will parse and compress your JS similar to how the CSS was compressed in the previous example.  The <a href="http://refresh-sf.com/yui/">YUI Compressor</a> can also handle both CSS and JavaScript and will compress your files in a similar way.  There are plenty of tools to choose from, the most important thing is to put at least one into use.</p>

<h1>Wrap Up</h1>
<p>Empathy toward our users' situations can go a long way in gaining trust and viewership.  Quality content and a consistent experience is what brings people coming back, not tricks and effects.  We as information disseminators need to be responsible in the way we present our content, and keep from turning away visitors before we get a chance to show them what we have.  If a website has content worth seeing and renders as expected, adding the occasional effect will only be that much more meaningful and it won't be at the user's expense.</p>

Accessible Websites for Everyone