Proposal for adding @extend to CSS

Several years ago, the Sass preprocessor adding the @extend rule,
which lets you declare that one selector "extends" another base
selector, so that any rules that apply to elements matched by the base
selector also apply to elements matched by the extending selector.

For example, you can "extend" a .error class with a .serious-error
class, easily applying all the basic .error styling to your
.serious-error elements as well.  This lets you avoid duplicating
anything - you don't need to put class="error serious-error" in your
HTML, or ".error:hover, .serious-error:hover" in your CSS selectors,
or manually copy over the .error styling into .serious-error ruels.

In August 2012, dbaron suggested something extremely similar
<https://lists.w3.org/Archives/Public/www-style/2012Aug/0363.html>,
based on a discussion with Yehuda Katz and Nicole Sullivan (Nicole
provided the original inspiration for @extend in Sass).  I pointed out
that this was just @extend with a different, slightly more awkward,
syntax.

In January 2013, Philip Walton also proposed something extremely
similar <https://lists.w3.org/Archives/Public/www-style/2013Jan/0241.html>,
and I again pointed out that this was just @extend with a more awkward
syntax.

I finally got together with Chris Eppstein, one of the primary
maintainers of Sass, and banged out a spec for @extend as a CSS
feature.  Natalie Weizenbaum, the creator and primary maintainer of
Sass, has reviewed it and found it acceptable, so I now present it to
the group for review:
<http://tabatkins.github.io/specs/css-extend-rule/>

This proposal adds the @extend rule, based on the semantics defined by
Sass.  It also adds the "placeholder selector", which is similar to a
class selector, but no aspect of the DOM can cause an element to match
it.  Experience with Sass shows that this is extraordinarily useful in
practice, as it lets you safely design styles without having to worry
about accidentally clashing with an existing classname, and then just
@extend elements into matching it.

To be precise, the semantics of @extend is that it causes elements to
act as if they have whatever additional features are necessary to
match the extending selector.  For example, in the following rule:

```
.serious-error {
  @extend .error;
  font-weight: bold;
}
```

Any element matching .serious-error is treated as if it also has the
.error class (as that's what's required in order to match the .error
selector).  All selectors in the document that mention .error now
potentially apply to .serious-error elements as well.

There are more examples in the document, so I won't reproduce them here.

The @extend rule has been one of the most popular and useful features
in Sass since its introduction.  It can only be imperfectly
implemented in Sass via selector rewriting (a naive implementation
runs into combinatorial explosions; Sass uses heuristics to tell which
selectors are "most likely" to be important and only exports those)..
We can implement it perfectly in the browser by actually affecting
matching, and bring this super-popular tool to millions of authors
using plain CSS.

Thoughts?

~TJ

Received on Saturday, 31 January 2015 00:07:29 UTC