Given the diverse nature of browsers today, the ability to detect browser features and constraints is vital to delivering an appropriate user experience. We have many ways to approach this detection, some more responsible than others.
DEVICE DETECTION: THE EVOLUTION OF A STOPGAP
Among topics of great debate in web development, perhaps the most contentious is the practice of device detection. Its mere mention in a gathering of peers gets my stomach tingling in anticipation of the fiery opinions that await. In truth, a little device detection is sometimes necessary in a complex cross-device codebase, but with each site I build, I find fewer reasons to use it. This is a good thing, as any approach that includes device specific logic risks threatening the sustainability of our codebase in the long term. Let’s explore some reasons why that is.
Detecting all the things
When a user first requests a page, we know precious little about their browsing environment. We don’t know the size of their device’s screen, or if their device even has a screen. We don’t know their browser’s capabilities. Fortunately, we can detect these qualities after delivering code to the browser, but in some cases that’s later than we’d prefer. One thing we can universally detect upon first arrival is a browser’s user agent information, included in every request that a browser—or user agent—makes. This string of text packs a variety of information, including the browser’s make and version, like Firefox 14 or Chrome 25, and its operating system, like Apple iOS. Crafty developers realized early on that if they gathered data about various browsers and their capabilities and stored them on their server (in what’s known as a device database), they could query that information when a user visits their site to get a good idea of the sort of browser they’re dealing with. This process is called user agent sniffing or, more broadly, device detection.
Sniffing up the wrong tree
Perhaps the most common criticism of user agent sniffing is that the information a browser provides isn’t always reliable. Browsers, networks, and even users sometimes modify user agent information for myriad reasons, which makes it difficult to know if you’re dealing with the browser you think you are. Let’s start with a few popular mobile browsers’ preference panels: Android’s default browser, Opera Mini, the BlackBerry browser, and others provide an easy means of changing the name the browser reports itself as. You’ll sometimes see this disguised as “Request desktop site” or with more granular settings like those in the Android browser, but the ability to change user agent information exists to give users the tools to fight against sites that deliver limited content and functionality to particular browsers its users from being locked out of the best versions of certain sites. For example, in addition to several appropriate bits of information, the UA string of my current browser (Chrome 34) mentions Mozilla, Webkit, KHTML, Gecko, and Safari—all terms describing non-Chrome browsers:
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5)
AppleWebKit/537.36 (KHTML, like Gecko)
Some browsers go even further and deliberately obscure information in their user agent string to trick sites into sending them the experience other browsers get! The user agent string for the vastly improved Internet Explorer 11 never mentions Internet Explorer; instead, it tries to trick device-detection libraries into thinking the browser is Firefox or Webkit, which developers came to recognize as the only browsers that support advanced features necessary to deliver a better experience. (In recent versions of IE, this is thankfully no longer true.) In her A List Apart article “Testing Websites in Game Console Browsers,” Anna Debenham notes a similar situation with the Sony PlayStation Vita’s browser: “The Vita’s browser is a WebKit-based version of NetFront. Strangely, it identifies itself as Silk in its user agent string, which is the browser for Amazon’s Kindle Fire”. Browser developers have an interest in ensuring the survival of their software. Ironically, the more web developers deliver their content and features unevenly based on user agent information, the less meaningful user agent information will continue to be.
“Set it and forget it?” Forget it!
But reliability is a minor problem compared to sustainability. We can only write detection logic against browsers and devices that exist now, which makes device detection utterly useless for gracefully accepting new browsers.
Most critically, relying too heavily on device detection can lead us to make dangerous assumptions based on information that’s not always up to date. Device detection provides, at best, stock information about a device or browser, meaning any optimizations we make based on that static data may not reflect the live, dynamic nature of a user’s actual browsing environment. These are some examples of variables that a device database can never accurately convey
- Viewport size. While a device database may return somewhat reliable information about a device’s screen, screen size often differs from a browser’s viewport size. For responsive layouts, it’s the viewport size we care about. We should also avoid assuming anything about a user’s connection speed based on screen size—smartphones are commonly used over fast Wi-Fi connections, while laptops and tablets can be tethered to a slow cell network—or worse: bus Wi-Fi.
- Device orientation. Those viewport considerations are twice as difficult when you consider display differences between portrait and landscape. Even if we know the dimensions of a screen, we have no way of knowing (on the server side) the device’s orientation. We need to ship CSS that accommodates viewport variability.
- Font size. The common practice of using em-based units for media queries means that users’ preferred default font size determines the layout they get, so a browser on a laptop with a large font size may need a smartphone-ish layout. (As we’ll discuss in a bit, CSS media queries handle this naturally.)
- Custom preferences. People commonly override their browser defaults and turn off features on their phones. A browser may support a feature, but a server has no way of knowing whether that feature has been disabled by the user.
- Input modes. Device databases can often tell us if a device has a touch screen. But as you may recall, just because a device has a touch screen doesn’t mean that it supports touch events, or that touch is the only input mechanism the device
offers. And of course, touch support is now built into devices that have large screens as well, such as Google’s Chromebook laptop, so it’s unsafe to infer any sort of relationship between touch support and screen size.