Episode 95 of The SitePoint Podcast is now available! This week Kevin Yank (@sentience) chats with Paul Irish (@paul_irish), Google Chrome Developer Relations guy, jQuery guy, and Modernizr guy, about how to detect the features supported by browsers, and what to do about the features you can’t detect.
Listen in your Browser
Play this episode directly in your browser! Just click the orange “play” button below:
Download this Episode
You can also download this episode as a standalone MP3 file. Here’s the link:
- SitePoint Podcast #95: The Undetectables with Paul Irish (MP3, 34:20, 31.5MB)
Subscribe to the Podcast
The SitePoint Podcast is on iTunes! Add the SitePoint Podcast to your iTunes player. Or, if you don’t use iTunes, you can subscribe to the feed directly.
Kevin: January 17th, 2011. This week a mega-techy conversation about feature detection in a post-standards world. I’m Kevin Yank and this is the SitePoint Podcast #95: The Undetectables with Paul Irish.
And I’d like to welcome Paul Irish on the Podcast today. Hi Paul.
Paul: Hi, Kevin, how’s it going?
Kevin: Thanks for being on. Paul is, well, Paul is a busy guy. His website says he’s a front-end developer but he also works for the Google Chrome Developer Relations Team, I assume there’s a whole team behind that developer relations, it’s not just you is it?
Paul: Yeah, we have about ten people all across the world talking with developers about making really cool stuff happen on the Web.
Kevin: Yep and when you’re not busy with that you’re hacking on jQuery, you’re a member of the jQuery team, and if that weren’t enough you also work on this amazing library, I guess you could call it a library, called Modernizr which is what brings us to you today.
Paul: Right. It’s interesting, like geolocation is a really nice one where all you have to do is say
if (navigator.geolocation) and you have basic geolocation support, and that’s pretty much all you need to get going. But then you look at something like 3D CSS transforms. Interestingly, the very base technique for detecting a CSS property is seeing if like
element.style.webkitTransform or something exists, if the browser recognizes that property. In the case of 3D transforms it exists but even in Chrome, which hasn’t supported 3D transforms for a bit now, and so you have to do a more robust technique where you actually check to see if a specific media query would succeed or not, and so there are all these little gotchas when it comes to feature detection, things might act differently inside private browsing or incognito mode, and so these are the kinds of things that get wrapped up into the Modernizr source code which is a fun read if you’re into the stuff.
Kevin: What I love about Modernizr is the way it boils down all these tricks into something really usable. What do you get; you put Modernizr into a page, it runs, what do you hang your hat on, what does it produce for you?
Paul: It gives you basically two separate APIs. The most usable one and the first one that people usually grab onto is that it throws a bunch of classes onto the
html element on the page, and so now the
html element has a class of
border-radius, but then it might have a class of
no-flexbox for the flexible box model. And so with that in your styles you can like let’s say with
box-shadow if you’re using
box-shadow you’re just going to put in those box shadow rules, but if you don’t have
modernizr, and so
modernizr.video is true if there is support for HTML5 video, and even
modernizr.video.ogg is true if there is support for the Ogg codec for video.
Kevin: Wow. So basically you get these two things, you get the
class attribute on the
html element which lets you — it’s kind of the next best thing to CSS media queries; ideally you’d be able to use like a CSS media query that said if the browser supports this feature use this whole bunch of CSS rules on the page, but since we can’t quite do that with media queries the next best thing is you can just make at the start of all of those rules
Paul: Right. And so the way that I’ve been using this for a while now is to basically “polyfill” support into older browsers if there’s isn’t any. And so “polyfill” is a word Remy Sharp actually came up with it.
Kevin: Yeah, I haven’t heard that word.
Paul: It’s essentially a shim.
Kevin: Well, polyfill is this product I remember my dad having in his workshop growing up; you squeezed it into cracks in the wall as far as I remember.
Paul: Yeah, exactly! And so like IE 6 and 7 and 8 have a lot of cracks and so we’re gonna fill those cracks with these polyfills. So for instance I really like
input type=range; I just type
Paul: But the point is that we only have to load them if we need them and so with Modernizr we have that control.
Kevin: Right. So we all have these websites that we built five years ago that if you look at the code you can go, oh, that entire approach is because I needed to support Internet Explorer 5 back then, and as a result this website is completely inefficient and difficult to maintain today because of a browser that no one uses anymore. It’s nice to be able to bundle those chunks of code that you are know are going to go away hopefully sooner rather than later so they’re really easy to lift out.
Paul: Yeah, exactly.
Kevin: I suppose the biggest benefit of a library like Modernizr is it makes it more convenient than ever to kind of start at the top, start with the best browsers today, build a site that works in those and then gradually work down through your list of more and more loathed browsers and adding support for them as you go.
Paul: Yeah, I totally agree. Andy Clark who goes by @malarkey on Twitter, he’s been evangelizing this kind of philosophy of design and development really well, it kind of coalesced it all into a nice package in his recent book Hardboiled Web Design, but it’s very much an approach of things are gonna look different in different browsers and that’s okay, but we want to be designing for the best possible experience because all browsers are catching up to where the top browser’s at, and we want to make the experiences really shine and really be engaging at that level. And we can kind of make our designs adaptive to the environment and so he’s really keen on this kind of approach of feature detection and skillful use of the features when they’re there and handling the cases when they’re not in a responsible manner.
Kevin: What’s your take on I suppose the common argument that is it just results in a whole lot more work, rather than building one website you end up building two or three.
Paul: It doesn’t for me. (laughter) It makes a lot more work when — it’s a lot more work when everyone expects things to look the same, like I’ve spent a lot of time trying to get the alignment of a
label to a radio button to be similar across browsers.
Kevin: Ah, yeah.
Paul: It’s such a pain, and like so we actually ended up landing some code in the HTML5 Boilerplate project that I’m active on to handle this, and so this issue might be put to bed, but I think trying to get rounded corners and shadows functional in IE 6 and 7 and 8 is a pain, and so it’s like selling someone on the idea that things can look different but acceptable everywhere actually ends up saving you a whole lot more time as a developer than actually trying to make it look the exact same.
Kevin: Yeah, I agree with you. We talked about HTML5 Boilerplate actually on this podcast back in episode #75, but yeah I think I agree with you that as soon as you— It’s an on paper argument, but in fact I think the killer hack here is to let a few of those things go. If 20% of your audience is on IE 6, and that would be a pretty extreme case these days I suppose, you’re hopefully lower than that now. But if 20% of your audience is IE 6 do you really want to spend the bulk of your time building code for that browser or do you want to make it look great on the great browsers and acceptable on the older browsers? I think you can save time that way, is what it comes down to.
So, with all of us on the same page there is another page I wanted to talk about, and that is The Undetectables, and this is what put your name on my radar this week. This is a page you started and wrote the bulk of on the Modernizr Wiki. This is on the— Modernizr’s hosted on the GitHub code sharing service and it has a Wiki attached and one of the three pages in that Wiki is The Undetectables. So I suppose as you start writing a library to detect features you become extra aware of the features you can’t detect.
Paul: Right. And so I was I sold on feature detection a while ago, but I was always catching these cases from time to time when I was like I don’t think that this is detectable, and the most obvious one and the one that showed itself up to me first was the behavior of the
select element in IE 6. Microsoft calls it a “windowed element”, and it shows up above everything else and so you’ll put like a modal dialogue on top but it’ll be like showing right through it and so you have to do this annoying thing where you use an empty
iframe that’s underneath the layer that you’re trying to show and that’s the only way to like — it’s such a pain.
Kevin: Yeah, the way we often do it is we hide all of the
select boxes on the pages as we go to modal dialogue.
Paul: Or that, yeah.
Kevin: It’s super ugly.
Paul: It’s terrible. And so like I was thinking about it and I was kind of exploring the element itself and I was trying to see if it exposed any sort of API that indicated that it was windowed, and there’s really nothing, and there’s no way to—
Kevin: You’re looking for like a
hasLayout for this particular quirk, yeah.
Paul: There’s no way to detect that that element will have that sort of behavior in that browser, and so you’re basically left with if it’s IE 6 do this thing, and so you use like conditional comments and like conditional comments is a lesser form of browser sniffing and so it’s moderately okay.
Kevin: Well, yeah, it would be great if you could just do an API call get a list of all of the “windowed elements” on the page and do something with them to get them out of the way.
Paul: Right. And so what I wanted to do was basically starting with
select elements and going to things like
registerProtocolHandler, which allows you to associate the mail to protocol with a web app instead of a native system app. That is exposed in some older versions of WebKit but doesn’t actually do anything but you don’t know that it doesn’t do anything because there’s no way to tell. Yeah, so, on The Undetectables page we basically have a list of a lot of these things, things from HTML5, things relating to networking (the amount of simultaneous connections that are possible, there’s no way to detect that smoothly or easily), and other things because, you know, I am an enormous proponent of feature detection. But I don’t want people to think that we can dissolve the user agent string or completely remove browser sniffing from the foundation, from any sort of library, because I just wanted to show that there are things that we might not be able to work around with feature detection and so it’s these things to keep in mind.
But I also like it because it’s kind of a good hit list because some of these things might actually be detectable; a good example was that when we had a lot of people contributing to this document when we released it, generated content with using
:after pseudo-selectors doesn’t really show up in the DOM so you can’t really touch it that way, but so someone added that in but a lot of other people saw that and were like I bet we can actually detect that, and so we actually ended up finding a really solid method of detecting support for that in a way that works everywhere.
Kevin: Do you remember off the top of your head what the trick was?
Paul: I think essentially what it is, so using the
:before pseudo-selector and then
content it injects content into the view directly inside that element but it’s not outside the element, so anyway, the trick is to basically force the container box to expand in size either through text wrapping or another way, and we can then detect the size of that box changing dimensions.
Kevin: Right. So if you make the
:before element style it as a block with one pixel height you can detect that the height of the containing element has increased by one pixel.
Paul: Right, that there’s a change.
Kevin: Wow! Yeah, I love that stuff (laughter). I don’t know if I’m the only one but I geek out on this stuff. So, the question I have is, is this a list of things that Modernizr simply doesn’t detect or is this a list of things where you’ve had to cheat in Modernizr and put in a user agent string detection?
Paul: Modernizr has no user agent string parsing at all in it, it actually previously had a few conditional compilation flags to snag IE’s JScript engine but those are now gone. So, Modernizr is straight up feature detection, there’s no user agent tricks in there right now.
Kevin: So it must be really, I don’t know, that seems to me like a really purist approach, it seems like you could add support for every single bullet point in this list if you just compromised on that one point.
Paul: (Laughs) Yeah, probably.
Kevin: (Laughs) So what’s the rationale, do you want to keep this stuff hard so that hopefully the browser vendors will take notice—and ignoring for the sake of this conversation the fact that you work for a browser vendor.
Paul: (Laughs) Yeah, let’s ignore that! I’ll give you a good example that is very close to my heart, which is file drag and drop is really sweet. So like in Gmail you can drag a file from your desktop into Gmail and all of a sudden it detects that, it sees that you’re actually dragging, you can just drop it right onto your message and it throws it in as an attachment so you don’t have to like go through that big, long finding through your Finder dialog to find that file, you just drag it in, it’s great. The feature is huge and I think people would adapt their apps to basically acknowledge, oh, this browser can support this. The problem there is that in order to detect it you basically have to explore the
dataTransfer object, the
dataTransfer object is attached to the event object that’s passed into the handler of a drag event.
Kevin: Wow, okay.
Paul: But, Gecko exposes a global
dataTransfer constructor, and so basically in Firefox we can just look inside that
dataTransfer constructor and see, oh, actually there is native support for file drag and drop in here. But because that object isn’t exposed globally in WebKit—so in Safari and Chrome—you can’t.
Kevin: You need a drag event first.
Paul: Yeah, you’d need to actually have the drag happen and then you would know at that point, but it’s usually too late when you’re actually in the action.
Kevin: Yeah, you can’t be checking for that when Modernizr runs at the start of the page.
Paul: Exactly, yeah, exactly. So that’s a good case where I think that the browser vendors can actually respond to this list and say— Because all the browser vendors absolutely support feature detection, in theory they agree that everyone should be doing it instead of UA parsing, and so I think there’s a few cases here where we can basically guilt browser vendors into doing the right thing. I mentioned before
registerProtocolHandler, that was actually removed by WebKit because of this exact case, someone spoke up and said hey this is a pain for developers who are using feature detection, they can’t detect this, you can’t have it exposed, and WebKit’s like okay we’ll remove it. So they are being responsive and I think there are a few cases here where they could be better.
Kevin: So, let’s talk about what doing the right thing means because I think it has changed over the years, and particularly in the last few years we’ve kind of— We’ve moved into what I guess I would call kind of a post-web-standards era where once upon a time we thought of web platforms and features in those web platforms in terms of W3C spec versions. This browser supports CSS1; this browser supports CSS2; it supports HTML4; it supports XHTML1. You bundled all these features together and you said the browser supports all of these or none of these and I’m gonna build my web pages along those lines. And the pace of browser development, the competition between the different browser vendors in the past few years has ramped up to a pace that we haven’t seen since the Web bubble in around 2000, where the version 4 browsers were going at it. And in that environment it just does not seem practical to bundle those features together, each individual CSS property and in some cases each individual value that you can assign to that CSS property is something that may have full support, no support, or support under development in any given browser. And I think web developers need to make their peace with that, but it means that it puts the burden I think on web browser vendors to be responsible about how they introduce new features into their platforms. And many of the items in this list of undetectables strike me as examples where they have failed on that front.
Paul: That’s a good way of looking at it. I agree though I think we can’t, you know, a lot of people used to be like, “Well which browser supports HTML5? We have to wait till browsers support HTML5.”
Paul: We’re not talking about one thing, we’re talking about what are the features inside HTML5 that we want to use and when are those available, and so you definitely have to break it down. Even with CSS
box-shadow you can do an inset box shadow and that has different support other than the standard box shadow, and then there’s a way to spread out or condense the size of the box shadow that’s different than the spread, and so there’s like all these little pieces of these implementations that differ even across the browsers that support the base feature.
Kevin: Yeah, features, and sub-features, and aspects of features.
Paul: And so I was gonna say seems like all those things that I mentioned are totally detectable, so it’s totally flexible for you as a developer to respond and to customize that experience.
Paul: So, a good example of this here is that— Well, I guess it’s worth pointing out that the vendor prefix is basically a signal to you as a developer that this, the behavior of this style might change, and by using this style you are entering into an agreement that you might have to update it in the future.
Kevin: Yeah, you’re gonna have to subscribe to a mailing list if you use this feature (laughter).
Paul: In general we haven’t really seen too much of that where the behavior has changed quite significantly, but I can tell you just I think this last week WebKit changed how it does gradients.
Kevin: Yeah, that was the big one, CSS gradients.
Paul: Right, and so now WebKit does linear and radial gradients very similar to how Firefox has been doing it which aligns very closely to what the spec has been updated to. And so it’s a little bit, it’s actually a touch different than what Firefox has had but it’s pretty close. But the nice thing is that actually it uses new properties so actually the syntax is different, so your old code should actually succeed and the new code uses new properties and so there won’t actually be a conflict there, but if you’re doing CSS gradients it will slowly be moving over to a completely standardized style which I think everyone is really looking forward to.
Kevin: Yeah, the other one that comes to mind I think was rounded corners, for a while every browser had its own
border-radius property with its own vendor prefix, and at least in Firefox’s case it was because they didn’t feel like their implementation was quite complete, the background of the box would bleed out underneath the rounded corners for a while and they said until we get this working exactly the way we want we’re gonna keep it with a vendor prefix even though we’re not technically doing anything that breaks the standard where we don’t feel like this feature is complete yet I guess.
Paul: Right, yeah.
Paul: Um, that’s a good question.
Kevin: Because it seems like the HTML5 web sockets API that I haven’t taken a close look at but I’ve seen a lot of people talking about how it’s just not ready for prime time and the browsers that do implement it the implementation isn’t good enough or final enough or stable enough for regular use.
Paul: This is for web sockets in particular?
Kevin: Yeah, yeah, yeah.
window.indexedDB, you have to go
window.mozIndexedDB, and that’s because we want developers to get used to these APIs and explore them and offer some feedback to the Standards list, and maybe there’s enough of a feedback, enough feedback that it’s worthwhile to change the API. And so it’s kind of like a time while things stay prefixed it’s a time for everyone to kind of explore things, see if you like it, and offer feedback to the Standards list to see if maybe we should tweak this because this doesn’t actually suit my needs as a user. And so until everyone feels comfortable that what is shipping in these experimental implementations, it’ll stay behind those vendor flags.
Paul: I actually think you can detect support for soft hyphen.
Kevin: Right, you think there’s a test case you could build similarly like measure the box dimensions?
Paul: Similar to the last one. Yeah, exactly.
Kevin: But just in general if you as a browser vendor were implementing that feature from scratch is there room for a standard API for advertising support for features like this? Like it’s an HTML entity, it’s really an invisible character that affects text flow.
is an entity.
Kevin: Yeah, well it’s a Unicode character really; it’s a particular code point that is treated differently.
Paul: Yeah, there’s no API. But an interesting thing is that browsers actually a long time ago they thought of this and they’re like wouldn’t it be great if we created a standardized way of asking your browser if there’s support for something, and so they introduced the
hasFeature method. And so I think it’s on
navigator, so it’s
window.navigator.hasFeature and then you’re like
hasFeature('SVG'), and it’ll be like oh, yeah, true, I totally support SVG.
Paul: But what we found out, I’ve spoken to Dmitry Baranovskiy of Raphaël because most commonly you see
hasFeature associated with SVG aspects, and so I’m like “If we want to know if SVG filters are supported, can we rely on the response from
hasFeature?”, and he’s like “Absolutely not.” And so basically we can’t really trust the browser to accurately tell us if they support something or not, and we kind of don’t want to trust them; they might say that they support
border-radius, but you know, don’t exactly support everything that we want yet, and so I think authors have a different idea of support than browser vendors do, and I think that’s okay, in many cases they’re a lot more rigorous than what authors expect out of them.
Kevin: So in a way Modernizr, even if it could ask the browser it’s not going to. It would rather say “Prove it. Render this.”
Paul: Yeah, exactly. Yeah, we want to see the proof. (laughs)
Kevin: (Laughs) Cool. Well, this is quite a laundry list; I hope it starts to get shorter quicker than it continues to get longer in the very near future.
Paul: Me too, me too.
Kevin: Thanks for putting it together. You are a fellow podcaster; I’d love to give you a chance to plug your podcast.
Kevin: Great! You can find Paul Irish at paulirish.com or you can follow him on Twitter @paul_irish. Thanks for being with us today Paul.
Paul: Thanks a lot, Kevin, this was fun.
Kevin: And thanks for listening to the SitePoint Podcast. If you have any thoughts or questions about today’s interview, please do get in touch. You can find SitePoint on Twitter @sitepointdotcom, and you can find me on Twitter @sentience. Visit sitepoint.com/podcast to leave a comment on this show and to subscribe to get every show automatically.
This episode of the SitePoint Podcast is produced by Karn Broad and I’m Kevin Yank. Bye for now!
Theme music by Mike Mella.
Thanks for listening! Feel free to let us know how we’re doing, or to continue the discussion, using the comments field below.