Adobe

decor

Web Platform Team Blog

Making the web awesome

Coming Soon: CSS Feature Queries

Feature Queries are part of the CSS3 Conditional Rules specification, and offer a native method of testing for CSS feature support. You can use Feature Queries to test whether certain CSS rules are supported, and optimize your page for the available set of features. Feature Queries have a number of stable browser implementations in Chrome, Firefox, and Opera, and at least one recent experimental implementation in WebKit. As browser support continues to increase, it’s probably worth taking a look to see if Feature Queries fit into your current projects.

Feature Queries in CSS

Feature Queries look like Media Queries, but test support for CSS property/value pairs rather than display characteristics. As a basic example, you could ask a browser to apply a set of CSS rules if it supports a value of 0 for the margin property.

@supports (margin: 0) { /*CSS to apply*/ }

Let’s move on to a more realistic example. Let’s say you want to use background-blend-mode to colorize a background image, multiplying a color tint over the original grayscale image.

See the Pen Feature Queries + Blend Modes by Adobe Web Platform (@adobe) on CodePen.

body {
  background-blend-mode: multiply;
  background: linear-gradient(rgb(59, 89, 106)
                , rgb(63, 154, 130))
              , url(background.png);
}

Altogether a great effect, right? However, browser support is a bit of a pain. background-blend-mode has relatively wide support, but there are also a good number of browsers where you will not see the correct result. To address non-supporting browsers, we will lay down a base set of functionality – an approximation using a semi-transparent color overlay.

body {
  background: #3F9A82;
  background: linear-gradient(rgba(59, 89, 106, 0.8)
                , rgba(63, 154, 130, 0.8))
              , url(background.png);
}

The above code includes a single-color fallback if the semi-transparent color overlay isn’t supported. Then, using a feature query, we can conditionally update the background if background-blend-mode is supported. A feature query looks just like a media query, using @supports and adding the CSS declaration to be tested inside parentheses.

@supports (background-blend-mode: multiply) {
  body {
    background-blend-mode: multiply;
    background: linear-gradient(rgb(59, 89, 106)
                  , rgb(63, 154, 130))
                , url(background.png);
  }
}

Feature Queries in JavaScript

The Feature Queries specification also provides a JavaScript interface: CSS.supports. We can take the above example, and test for support using JavaScript. If background-blend-mode: multiply is supported, we can add the blend-mode class to the <body> element.

See the Pen Feature Queries + Blend Modes (JS) by Adobe Web Platform (@adobe) on CodePen.

window.onload = function() {
  if (CSS.supports('(background-blend-mode: multiply)'))
    document.body.classList.add('blend-mode');
}
body.blend-mode {
  background-blend-mode: multiply;
  background: linear-gradient(rgb(59, 89, 106)
                , rgb(63, 154, 130))
              , url(background.png);
}

As one further trick, you can also combine tests using logical operators and, or, and not. For example, if you wanted to test that the background-blend-mode and background property values were both supported, you could use either of the following:

@supports (background-blend-mode: multiply)
          and (background: linear-gradient(...), url(...))

or

CSS.supports('(background-blend-mode: multiply) \
              and (background: linear-gradient(...), url(...))');

Feature Queries are almost ready for primetime development. When considering whether to use them, just make sure that they are available in the same browsers as the features you are testing for. Although Feature Queries won’t make the headache of feature testing go away, they will hopefully make the problem a bit more manageable. Try it out, and let us know what you think.

11 Comments

  1. August 22, 2014 at 6:08 pm, Gibran Malheiros said:

    this is fucking awesome!

  2. August 23, 2014 at 9:16 am, Alberto said:

    I was about to write the following comment:
    “That’s cool but not very useful:
    I use modernizr to check if the user is using a older browser that does not support a certain feature, but older browsers are not going to support this feature”

    And then I realized I could just do the inverse process, but still, may not be ideal.

  3. August 23, 2014 at 12:10 pm, Patrick Burtchaell said:

    Nice! This will be so useful in production.

  4. August 24, 2014 at 9:48 am, Sten Hougaard said:

    Will it be possible to nest @media quieries and @supports?

    • August 25, 2014 at 9:54 am, bear said:

      Yes, it is possible to nest media and feature queries. The specification mentions nesting conditional rules in general, but doesn’t have a specific example of these two nesting.

  5. August 25, 2014 at 11:23 pm, Sten Hougaard said:

    Is it required to “ask” concrete style features with a value? Like:
    @supports (background-blend-mode: multiply)
    or will it be possible to “ask” in a more general manner? Like:
    @supports (background-blend-mode)

    • August 26, 2014 at 9:58 am, bear said:

      Yes, the spec currently only supports property/value pairs (margin: 0) rather than also supporting plain properties (margin).

      • August 27, 2014 at 7:46 am, happyWang said:

        a feature that supports plain properties will be useful, we don’t always need a value

  6. August 28, 2014 at 9:03 am, Mathew Porter said:

    This is a fantastic step forward… If only it was in the spec years ago it would be amazing for supporting older browsers. Although that same thought process could be said to lots of recent developments in CSS and HTML rendering my point useless :(

  7. August 29, 2014 at 7:55 am, Matt McClard said:

    Does this work in Dreamweaver?

    • September 01, 2014 at 12:13 am, bear said:

      As far as I know, not yet. I wouldn’t expect them in Dreamweaver until browser support is a little further along.