New Approach Browser sniffing

I’ve started exploring a new approach to sniffing out browser makes and models. The idea is between vendor prefixes in the CSS and different browsers introducing features in different orders using the presence of a feature becomes a reasonable way of targeting an old browser. The technique has the failing that it cannot be safely used to target an edge browser, but the various edge browsers usually aren’t the trouble makers - it’s the old crap.

Before introducing them a disclaimer - I feel a targeted browser hack is a last resort action - the sort of thing you do when the bug is found the day before launch. Ideally a solution should be devised that works on all browsers. Also, unless you’re using edge features this sort of thing shouldn’t come up. Here’s what I’ve come up with so far.

iOS 7 mobile Safari, Safari 7.0 or earlier
Apple did us all an enormous favor by implementing CSS view units wrong. I like using these, but iOS 7’s borking of them remains a pain in the tail. iOS 8 fixes it, but iPhone 4 can’t upgrade to it and there’s a handful of those units out there. So

    if( typeof window.HTMLTemplateElement === 'undefined' && 
        typeof document.body.style.webkitBorderRadius !== 'undefined' 
    ) {
        document.getElementByTagName('html').className += ' iOSlt8';
    }

The template Element was also introduced in iOS 8, so it can be used to distinguish the two. A check to insure we’re talking webkit browsers is needed since IE correctly displays view units but doesn’t support the Template element. Chrome supports that particular webkit tag, but it also has had the template element for awhile so like iOS 8 it will ignore this.

IE 10
Starting with 10 the html conditionals go away. To pick it out we test for a proprietary tag introduced in 10 (Grid columns) and make sure one added in 11 isn’t around (Request Full Screen)

    if (typeof document.body.style.msGridColumns !== 'undefined' &&
        typeof document.body.msRequestFullScreen === 'undefined'
    ) {
        document.getElementByTagName('html').className += ' ie10';
    }

IE 11
This one is a little chancier - it will become broken if Microsoft changes their mind about adding the gamepad api to IE 12. Since they’ve been hyping it a lot I think that’s pretty unlikely.

if (typeof document.body.msRequestFullScreen !== 'undefined' &&
    typeof navigator.getGamepads === 'undefined'
) {
    document.getElementByTagName('html').className += ' ie11';
}

The main reason to check for IE 11 is its lack of transform: preserve-3D causes certain transitions to become unstable, so feeding IE an alternate 2D based transition works well here.

This approach can’t be broken by future changes to the user agent string. It will break if you try to use it with edge browsers because you’ll get a false positive on successive generations released after your code was written. That might not always be a bad thing - in the case of the IE 11 sniff above, for awhile I was just checking for request full screen to switch transition styles. The alternate 2d one looks just as professional as the snazzy 3d one, and it wouldn’t break my heart if IE was forever doomed to use that transition.

All of the examples above are intended for use with CSS. For example, how the iOS version would be used:

h1 { font-size: 20vmax; }
html.iOSlt8 h1 { font-size: 20em; }

And yes, I know about the buggy-fills out there. I found them to be themselves pretty buggy and unreliable, so I’d rather just give em units appropriate to the iphone 4 and call it a day.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.