6

Following Eric Bidelman's Google I/O presentation yesterday, which touched on the subject of @supports, I figured I'd start playing with it in Chrome Canary. However, it's raised the obvious question:

What is the best way to check whether a browser supports @supports using only CSS?


I'm currently toying with it by simply checking whether display: block is supported. This method works, obviously, but I'm not sure if this is the most practical approach:

body { background:#fff; font-family:Arial; }
body:after { content:'Ek! Your browser does not support @supports'; }

@supports (display:block) {
    body { background:#5ae; }
    body:after { color:#fff; content:'Your browser supports @supports, yay!'; }
}

Here is a JSFiddle demo of this in action.

These attempts do not work (in Chrome Canary, at least):

@supports (@supports) { ... }
@supports () { ... }
@supports { ... }
James Donnelly
  • 126,410
  • 34
  • 208
  • 218

3 Answers3

5

@supports currently only tests property/value combinations, and nothing else. Your other options don't work because none of them are valid (including the last one with just the at-keyword followed by the opening brace!). The property/value pair requirement is dictated by the grammar for @supports, which you can find in the spec.

Simply test for a property/value pair that you know is guaranteed to work across all user agents whether or not @supports is implemented. This (sort of) eliminates the possibility that you'll run into a user agent that implements @supports but not that property/value combination, focusing on its support for @supports instead.

Your given example of display: block will suffice. Your use of the cascade to check if a browser does not implement @supports by overriding declarations within a @supports rule for browsers that do support it is also acceptable (being the only obvious way to do it anyway).

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • Could there be a situation where `display: block` *isn't* included in a CSS implementation? If so, would it be more logical to test against something which would never be part of CSS; something like `@supports not (_:_) {}`? – James Donnelly May 16 '13 at 10:49
  • @JamesDonnelly `@supports not (_:_) {} == @supports not (whateverbutthisdoesntmakeanysenseproprty:5px) {}` so if the property value pair is invalid or property is not valid at all, browser will just assume that it is not yet supported – Mr. Alien May 16 '13 at 10:51
  • 1
    @James Donnelly: Practically speaking, no - I'd rather worry about a browser implementing `@supports` incorrectly. But if you want, you can do that as well. – BoltClock May 16 '13 at 10:52
  • @Mr. Alien: Yes. Of course, you do have to make sure that it doesn't break the `@supports` rule. – BoltClock May 16 '13 at 10:53
  • @BoltClock yap, if the `prop:val` is valid, it won't break..BTW it also checks the valid units for the value, I don't know whether that's case sensitive or not.. like `px != PX`, am sure it won't be... – Mr. Alien May 16 '13 at 10:56
  • 3
    Man I need to earn a 3 digit rep with a K to get my answers to be selected as correct ;) – Mr. Alien May 16 '13 at 11:07
  • @Mr.Alien well, (sometimes - sadly) answers are accepted from the OP. This does not necessarily say something about correctness, usefulness or comprehensiveness of the chosen answer. – Christoph May 16 '13 at 11:29
  • @Mr.Alien your answer is a good reference, but the question asks how to detect `@supports` within a browser, not how to *use* `@supports` within a supported browser. – James Donnelly May 16 '13 at 11:51
  • @JamesDonnelly Did you even read it? :) Read 2nd line in 2nd para – Mr. Alien May 16 '13 at 11:52
  • @Mr.Alien I did read it. You're explaining how `@supports` works (and why my failed tests didn't work), but you're not explaining whether or not that is a practical way to determine `@supports` support. I upvoted your answer because it's a good `@supports` reference. I didn't accept answer because it doesn't answer the question. – James Donnelly May 16 '13 at 12:04
  • @JamesDonnelly `your example is completely fine here` Anyways it's k, I don't want any war here ;) – Mr. Alien May 16 '13 at 12:07
2

David walsh blog has a nice tutorial about @supports Link.

Indeed you JsFiddle work perfectly in Chrome Canary.

Valid syntax for @supports are,

@supports(prop:value) {
    /* more styles */
}

/* Negation */
@supports not(prop:value) {
    /* more styles */
}

/* `or` keyword*/
@supports(prop:value) or
         (prop:value){
    /* more styles */
}

/* `and` keyword*/
@supports(prop:value) and
         (prop:value){
    /* more styles */
}

/* `or`, `and` keywords*/
@supports(prop:value) or
         (prop:value) and 
          (prop:value) {
    /* more styles */
}
Nobal Mohan
  • 466
  • 7
  • 20
2

This will probably won't work, you cannot check whether @supports is supported or not by CSS only, your example is completely fine here, but there's no option for a straight approach here, for example you are using this :

@supports (@supports) {
   /* Styles */
}

Now that won't actually work, may be for Chrome Canary, this is fine @supports but when it goes ahead to check between parenthesis, it fails, why? It expects a CSS property: value pair inside the parenthesis and not any @ rule, it actually checks whether any property is valid or not, even if you replace that with @supports (@font-face) won't work, further down, I'll explain you with a demo

When you use @supports, it comes with a keyword called not to check whether a specific style is supported by the browser or not, if yes, than apply, else apply other...

Example

@supports (-webkit-border-radius: 6px) {
    div:nth-of-type(1) {
        color: red;
    }
}

@supports not (-moz-border-radius: 6px) {
    div:nth-of-type(2) {
        color: blue;
    }
}

Demo (Note : This works only on chrome canary as of now)

Explanation :

@supports (-webkit-border-radius: 6px) will check in Chrome Canary that whether a property called -webkit-border-radius is supported, if yes than go ahead, change the color of first div to red and it does, cuz Chrome Canary does support -webkit properties while the second will fail as Chrome doesn't support -moz prefixed properties, it will paint blue because I am using not here

@supports not (-moz-border-radius: 6px)
        ---^---

Hopefully FAQ

1) Why none of the styles are applied in browser?

That's because your browser doesn't support @supports yet and hence none will apply as browser will just ignore @supports rules


From the W3C

The ‘@supports’ rule is a conditional group rule whose condition tests whether the user agent supports CSS property:value pairs

Mr. Alien
  • 153,751
  • 34
  • 298
  • 278
  • 1
    The demo doesn't actually explain why `@supports (@font-face)` doesn't work... it just explains how to *use* `@supports`, which as mentioned by the OP is irrelevant to the question. – BoltClock May 16 '13 at 12:03
  • 1
    @BoltClock `@supports but when it goes ahead to check between parenthesis, it fails, why? It expects a CSS property: value pair inside the parenthesis and not any @ rule, it actually checks whether any property is valid or not, even if you replace that with @supports (@font-face) won't work` How can I provide him with the demo when @supports only work with property value pair? – Mr. Alien May 16 '13 at 12:03
  • 1
    You're demonstrating the difference between `@supports` and `@supports not` - what does that have to do with `@supports (@font-face)`? Although I guess that is answered by the FAQ bit, but your answer seems pretty confusing. – BoltClock May 16 '13 at 12:14
  • @BoltClock I shown him the demo that how it only works with properties and not `@` rules, further down I explained him how to work with `@supports` having a valid parameter of `property:value` combination, certainly `@font-face` has nothing to do with the demo as it JUST DON'T WORK, so I explained him how it works in the real way so he can't check the way he was trying to, as specified in his question `These attempts do not work (in Chrome Canary, at least): @supports (@supports) { ... }` the intention was to clear how it works and I created a demo to show that – Mr. Alien May 16 '13 at 12:17
  • @BoltClock I guess this is what makes you confused hehe `I'll explain you with a demo` – Mr. Alien May 16 '13 at 12:20