- From: François REMY <francois.remy.dev@outlook.com>
- Date: Sat, 31 Jan 2015 13:56:32 +0100
- To: "'Tab Atkins Jr.'" <jackalmage@gmail.com>, <public-houdini@w3.org>
± De : Tab Atkins Jr. [mailto:jackalmage@gmail.com]
±
± 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?
Hi Tab,
I fully understands this first draft is only a "flex-basis" for discussion, but given it's what I have at hand, I'll comment on the document itself more than on the idea; I'll read the minutes of the next Houdini meetings for ideological matters ^_^
So. I had a look at the specification, but I remained hungry for more after reading it. I know it's not always the role of a specification to tell the "imperative story" of the things it defines, but in this particular case I wasn't satisfied with the "functional story".
As a starter, I would have loved to see a selector matching algorithm which is conforming this specification; I'm interested in particular in how we can implement this in a single-phase matching, if that's possible. My thoughts is that you can't perform this in a single matching phase and will first need to match rules containing @extend rules, modify the "matchable dom" and repeat until no more additional changes is made to the matchable dom.
This means that selector matching now needs to be performed top-down as selector matching for an ancestor may affect what rules match one if its children as a result of the mutated matchable dom; this may harm the parallelization of matching. That being said, maybe some other characteristics of css matching already do so; that's why I would have liked to see this discussed. I also wonder what might be the performance impact (but I guess only a prototype might inform us).
My second thought is this simply isn't going to be easy to create a consistent matchable dom using @extend. I have some examples:
:not(.open) { @extend .open }
.open { @extend :not(.open) }
.a { @extend .b }
.b { @extend :not(.a) }
<div> <e1/> <e2/> </div>
:not(button) + e2 { @extend button }
:nth-last-child(2 of button, e1) { @extend button }
It may also be hard to manage security restrictions:
a:visited { @extend button }
It's maybe possible to resolve those cases in a sensible way, but it may be harder than it looks at first sight when reading the spec.
Happy discussions in Sydney,
François
Received on Saturday, 31 January 2015 12:57:11 UTC