Tuesday 17 June 2014

Feature Support & Polyfills

Building a website can be both extremely rewarding and frustrating. Common frustrations arise from trying to get a website to look and perform the same in every browser. All front end developers have shared this frustration at one point or another.
Truth be told, websites do not need to look or perform the same in every browser. Exactly how close a website works in each browser is up to you and your level of comfort for a given website. If a website receives under half a percent of traffic from Internet Explorer 6 it might make sense to drop support for it. If that half a percent is still contributing to thousands of dollars in sales, support may be mandatory. Determine what is acceptable for a given website and work from there.
There are a handful of common practices to get websites to perform adequately in all browsers, some of which have already been covered within this guide. When incorporating CSS3 properties, fallbacks are recommend to support older browsers. Other techniques include shivs and polyfills. Generally speaking, shivs and polyfills are small JavaScript plugins that add support for a requested set of features not natively supported by a specific browser.

HTML5 Shiv

Perhaps the most popular shiv, and one you may have likely used already, is the HTML5 Shiv. The HTML5 Shiv was created by Remy Sharp to provide the ability to use HTML5 elements within versions of Internet Explorer 8 and below. The HTML5 Shiv not only creates support for HTML5 elements but also allows them to be properly styled with CSS.
The shiv should be downloaded from Google, where Remy maintains the latest version, then hosted on your server. For the best performance, reference the shiv JavaScript file within the head of the document, after any stylesheet references. Additionally, you want to reference the shiv inside of a conditional comment, making sure that the file is only loaded within versions of Internet Explorer 8 and below.
In this case the conditional comment looks like <!--[if lt IE 9]>...<![endif]-->.
1
2
3
<!--[if lt IE 9]>
  <script src="html5shiv.js"></script>
<![endif]-->

The Difference Between a Shiv & a Shim

Chances are you may have heard of both the HTML5 Shiv and HTML5 Shim, and wondered what the difference, if any, may be. Oddly enough, there is nodifference between the HTML5 Shiv and HTML5 Shim. The two words are often used interchangeably and are commonly transposed.
Additionally, once the new HTML5 elements are created using the shiv, any block level elements need to be identified and updated using the display: block; declaration.
1
2
3
4
5
6
7
8
9
10
11
12
13
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
nav,
section,
summary {
  display: block;
}
Lastly, Internet Explorer 8 and 9 do not correctly define styles for a few HTML5inline-block level elements. As before, these styles will need to be explicitly stated. After which, all versions of Internet Explorer should be good to go using any new HTML5 elements.
1
2
3
4
5
audio,
canvas,
video {
  display: inline-block;
}

Detecting Browser Features

Referencing the HTML5 Shiv works well with a conditional comment because the intention is to specifically target browsers that don’t support new HTML5 features and elements. Additionally, there is a way to to provide support for specific HTML5 and CSS3 features, regardless of which browser is being used.
Feature detection, as provided by Modernizr, provides a way to write conditional CSS and JavaScript based on whether or not a browser supports a specific feature. For example, if a browser supports rounded corners Modernizr will add the class ofborderradius to the html element. If the browser doesn’t support rounded corners, Modernizr will add the class of no-borderradius to the html element.

Loading Modernizr

To get feature detection with Modernizr up and running, simply visit their downloadpage and customize what features you are looking to detect, or use the out of the box development version. Most commonly the development version is the way to go, however, if you are only looking for support for one feature, a custom build would be more appropriate. Once downloaded, upload the JavaScript file on your server and reference it within the head of your HTML document, below any referenced style sheets.
It is worth noting that Modernizr may be configured to include the HTML5 Shiv, in which case the shiv doesn’t need to be referenced on top of Modernizr.
1
<script src="modernizr.js"></script>

Conditionally Applying CSS Styles

Once Modernizr is up and running CSS styles may be conditionally applied based on the features a given browser supports. Modernizr has detection for the majority of the CSS3 properties and values, all of which can be found in the Modernizrdocumentation.
One item to weigh out is if feature detection is necessary for certain styles. For example, using an RGBa color value may easily be supported with a fallback hexadecimal value without the use of feature detection. When deciding to use feature detection, it is important to keep styles organized and performance in mind. Avoid duplicating any code or making additional HTTP requests when possible.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
button {
  border: 0;
  color: #fff;
  cursor: pointer;
  font-size: 14px;
  font-weight: 600;
  margin: 0;
  outline: 0;
}

/* With CSS Gradient Styles */

.cssgradients button {
  border: 1px solid #0080c2;
  background: linear-gradient(#00a2f5, #0087cc);
  border-radius: 6px;
  padding: 15px 30px;
}
.cssgradients button:hover {
  background: linear-gradient(#1ab1ff, #009beb);
}
.cssgradients button:active {
  box-shadow: inset 0 1px 10px rgba(255, 255, 255, .5);
}

/* Without CSS Gradient Styles */

.no-cssgradients button {
  background: transparent url("button.png") 0 0 no-repeat;
  padding: 16px 31px;
}
.no-cssgradients button:hover {
  background-position: 0 -49px;
}
.no-cssgradients button:active {
  background-position: 0 -98px;
}

Feature Detection Demo

In the demonstration above, the button inherits some default styles. However, specific styles are only applied based on whether or not CSS3 gradient background are supported. In this case, rounded corners and box shadows are also included within the conditional styles. Those browsers that support gradients get a gradient background, rounded corners, and a box shadow. Those browsers that do not receive an image with all of these styles included within the image. With this code none of the styles are being over written and an HTTP request is only made when necessary.
When working with CSS3 feature detection it is hard to know what the styles look like in browsers that do not support specific CSS3 features. Fortunately, there is a bookmarklet called deCSS3 which disables any CSS3 features. Doing so allows you to see what a website would look like without CSS3, and if your conditional styles are working. To get a quick idea of what an individual browser supports, visit haz.io within that specific browser.