We Can Have Hack Free CSS With the @unsupported Directive

This post discusses a feature for CSS that does not yet exist.

As a CSS Framework creator and maintainer, it’s become obvious to me that graceful degradation can only get us so far down the path of creating robust designs that work in all browsers. Moreover, CSS parsers are less and less broken, but are increasingly diverse in the list of features they support, making relying on CSS Hacks an impossibility. It is time for the CSS specification to provide feature support that solves the backwards-compatibility problem once and for all.

My One Request for CSS3: The @unsupported Directive

The @unsupported directive processes the corresponding CSS if the CSS feature is not supported. Similarly, the @supported directive has the same syntax but only processes the embedded CSS if the style property is supported.

CSS
.rounded-box {
  border-radius: 5px;
}

@unsupported border-radius {
  /* NOTE: This is not a proper sliding doors implementation. */
  .rounded-box {
    background: #fff url(rounded.png) top left;
    padding-left: 5px;
  }
  .rounded-box span.right-side {
    background: #fff url(rounded.png) top right;
    padding-right: 5px;
  }
}

Feature Queries

The @unsupported directive would accepts a “Feature Query” as its single argument. Feature queries should be quoted except in the simple case of basic property query as seen above.

border-radius
Checks if the border-radius style property is supported.
"div {border-radius}"
Checks if the border-radius property is supported on div elements.
"display: table;"
Checks if the value table is allowed for some element.
"div{display: table;}"
Checks if the value table is allowed for the display property on div elements
"div,span{display: table;}"
Checks if the value table is allowed for the display property on div and span elements
"div{display: table;}", "div{display: table-cell;}"
Checks if the div elements allow both display:table AND display:table-cell
"div{display: table;}" | "div{display: table-cell;}"
Checks if the div elements allow EITHER display:table OR display:table-cell

Only element selectors may be used in a feature query selector.

Working with Legacy Browsers

The parsing rules of CSS dictate that unsupported features should be ignored, which is exactly the opposite behavior we’d like to have for the @unsupported directive. To work around this, I also propose a live-comment syntax to allow the @unsupported directive to be used to target legacy browsers that do not support the @unsupported directive (not unlike the conditional comments of IE). Browsers that understand the @unsupported directive would also need to parse these live comments and ignore the content between them if they support the feature. Legacy browsers would not see the @unsupported contents because they are within a comment, but they would see the directive’s contents. Example:

CSS
.rounded-box {
  border-radius: 5px;
}

/*@unsupported border-radius {*/
  /* This is seen by browsers that don't support @unsupported.
     This is ignored by browsers that support the feature query.  */
  .rounded-box {
    background: #fff url(rounded.png) top left;
    padding-left: 5px;
  }
  .rounded-box span.right-side {
    background: #fff url(rounded.png) top right;
    padding-right: 5px;
  }
/*}*/

What Do You Think?

I can’t petition the W3C directly, I don’t work for a member company, but the CSS3 specification needs some thought about how developers are supposed to gracefully take their applications forward. The specific syntax of feature queries still need some serious thought and discussion. I’m curious to see what the community thinks about this idea and if there’s a better syntax or approach.