Polyfills have been written about extensively in the past few years. In fact there are numerous outstanding guide articles to be found right here on HTMLGoodies.com. So what’s left to say on the subject? Quite a bit actually. The Internet landscape changes in so many ways and with such rapidity that it seldom remains static for any length of time. So too with the world of Polyfills. As we’ll see in this 2017 update, we now have specialized Polyfills such as those for CSS and ECMAScript 2015, as well as libraries that tailor Polyfills to the browser.
Modernizr Keeps on Chugging Along
Although the first release of Modernizr hit the streets way back in July of 2009, it continues to enjoy massive popularity among web developers. Version 3.3.0 was released in early 2016, followed soon after by 3.3.1, which included some bug fixes. Besides making Modernizr better, the 3.3.x versions also included support for some newer browser and JavaScript features, such as:
- Safari’s new Force Touch/3D Touch API
- CSS hairlines
- ES6 collections
- font ligatures
- jpeg 2000
- css snap scroll points
- crossOrigin support on the img tag
Modernizr’s staying power can perhaps be attributed to its handling of both JavaScript and CSS. To illustrate, here are two ways to inform the user whether or not their browser supports web sockets, this first using JavaScript, the second, the CSS display property:
<!DOCTYPE html> <head> <script src="path/to/modernizr.js"></script> </head> <body> <p id="result"></p> <script> document.getElementById('result') .innerHTML = 'Your browser ' + (Modernizr.websockets ? 'supports' : 'does not support') + ' WebSockets.'; </script> </body> </html>
<!DOCTYPE html> <head> <style> .wsno, .wsyes { display: none; } /* Modernizr will add one of the following classes to the HTML element based on whether or not WebSockets is supported by the user's browser. */ .no-websockets .wsno, .websockets .wsyes { display: block; } </style> <script src="path/to/modernizr.js"></script> </head> <body> <p class="wsno">Your browser does not support WebSockets.</p> <p class="wsyes">Your browser supports WebSockets.</p> </body> </html>
Specialized Libraries
For those developers who are interested in equalizing either CSS or JavaScript, there are some quality offerings to choose from. As examples, we’ll focus on BABEL and Polyfill.js, which are ECMAScript 2015 (ES2015) and CSS libraries respectively.
ES2015 was a significant update to the ECMAScript/JavaScript language, and the first major update to the language since ES5 was standardized in 2009. While major browser vendors are in the process of implementing these features, you can employ BABEL to use the best language features – such as the arrow (=>) operator, Let and Const keywords, and generators – right now.
function square() { let example = () => { let numbers = []; for (let number of arguments) { numbers.push(number * number); } return numbers; }; return example(); } square(2, 4, 7.5, 8, 11.5, 21); // returns: [4, 16, 56.25, 64, 132.25, 441]
Unlike JavaScript, normalizing CSS across browsers is much more challenging and can impact performance. The reason is that CSS is a lot less extensible than JavaScript, so the latter has to be employed to modify the former. Here is an explanation in the Polyfill.js author’s own words:
JavaScript is a dynamic language, which means you can use JavaScript to polyfill JavaScript. And because it is so dynamic, it’s extremely extensible. CSS, on the other hand, can rarely be used to polyfill CSS. In some cases, you can transpile CSS to CSS in a build step (PostCSS does this); but if you want to polyfill anything that depends on the DOM’s structure or on an element’s layout or position, then you’d have to run your polyfill’s logic client-side.
In fact, the author of Polyfill.js has decided to no longer support the library. That being said, if you’re really keen on utilizing CSS Polyfills, the Polyfill.js will definitely get the job done. You just have to include the Polyfill.js library on your page and then create a new instance of the Polyfill object by passing in one or more keywords representing the CSS features you want to polyfill:
<script src="path/to/polyfill.js"></script> <script> var localLinkPolyfill = Polyfill({ selectors: [":local-link"] }); </script>
Loading Polyfills Based on the Browser
Traditionally, the drawback to using Polyfills has been that they penalize users on modern browsers by forcing them to download a lot of unnecessary code. Since the idea is to bring older and non-compliant browsers to the level of the latest and greatest ones, it makes a lot of sense to only load polyfills when they’re needed. Developed and maintained by a community of contributors led by a team at the Financial Times, Polyfill.io is a service that returns polyfills that will be of most benefit to the requesting browser, based on the User-Agent header. To use it, just include a reference to the hosted script:
<script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script>
Moreover, you can tailor the response for the specific features that you’re using in your app via the query string:
<!-- Load Array.prototype.map if needed by the browser and modernizr:es5array polyfills regardless of the user-agent - unminified. --> <script src="https://cdn.polyfill.io/v2/polyfill.js?features=Array.prototype.map,modernizr:es5array|always"></script>
Conclusion
The polyfills business is alive and well thanks to the ubiquity of devices, browser vendors, and ever-evolving language specs. Should you decide to make use of a polyfill service like Polyfill.io, I recommend examining your web stats to determine what browsers your visitors are using to view your site. That will help you better determine what polyfills to load and which can be safely ignored.