Feature Queries, a hypothetical CSS vendor prefix alternative

Web browsers can be pretty self-absorbed. Vendor prefixes (and conditional comments before them) are narcissistic solutions that favor browser detection over feature detection, contrary to our industry’s best practices. As a result, browser makers have gotten themselves in a bit of a pickle.

To be fair, their intentions were (and still are) good. Our designs have benefited from proprietary or burning-edge CSS features, most of which would be difficult or impossible to implement without vendor prefixes.

The problem is, we got here by asking the wrong questions.

We shouldn’t care about whether or not our design is viewed in a “WebKit” browser, Firefox or Internet Explorer. We also shouldn’t care about whether or not a feature is in “alpha” or “beta”, distinctions too broad and subjective to be of much practical use.

Here’s what we really need to know:

  1. Does the browser support this feature?
  2. Can the browser successfully parse the syntax I’m using?

Media queries already work this way. The browser only renders the styles therein when the query is true. Because CSS is fault-tolerant, browsers that don’t support media queries will ignore the ruleset entirely.

What if we adopted a similar syntax for feature detection? Let’s use our imaginations and dive in to this 100% fictitious, hypothetical example:

@feature (transition) {
    .example {
        transition: background-color .25s ease-in-out;
    }
}

The .example ruleset will only be rendered if the browser supports the @feature query and the transition property.

By implementing the not operator from media queries, we could get hardboiled and only use queries for fallbacks:

.example {
    transition: background-color .25s ease-in-out;
}
@feature not (transition) {
    /* Fallback rules */
}

If these (again, hypothetical) feature queries could be extended to test values as well as properties, we could test for differences in syntax:

/* -moz syntax */
@feature (linear-gradient(left, white, gray)) {
    .example {
        background-image: linear-gradient(left, white, gray);
    }
}
/* -webkit syntax */
@feature (linear-gradient(linear, left center, right center, from(white), to(gray))) {
    .example {
        background-image: linear-gradient(linear, left center, right center, from(white), to(gray));
    }
}

This idea obviously has its flaws. In the latter example, things can get pretty verbose (not to mention repetitive). Also, it feels a little unintuitive to group rules by feature instead of by element or media (even though Modernizr already encourages this, albeit much more succinctly). In spite of these flaws, feature queries would allow us to design for features instead of browsers, which feels like a step in the right direction.

Then again, I may be woefully misguided. Thoughts?

Responses

matt lohkamp says

huh, I think you’re particularly on the right path with the ‘@feature not’ form – the others are useful, but you’re right, I could see them getting a little too repetitive. kinda like wrapping everything in try/catch statements, right?

Responded

Tyler Sticka says

It definitely could get repetitive, depending on your stylesheet. If you use an edge feature only once, vendor prefixes would be leaner. But if you use a particular feature multiple times throughout your stylesheet, the extra line or two to test for support would quickly be eclipsed by all the space you save not repeating every rule 3-5 times.

Responded

Rob Wierzbowski says

I think you’re missing the point of vendor prefixes: they’re there in large part to sandbox different applications of the same css property and help us try out new css without having to browser detect. In a simplified example, Modernizr (feature detection) can tell you if a browser supports box shadow, but can’t tell you if the browsers implement the box shadow syntax in the same way as its peers, if the box shadow is brand new and extra buggy in Firefox but totally safe and mature in Chrome, or if Safari oddly renders box shadow twice as dark as IE. The non-prefixed property is there for when the spec is stabilized and browsers are implementing things consistently.

That’s the problem with the mozilla/webkit prefix mashup: deciding which browser implementations of less mature css properties we’re willing to use in our sites is no longer in our control at the css level.

Responded

Tyler Sticka says

That’s a great point, Rob. My definition of consistency in this post was focused primarily on syntax and not on visual implementation, neither of which should be discounted.

That said, I feel you’ve inadvertently justified two-thirds of my proposed solution. Feature queries would allow for Modernizr-style feature detection (see example 1) and for testing differences in syntax (example 2). It does lack the ability to detect the current browser, but I believe this to be a lesser concern because:

  1. Several “mature” CSS properties without vendor prefixes suffer from cross-browser inconsistencies as well.

  2. Vendor prefixes and Modernizr currently allow us to do browser detection in CSS and CSS feature detection in JavaScript. That seems backwards to me. Why not detect CSS feature support in CSS and the client’s browser using client-side scripting?

These opinions are still evolving, though, and I greatly appreciate the discourse.

Responded

Leave a response

Your email address won’t be published. You can use some HTML or Markdown.