Using CSS 3 on the web today means that, inevitably, some browsers won’t be able to display some elements of your design. Hopefully you’re using progressive enhancement so that your pages still function in less-capable browsers, which might not understand all those fancy transform
rules.
For more complex projects progressive enhancement might even mean turning to a feature-detection library like Modernizr, which will detect and apply CSS classes based on the current browser’s capabilities.
Modernizr is great when you need it, but did you know that soon the browser itself will be able to give you the same information?
Both Opera 12.10 and Firefox 19 (currently in the Aurora channel) support native CSS feature detection through the CSS @supports
rule. CSS @supports
offers the same capabilities of Modernizr — selectively applying CSS based on what the current browser supports — but it does it through much faster native code. Even better, because browsers that don’t support @supports
will just ignore it, you can start using it today.
Opera Software’s Chris Mills recently posted a nice intro to using @supports
which you should read for more details, but here’s an example to illustrate the basic idea:
@supports ( box-shadow: 2px 2px 2px black ) {
.my-element {
box-shadow: box-shadow: 2px 2px 2px black;
}
}
The code above uses @supports
to check for support for the box-shadow
property and then applies a box shadow to browsers that will display it. Of course since many of the features you’d likely be detecting are still prefixed, a more complete example (pulled from the W3C’s @supports page) would look like this:
@supports ( box-shadow: 2px 2px 2px black ) or
( -moz-box-shadow: 2px 2px 2px black ) or
( -webkit-box-shadow: 2px 2px 2px black ) or
( -o-box-shadow: 2px 2px 2px black ) {
.outline {
color: white;
-moz-box-shadow: 2px 2px 2px black;
-webkit-box-shadow: 2px 2px 2px black;
-o-box-shadow: 2px 2px 2px black;
box-shadow: 2px 2px 2px black; /* unprefixed last */
}
}
Now we’re checking for not just box-shadow
but any vendor-prefixed versions of it as well. We’re also not just applying box-shadow
, but also changing the outline color to white, which (assuming a white background) would not be good to do in browsers that don’t support box-shadow
since it would make the outline invisible to the user.
As you can see, @supports
is pretty handy for progressive enhancement and it avoids the overhead of loading a JavaScript library like Modernizr. CSS @supports
also works with operators like not
and or
so that you could write a rule that says the opposite of what we did above. In other words, detect that the current browser doesn’t support box-shadow
and do something else.
CSS @supports
gets even more powerful when you start chaining @support
rules together, which is what Mills does in his post on the Opera Dev center, detecting for animations and transforms to serve one thing to browsers that support 3-D transforms, one to those that only understand 2-D transforms and a third to those that don’t support transforms at all.
So should you ditch Modernizr and go with @supports
? Probably not just yet, but soon. First off, if you’re using Modernizr for more than just CSS detection then obviously stick with it. But, as Opera’s Bruce Lawson notes in a follow-up to Mills’ post, “the reason to use @supports
over Modernizr is performance; functionality that’s built into the browser will always be faster than adding it in script.” Getting rid of Modernizr would also mean eliminating an external dependency, which saves an HTTP request as well.
In fact Modernizr itself plans to defer to @supports
in future releases. If you’d like to have the best of both worlds today, what you need to do is first detect for @supports and then if it’s not available load Modernizr. See Lawson’s post for a code snippet that does just that.