7 awesome browser features
Here's how to use seven awesome new browser features, and ensure users on older browsers can still play along too.
New APIs for the web seem to be released every week. It would be cool to be able to use them, but if you need to make sites for the average user, you won’t be able to implement them for years – right? Wrong. Exploring the latest and greatest of the web platform means you get to use the best tools at your disposal for your users and help push the web forward.
Here is a number of different features – some old, some new, all underused – that can be implemented quickly on your site, and will be almost guaranteed to improve the experience.
01. The Font Loading API
If you have ever browsed the internet over hotel Wi-Fi, 2G, or any other ungodly slow connection over the past few years, you will have undoubtedly encountered FOUT (flash of unstyled text). I love @font-face as much as the next person, but when you’re loading a multi-megabyte font over a connection measured in bytes per second, you are going to have a bad time.
The reason is that historically, browsers hide text from the user until the custom font has been loaded. However, new font dimensions can impact the layout of the page dramatically, and having a font change after the user has started interacting with the page could be an awful experience.
Monitoring font rendering on the web has always been tricky, because we’ve never had a way to know whether or not a font has been loaded. Until now, the most reliable method was to load text into a canvas tag and constantly check its width until it changed, signalling a font load. What’s worse was knowing that all the text had already been downloaded by the browser, and users were being blocked from seeing the very thing they came to read, just to give the browser time to make it look prettier.
With the new Font Loading API, you are able to take full control of the experience. The promise-based API notifies you when your web fonts have loaded – this means you can define a system font for the initial render, and a toggle CSS class so that you only use your web font after it has been loaded.
<style>
body {font-family: Sans-Serif}
body.fontLoaded {font-family: P4+RickRul3z-Sans}
</style>
<script>
document.fonts.ready.then(function() {
document.body.classList.add('fontLoaded');
});
</script>
There is a lot more to this spec, but this feature alone is a huge win. The only problem is the same one we have with all new APIs: it’s new. And therefore its browser support isn’t stellar. As of July 2016, the API is only supported in Firefox and Chrome. That is probably a large chunk of your market, but we can’t hang critical UX on a non-universal API. However, we can get a nearly identical API through Bram Stein’s super-lightweight Font Face Observer:
Get the Creative Bloq Newsletter
Daily design news, reviews, how-tos and more, as picked by the editors.
var font = new FontFaceObserver('P4+RickRul3z-Sans');
font.load().then(function () {
document.body.classList.add('fontLoaded');
});
Between these two APIs, you will be able to offer your users text that instantly loads, without having to give up your gorgeous web fonts.
02. Service workers
The hottest buzzphrase for web development in 2016 has to be progressive web apps. The new paradigm for creating web apps highlights offline functionality as one of the biggest missing pieces to the web.
Service Workers bring us a stunning amount of power, chief among it the ability to programmatically intercept any and all network requests (read: 100 per cent offline support). It will almost certainly be the cornerstone of any groundbreaking new app.
Even though all major browser vendors (sans Apple) have publicly committed to implementing Service Workers, it will still be months – if not years – before you can count on the API being in your user’s browser. Does that mean we need to wait that long to use it? Hell no.
We have been able to go offline since 2008 ... with AppCache. Don’t get me wrong, AppCache is terrible for a myriad of reasons, most of which are covered in colourful detail by Jake Archibald in his ‘AppCache is a douchebag’ talk from JSConf 2013. But AppCache has one major strength: incredible browser support.
Every major JavaScript-enabled browser of the past few years has supported it. So while we can (and should) build with Service Workers, you can fall back to using AppCache for basic asset caching in other browsers.
if (navigator.serviceWorker) {
navigator.serviceWorker.register('/sw.js')
} else if (window.applicationCache) {
var iframe = document.createElement('iframe');
iframe.src = '/customBuiltIframe.html';
document.body.appendChild(iframe);
}
Obviously we want to use Service Workers when they are available, so we only ever fall back to AppCache after confirming Service Worker is not available. The only catch is that for AppCache to work, the manifest attribute (which is used to load the AppCache configuration file) has to be included when the page is loaded. The way around this is to append a hidden iframe to the page with just the manifest defined.
<!doctype html>
<html manifest="/offline.appcache">
<title>blah</title>
</html>
And that’s it! Now you have your static assets cached, you will have much faster loading and browsing experiences. There are a ton of rough edges with AppCache so please do your research before deploying, but with careful attention you can give nearly all your users a great offline experience today.
03. Web Workers
Web Workers are probably the most under-utilised piece of the web. Introduced by WebKit in 2008, this API solves one of the most nagging problems with developing performant websites: the single-threaded nature of browsers. Because the browser doesn’t have a way to guarantee that one chunk of JavaScript won’t change the state that another chunk depends on, it has to run all the code in sequence.
You may have learned this the hard way if you ever tried to attach a function to a scroll event on your site. Because it can fire dozens of times a second, anything over very simplistic functions quickly janks up the entire page. Web Workers solve this problem by creating a new context, separate from the DOM. That means you won’t have access to the DOM, or a number of global window properties. Your main communication is postMessage, a callback-based, text-passing API that lets you send data from your main script to the worker and back again.
// feature detect webworker, in case we are using an old browser
if (window.Worker) {
// worker.js is a separate JS file, which defines the worker
var worker = new Worker("/worker.js");
worker.onmessage = function(e) {
var result = e.data;
console.log(result);
}
// We send a message to the Worker via postMessage.
// It can be almost anything you want, (e.g. Object, Array, or String)
// but keep in mind it will be stringified before it reaches the worker
worker.postMessage({msg: 'Hello World'});
}
In a separate file, which we have named worker.js, we set up our Worker:
// Workers have a global function, importScripts, which does what it says on the tin
// You can use it to load any JS file from your site, commonly external libraries
importScripts('lib.js');
// All we need to do is wire up a global function called onmessage, and we can
// receive any communications sent from our regular script
onmessage = function(e) {
// even though we sent an object in the above snippet, it was stringified.
// so we need to parse it again to convert it to JSON.
var data = JSON.parse(e.data)
if (data.msg === 'Hello World') {
postMessage('Right back atcha')
} else {
postMessage('I didn't want to say hello anyway...')
}
}
Of course, this is a very silly example – you would never need a Worker just to send text back and forth. However, you can see how simple the API is, and how powerful it can be to have a space where you can run GPU-melting code without losing so much as a frame on the main thread.
Once you’ve souped up your site with Web Workers, you can do things that previously would have been unimaginable: resizing gigapixel images without ever contacting the server, including full databases like PouchDB, or writing some AI for a chess game. Basically, if you can code it, you can add it to your page through a Web Worker, all while keeping everything silky smooth.
04. Clipboard
There have been ways to copy text since Microsoft shipped IE4 in 1997, but was a long, long road to where we are today: with an interoperable version shipping in all major browsers (Safari’s is still in Technical Preview, but it is coming soon!). It may seem like a relatively simple feature, and it is, but if you add it to the right thing on your site, you can surprise and delight users with a streamlined experience.
Rather than relying on Flash libraries or other hacks, we can simply use vanilla JavaScript:
var button = document.querySelector(‘.copyButton');
var range = document.createRange();
range.selectNode(button);
window.getSelection().addRange(range);
try {
var result = document.execCommand('copy');
var msg = result ? 'successful' : 'unsuccessful';
console.log('copy was ' + msg);
} catch(err) {
console.log(err)
}
window.getSelection().removeAllRanges();
Like most 20 year-old browser APIs it’s clunky, but it is fairly straightforward. You just create a range (the content that is being selected, in our case the .copyButton element), and then run execCommand('copy') on it. Like I said, it’s simple and small, and it can result in huge usability wins for any website.
05. The Blob API
You don’t need to reach out to the server to create a file. With blobs (binary large objects), you can take any arbitrary content – be it user-created Canvas images, generated documents like those on coding sites like CodePen or JS Bin, or even the page you are already on.
<!doctype html>
<html>
<head>
<title>content demo</title>
<script>
var pageContent = new XMLSerializer().serializeToString(document);
var pageBlob = new Blob([pageContent], {type: 'application/octet-stream'});
var a = document.createElement('a');
a.href = URL.createObjectURL(pageBlob);
a.innerText = 'Click me to download this page!';
document.documentElement.appendChild(a);
</script>
</head>
<body/>
This is super-useful any time the user creates content on your site, or you have to go on a trip back to your server to download some generated content just to trigger the ‘Save’ dialog prompt.
All that is required is for you to pass in an array of the content you want to generate the blob from, as well as the mime-type you want the client to treat, and you get a binary blob representing that content.
If you want to be able to download that on the page, pass the blob into URL. createObjectURL and create a link that points to it. You can either have the user click a button, or call .click() yourself. Either way, you get to download your files without ever leaving your user’s device, saving bandwidth and time.
06. Scroll Snap Points
At nearly every job I have ever had, I’ve had to implement a carousel. Despite being a simple concept, it inevitably ends up being more code than feels right – and good luck trying to make sure it is accessible and performant.
Because I am not alone in this Sisyphean task, Matt Rakow and Jacob Rossi from Microsoft created CSS Scroll Snap Points. Rather than animate all of your slides with JavaScript, Snap Points lets us separate our presentation from our logic and define the carousel-like interaction entirely in CSS.
#carousel {
scroll-snap-type: mandatory;
}
.slides {
scroll-snap-points-x: repeat(100%);
}
Now when the user stops scrolling, the most recent slide will snap to the left of the carousel container. Everything else works automagically, with GPU-powered goodness. Of course there is a ton more you can do with it, and a number of properties and values you can use to customise your carousel.
It is worth noting that while the Internet Explorer team created the specification, it has evolved quite a bit since. As a result, the implementations are quite different across browsers – use a tool like Autoprefixer to make sure you are covering your bases. And as always, make sure you are loading a polyfill like scrollsnap-polyfill for non-supported browsers – you don’t want the content to be inaccessible.
07. IndexedDB
IndexedDB is yet another feature of the web platform that is criminally underused. Effectively a full database inside the browser, it lets you store dozens of megabytes of content on mobile (typically over 50MB), and anywhere up to hundreds of gigabytes on desktop (yes gigabytes, with a ‘g’)! It’s also a great option for storing blobs of data, like page assets or images, so they can be loaded even when the user’s device is offline.
The biggest drawback to IndexedDB has always been its obtuse syntax. While technically brilliant, it is much more complex than document.cookie, localStorage, or any other data storage method. You shouldn’t let that stop you any longer, though! There are some fantastic libraries that cover up browser differences, as well as giving you much more human-readable syntax.
For example, Dexie.js gives you a beautiful jQuery-style syntax around your transactions, and the localForage wrapper gives you the power of IndexedDB with the simplistic API of localStorage. Perhaps one of the coolest wrappers is Mikeal Rogers’ PouchDB. This is a complete client-side implementation of CouchDB, which means you get Couch’s built-in full replication (you can replicate the entire database down to a user’s device!).
IndexedDB is ridiculously powerful, and with recent updates to Safari and the plethora of great libraries paving over browser inconsistencies, you should really check it out today.
Conclusion
What I’ve covered here is the tip of the iceberg. There are dozens and dozens of APIs and features that have been created to improve the web platform. Not all of them get glossy cover features or in-depth blog posts, but they are there, waiting in your users’ browsers for you to wow them with. Don’t let a lack of full browser support stop you from playing with any new APIs. With just a little progressive enhancement, you can give a great experience to nearly all your users, and help push the web forward.
Thank you for reading 5 articles this month* Join now for unlimited access
Enjoy your first month for just £1 / $1 / €1
*Read 5 free articles per month without a subscription
Join now for unlimited access
Try first month for just £1 / $1 / €1