- From: Tab Atkins Jr. <jackalmage@gmail.com>
- Date: Mon, 21 Mar 2011 12:55:21 -0700
- To: www-style list <www-style@w3.org>, Shane Stephens <shans@google.com>, Nathan Weizenbaum <nweiz@google.com>, Chris Eppstein <chris@eppsteins.net>
I recently gave a talk and blogged about a few experimental CSS features that Chrome is playing with. I've already talked about one of them here on the list, CSS Variables, which got a relatively positive reception. Another one, CSS Mixins, has been moving faster in implementation than I anticipated, so I haven't yet had a chance to talk about it despite it starting to land in Webkit patches. So, I'd like to start talking about this feature and whether the CSSWG is interested in pursuing it. A mixin is a block of rules that can be "mixed into" other declaration blocks. This enables you to create chunks of reusable CSS, avoiding duplication of code when you have bunches of otherwise-dissimilar elements that happen to all use a particular thematic grouping of rules. Mixins are used in, for example, SASS <http://sass-lang.com/tutorial.html#mixins>. (Why can't you just add a class to these elements and put the "reusable" CSS in a ruleset targetting that class? While this strategy does the job, it requires you to alter your HTML and sprinkle otherwise-meaningless classes around your page. If you want to change what elements receive the special CSS, you have to change your document, which is an anti-pattern that CSS and Selectors were supposed to solve. Basically, implementing mixins via classes is roughly equivalent to putting "redText" classes in your HTML - it leaks presentational information into your document, rather than keeping it in the CSS where it belongs.) The syntax that we're experimenting with for Mixins is fairly simple - it involves two new @-rules, one at the top-level and one that lives in declaration blocks. The first one declares the mixin, which we're calling a "trait" (name very much temporary). It looks like this: @trait foo { prop: val; prop: val; } The syntax is "@trait", followed by the name of the trait, followed by a declaration block. Traits can also take arguments, which are treated like local variables within the body of the mixin: @trait bar($one, $two) { prop: $one; prop: $two; } (What's the scope of these local variables: dynamic or lexical? The former would allow arguments to percolate down into nested mixins. The latter is a lot simpler to read and reason about. I like lexical scope much more.) (These local variables presumably shadow any global variables with the same name. Do we need a way to access the global var? Assuming lexical scope, the arguments shadow a very localized area, and the argument names are under the control of the same person who writes the CSS in the decl block presumably, so they can just rename if necessary. The var() notation for variables may make this easier by allowing a local() function for accessing arguments.) (Probably we want to allow default values for the arguments as well. This has similar ambiguity problems as the @mixin rule, and should be solveable in the same way.) Within a declaration block, you can invoke a mixin by using @mixin, like so: selector { prop: val; @mixin foo; @mixin bar(red, 5px); } The effect of this is as if you had simply textually substituted the contents of the trait's declaration block at the point of the @mixin rule. Rule overrides happen based on the "virtual position", etc. (There is an ambiguity with the arguments here - variables allow comma-separated values, which would conflict with comma-separated arguments. SASS gets around this by forcing you to enclose comma-separated values in parentheses. Is this reasonable?) On the CSSOM side, Traits would be a new type of CSSRule. I'm not *entirely* sure how the @mixin would be represented, because we haven't yet had to worry about @-rules inside of declaration blocks. I suspect it might involve giving CSSStyleRule a cssRules property, like CSSMediaRule, and listing the @-rules there. Thoughts? ~TJ
Received on Monday, 21 March 2011 19:56:34 UTC