Support CSS variables #1128

Closed
nex3 opened this Issue Feb 23, 2014 · 39 comments

Comments

Projects
None yet
10 participants
Contributor

nex3 commented Feb 23, 2014

CSS Variables introduces the <any-value> production, and Sass should support it.

This production introduces some serious questions about how Sass should parse it. It's general enough to allow practically any string, which means that treating it as a normal property would break CSS compatibility. For example, var-foo: 1 +; is valid CSS, but currently Sass would fail to parse it. Fundamentally, we need to decide what balance to strike between compatibility, programmability, and user expectations. Here are several options:

  1. The most compatible option would be to parse it exactly as specified in CSS and make no changes. For example, var-foo: $var would emit var-foo: $var literally, without replacing $var with its Sass value. This would make it impossible to assign variable values programmatically, though, as well as seriously violating user expectations.
  2. The most programmable option and the option that would be least surprising to users would be to parse these as any other property. This would be a much larger break with CSS compatibility than we've done before, though, which itself violates the user's expectation that all CSS is valid SCSS.
  3. We could meet somewhere in the middle by allowing the use of #{} and possibly a single variable in <any-value> productions. This violates both compatibility, since $var is a valid CSS value that a user's JavaScript might theoretically use, and user expectations, since e.g. var-foo: $var1, $var2, $var3 won't work as expected. However, it will support most valid CSS and will allow variables to be created with mixins, albeit possibly with an ugly intermediate variable.
  4. We could try to parse the value as a plain SassScript value, and if it fails to parse treat it as an unparsed. This would mean that any syntax errors would be difficult to track down, and poses more serious compatibility issues than option 3, since var-foo: 1 + 2 will be treated very differently in Sass than in raw CSS.

I'm not sure what the best option is. If I had to choose now, I'd probably lean towards option 3, but I don't really like any of them.

Contributor

nex3 commented Feb 23, 2014

@tabatkins Is there any chance we can get the spec to change to something more preprocessor-friendly? It would be possible to make the variable values something that's a superset of all valid property values -- something like what Sass's static value parser parses -- without making practically any string valid. Users who want non-CSS values could just put them in a string. For example:

var-foo: "if(x > 5) this.width = 10";

nex3 removed the Feature label Feb 23, 2014

We can't make it sufficiently preprocessor-friendly (read: staying totally out of the way of whatever syntax niceties you invent) without severely damaging the "use custom properties to invent your own shit and parse it with JS" use-case.

I suggest making all the normal SASS stuff work inside of custom props, just like normal. To help people who are trying to write something literally in there, add a magic function that just inserts its contents literally into the stylesheet without parsing. Since var-* values still need to match braces and whatnot, this'll be safe. Like:

var-foo: $bar; // Substitutes in the $bar SASS variable.
var-foo: literally($bar); // Sets the variable to literally "$bar".
Contributor

nex3 commented Feb 24, 2014

We can't make it sufficiently preprocessor-friendly (read: staying totally out of the way of whatever syntax niceties you invent) without severely damaging the "use custom properties to invent your own shit and parse it with JS" use-case.

Why is this? Why can't JS parse the value from a string literal, like in my example?

I suggest making all the normal SASS stuff work inside of custom props, just like normal.

This would be a serious breach of CSS compatibility, which is something we try very hard to avoid. People should be able to use a plain CSS stylesheet as SCSS without having to rewrite it, even if they're parsing a var-* property with JS.

Owner

chriseppstein commented Feb 24, 2014

Ok. So here's my philosophy on this: CSS is a very forgiving language. It recovers (mostly silently) from all sorts of invalid values. One of the values that Sass brings to authors is delivering an error during compilation where CSS would not. Maybe var-add-with-one: 1px +; margin: calc(var(add-with-one) 2px) is valid CSS resulting in margin: 3px, but it is terrible code and I'd rather give an error than support CSS allowing authors to do stupid things as a side-effect of it also allowing authors to do awesome things.

Maybe I'm missing a use case for doing something good with the syntax violations of a standard property but until I see one I think we should continue to parse var-xxx as a standard property. We already have the escape that @tabatkins mentions in the form of unquote("$bar"). I suspect we will never encounter a real world use case where an author is peeved at Sass for giving an error in one of these edge case situations.

Owner

chriseppstein commented Feb 24, 2014

I'm going to raise this issue on the CSSWG mailing list in a few days and see what consensus there is there.

chriseppstein self-assigned this Feb 24, 2014

@nex3 We can't just say "use a string if you go outside [some restrictive subset of all values]" because (a) it's author-hostile, because the boundary between valid and invalid will be pretty non-obvious, and (b) it's future-hostile, because we can add more stuff to CSS in the future that'll violate that subset.

There is probably some subset that would work half-reasonably, but it would be wider than what you want - it would include things that have special meaning in SASS today. So that wouldn't work anyway.

If you want full CSS-as-SCSS compat, you have to just ignore all SASS things inside of var-* properties. (And var() functions, as the fallback arg has the same syntax constraints.) That's your option 1.

I'm with Chris, though - the places where SASS syntax collides with allowable var-* values aren't realistic. Just go with your option 2.

Contributor

nex3 commented Feb 24, 2014

(a) it's author-hostile, because the boundary between valid and invalid will be pretty non-obvious

I don't understand what use-case is likely to cause a user to try to write an invalid variable. Most variables will be storing values that will be used in other properties, which are by definition valid. For the rest, it seems like users familiar with CSS will be more likely to try to expect that values that look like CSS properties are valid than they are to assume that any text at all is valid.

(b) it's future-hostile, because we can add more stuff to CSS in the future that'll violate that subset

When CSS adds new syntax, why can't you add that to the set of valid var-* values? If a user is running an older browser that doesn't support some new syntax, there's no use in being able to assign that syntax to a variable if that variable won't be valid anywhere in the stylesheet.

I'm with Chris, though - the places where SASS syntax collides with allowable var-* values aren't realistic. Just go with your option 2.

The issue with option 2 isn't that user's <any-value> constructions are likely to collide with SassScript. It's that if we parse these values as SassScript, non-colliding constructs that aren't valid in other CSS properties will fail to parse. This means that use-cases that are explicitly called out in the spec, such as parsing custom syntax with JS, will be broken in Sass.

(Let's call custom properties intended for JS processing, rather than use as variables, JS-processed properties.)

I think you're assuming that it's acceptable for all JS-processed properties to take their values as a single string. It's really not. Most of the time you'll want your JS-processed property to look like CSS, which means writing it normally, not as a string. But if you innovate in syntax somehow, and we went with your plan, you'd have to either carefully design your new syntax to stay within the "reasonable CSS" guidelines (difficult, and dev-hostile), or else users of your library will have to remember when they can do unquote values and when they have to quote them (difficult, and author-hostile).

We technically have similar restrictions today, in that there are places that accept <custom-ident>, and the author has to be familiar enough with the ident syntax to write something correctly, but the guidelines for that are really reasonable and easy (start it with a - or a letter, only use dashes, letters, and numbers). If you just write things that look like variable names, or like the kind of names that CSS already uses, you'll be fine, so this isn't hostile in practice.

When CSS adds new syntax, why can't you add that to the set of valid var-* values? If a user is running an older browser that doesn't support some new syntax, there's no use in being able to assign that syntax to a variable if that variable won't be valid anywhere in the stylesheet.

Again, you're discounting the use-case of JS-processed properties. It would be quite bad if a page author could write a valid custom property in one browser, intending it to be consumed by my JS library, but it was thrown out as invalid in older browsers.

The issue with option 2 isn't that user's constructions are likely to collide with SassScript. It's that if we parse these values as SassScript, non-colliding constructs that aren't valid in other CSS properties will fail to parse. This means that use-cases that are explicitly called out in the spec, such as parsing custom syntax with JS, will be broken in Sass.

Ah, gotcha. In that case, how about an inversion of the normal rules? Custom properties are normally parsed as literal CSS; no special SASS parsing happens at all. (Your option 1.) But you have some special flag that means "never mind, this is supposed to be SASS, please interpret it". This flag will be somewhat limiting, in that you won't be able to use values that end up breaking the SASS parser, but thems the breaks.

I already have plans for something similar to this in level 2 of the spec, so you can declare the type of your variable and get some level of processing done for you (and the value-based OM can expose something smarter). The current proposed syntax is a ! value, like var-foo: 5px 5px blue !type(box-shadow);. I have no idea if this idea is stable, though, so you should feel free to invent whatever you want, maybe just a !sass at the end.

Contributor

nex3 commented Feb 25, 2014

But if you innovate in syntax somehow, and we went with your plan, you'd have to either carefully design your new syntax to stay within the "reasonable CSS" guidelines (difficult, and dev-hostile), or else users of your library will have to remember when they can do unquote values and when they have to quote them (difficult, and author-hostile).

I guess my intuition is that JS-processed properties will fall into one of two categories. Either they'll be properties that are explicitly intended to be used as CSS and eventually fed back to the CSS processor, in which case they'll already have to be compatible with the browser's understanding of CSS; or they'll be something completely unrelated to CSS, in which case it makes more sense to use a string than some CSS construction that coincidentally intersects with your use-case. I don't think there's likely to be much middle ground where people want to use new CSS syntax without actually interpreting it as CSS.

I guess there is the use-case of polyfilling a property on browsers where the syntax doesn't exist yet, but in the world I'm suggesting it would be clear to the author of the polyfill that a string was necessary for the same reason that the polyfill was necessary.

Ah, gotcha. In that case, how about an inversion of the normal rules? Custom properties are normally parsed as literal CSS; no special SASS parsing happens at all. (Your option 1.) But you have some special flag that means "never mind, this is supposed to be SASS, please interpret it". This flag will be somewhat limiting, in that you won't be able to use values that end up breaking the SASS parser, but thems the breaks.

This is effectively a variant of option 3, using a flag to trigger SassScript rather than #{} or a variable.

I guess my intuition is that JS-processed properties will fall into one of two categories.

I find it likely that people will use JS-processed properties to just invent new CSS properties for themselves. Most of them will use standard CSS syntax, but some will want to innovate in syntax a bit, and I think that's totally reasonable.

For example, what if they allow a function like calc(), but with more operations allowed? They'll use operations in there that look like math, and which I presume would trigger SASS processing (since it's not wrapped in a calc() function). Or maybe they'll allow math at the top-level, just like SASS, but with their own set of math operations, beyond what SASS offers and/or with a slightly different syntax.

These scenarios are believable and reasonable to me.

This is effectively a variant of option 3, using a flag to trigger SassScript rather than #{} or a variable.

Yes, it's a somewhat more explicit variant of option 3, which avoids some of the pitfalls of option 3 as you've presented it.

Contributor

nex3 commented Feb 25, 2014

These scenarios are believable and reasonable to me.

I agree, but I also think those scenarios are well-supported by a narrower syntax. Writing var-calculcated-width: "fancy-calc(2 ^ 6)" is a little more verbose than writing it without quotes, but not egregiously so. It also explicitly calls out the fact that this property will be processed specially and isn't just a new CSS feature that the reader hasn't heard of yet.

CSS generally does a very good job of calling out when a feature is experimental or otherwise scary. However, if var allows any syntax, it becomes impossible for a reader of a variable declaration with weird-looking syntax to tell if that syntax is part of CSS or external without scouring the stylesheet for references or checking the spec. This makes stylesheets using this feature more difficult to understand, including those that don't use JS-processed properties.

Ultimately, it seems to me that the tradeoff here is between making life harder for users of preprocessors and making it harder for users of JS-processed properties. I contend that even once this spec becomes implemented there will continue to be more preprocessor users for the foreseeable future. I also contend that that the degree to which the existing spec adds difficulty for preprocessor users is substantially higher than the degree to which my proposal adds difficulty for JS-processed property users.

The fact that the library author and the page author both have to know/remember that fancy-calc() requires quoting while other made-up syntax (that happens to be less adventurous) doesn't is precisely the hostility I keep talking about. It's even worse if you only need to quote when you use fancy-calc(), and can omit the quotes otherwise. Ain't nobody going to remember that.

It's apparent that you don't understand just how difficult it is for most devs to learn and understand syntaxes when there are seemingly arbitrary barriers that can be crossed accidentally and easily. Consistency is key in making things easy to understand and use, not special cases or hard-to-learn syntax barriers.

I assert that it's impossible to draw a line in syntax-space between "currently-valid CSS" and "special SASS syntax" that isn't twisty and confusing, especially if you try and do so in a way that preserves CSS's ability to change in useful ways in the future. (And that's ignoring the possibility that CSS might expand into SASS syntax space itself, which would render the task impossible if the semantics aren't identical.)

(I'm not going to try and expand into SASS space, but SASS has a goodly bit of syntax, and so do other preprocessors, and I can't and won't discount the possibility that use the same syntax in future CSS.)

Contributor

nex3 commented Feb 26, 2014

It's apparent that you don't understand just how difficult it is for most devs to learn and understand syntaxes when there are seemingly arbitrary barriers that can be crossed accidentally and easily. Consistency is key in making things easy to understand and use, not special cases or hard-to-learn syntax barriers.

This is precisely why I'm fighting for this change: under the current proposal, users of any preprocessor that tries to maintain CSS compatibility will be subject to exactly the arbitrary barriers you're referring to. This isn't just my problem: preprocessor users are CSS users as well, and you should care about how your decisions affect their experience just as much as you care about any other user of CSS.

Both the current spec and my suggestion will cause some pain; I don't think anyone's disputing that. My claim is that my suggestion will cause less on the whole. The pain of my suggestion affects only users of JS-processed property; the pain of the current spec affects all users of variables with preprocessors, since it causes inconsistency in how they're handled relative to normal properties (which as you rightly point out makes it hard to understand and use).

In addition, my suggestion will only cause pain to users of JS-processed properties in the specific case where there's not a clear distinction between custom syntax and CSS syntax. This is a case that's already painful, since it forces users to contend with another arbitrary barrier of the sort you call out: understanding which syntax works in which var-* declarations and which can be used in normal properties.

I assert that it's impossible to draw a line in syntax-space between "currently-valid CSS" and "special SASS syntax" that isn't twisty and confusing, especially if you try and do so in a way that preserves CSS's ability to change in useful ways in the future. (And that's ignoring the possibility that CSS might expand into SASS syntax space itself, which would render the task impossible if the semantics aren't identical.)

The problem is that this isn't stepping on specific Sass syntax, it's stepping on all theoretical preprocessor syntax. When CSS expands in a way that overlaps with existing syntax, we may grumble about it but we'll move out of the way. But in this case we can't do that, because the syntax is so wide it overlaps with everything.

This is precisely why I'm fighting for this change: under the current proposal, users of any preprocessor that tries to maintain CSS compatibility will be subject to exactly the arbitrary barriers you're referring to. This isn't just my problem: preprocessor users are CSS users as well, and you should care about how your decisions affect their experience just as much as you care about any other user of CSS.

Both the current spec and my suggestion will cause some pain; I don't think anyone's disputing that. My claim is that my suggestion will cause less on the whole. The pain of my suggestion affects only users of JS-processed property; the pain of the current spec affects all users of variables with preprocessors, since it causes inconsistency in how they're handled relative to normal properties (which as you rightly point out makes it hard to understand and use).

That's not all; your suggestion also impairs CSS itself, as it requires us to define a line across syntax space, which segments "current CSS" from "all SASS (and other preprocessor) syntax", and then never cross that in the future. If we do cross it, it'll cause just as much pain for you.

Further, you really underestimate the pain here from your suggestion. Learning arbitrary syntax distinctions is hard. There's no simple rule to learn; rather, it's a whole bunch of grammar you have to internalize.

The current pain, which is just that SASS syntax doesn't work in var-* properties (unless you turn on some flag somehow) is conversely very easy to learn and memorize. It's worse than not having to memorize anything at all, but if you gotta memorize something, a clean easy segmentation like that is about the best you can hope for.

In addition, my suggestion will only cause pain to users of JS-processed properties in the specific case where there's not a clear distinction between custom syntax and CSS syntax. This is a case that's already painful, since it forces users to contend with another arbitrary barrier of the sort you call out: understanding which syntax works in which var-* declarations and which can be used in normal properties.

Nope, this is easy - it's the difference between "I'm setting a variable" and "I'm using a property that some JS lib will deal with". The two use-cases use the same prefix, because they're functionally identical in browser behavior, but I think they're quite easy to separate mentally in practice.

The problem is that this isn't stepping on specific Sass syntax, it's stepping on all theoretical preprocessor syntax. When CSS expands in a way that overlaps with existing syntax, we may grumble about it but we'll move out of the way. But in this case we can't do that, because the syntax is so wide it overlaps with everything.

This is precisely why I can't do what you say - it's a problem with overlapping with all preprocessors. We can't just draw a line between "current CSS" and "current SASS", we have to draw something that also separates us from "current LESS"/etc, or else we're causing the exact same problem for them as well.

Rather than speculatively limit future CSS evolution in a complex, hard-to-understand way, it's better to adapt as suggested here, and have the preprocessor always interpret variables literally unless you flip a flag on the property. (Putting the flag on the right side of a ! is safe, because the syntax of var-* disallows use of a ! in the value. It's always interpreted as a proper bang-flag, not a part of the property value.)

Contributor

nex3 commented Feb 27, 2014

That's not all; your suggestion also impairs CSS itself, as it requires us to define a line across syntax space, which segments "current CSS" from "all SASS (and other preprocessor) syntax", and then never cross that in the future. If we do cross it, it'll cause just as much pain for you.

I don't understand this claim. What I'm suggesting is that you define <any-value> to be a superset of all valid CSS values, and expand it when additional CSS syntax is added. If new syntax, and thus <any-value>, starts overlapping with Sass, we'll move out of the way. I understand this means that JS-processed properties will have to be careful to use widely-compatible syntax, but staying within browser compatibility boundaries is something that CSS users are very familiar with as it stands.

It also seems like the existing spec has plenty of its own "arbitrary barriers that can be crossed accidentally and easily". Using the spec's example of JS-processed properties that evaluate JS, users have to know to avoid things like // comments followed by *, using ! to mean "not", and a function named url() (depending what its arguments are). I assume you've considered these cases already; I just mean to bring them up to point out that clearly some level of syntactic inconsistency and pain is acceptable.

Further, you really underestimate the pain here from your suggestion. Learning arbitrary syntax distinctions is hard. There's no simple rule to learn; rather, it's a whole bunch of grammar you have to internalize.

Users will have to learn these distinctions only if they're using JS-processed properties, and then only if the specific JS processor does a poor job of designing its property space. I'm not saying that will never happen, but for the most part properties would expose well-defined and widely-compatible syntaxes.

I guess I just don't understand the sort of JS processor you're envisioning. In my suggested world where only CSS-compatible syntax works, what processor would guide people away from using that syntax? How would the user end up experiencing the pain you're describing?

Rather than speculatively limit future CSS evolution in a complex, hard-to-understand way, it's better to adapt as suggested here, and have the preprocessor always interpret variables literally unless you flip a flag on the property. (Putting the flag on the right side of a ! is safe, because the syntax of var-* disallows use of a ! in the value. It's always interpreted as a proper bang-flag, not a part of the property value.)

Requiring a special flag for SassScript in variables is not a user-friendly solution. It's an option that we would consider, but we would likely opt to avoid CSS compatibility in this case for the sake of our users.

I am in favor of contents of var-*: ; interpreted as a string. Maybe #{} can be used inside CSS vars if any Sass variables or arguments need to be passed through.

There aren’t always really experienced users who use this kind of stuff. Many people copy and paste CSS from all over into their stylesheets and assuming they know how to fix edge cases isn’t that great.

I definitely plan on porting some of my Sass functions over to CSS vars with JS processing. I would much rather specify what inside of var- interpreted as a string than interpreted as Sass by default.

Note that we made a last-minute change to the syntax, so that custom properties are now named --foo. This is definitely stable now, because it's what Firefox is shipping.

Owner

chriseppstein commented Mar 28, 2014

@tabatkins Thank you for the update.

HugoGiraudel referenced this issue in alsacreations/KNACSS Apr 1, 2014

Closed

Au programme pour KNACSS v3.0 #48

nex3 changed the title from Support the <any-value> production to Support CSS variables Apr 25, 2014

Sorry, didn't see what state this ended up in. I'm still not seeing support in 3.3.8. Forgive me if I've missed it somewhere.

❯ sass index.scss index.css
Syntax error: Invalid CSS after "   -": expected number or function, was "-navy: hsla(206..."
        on line 3 of _colors.scss
        from line 1 of index.scss
  Use --trace for backtrace.

❯ sass -v
Sass 3.3.8 (Maptastic Maple)
Contributor

nex3 commented Jun 12, 2014

The issue is still open, which indicates that the feature is not yet supported.

Ah, gotcha. Thanks.

chriseppstein removed their assignment Jul 11, 2014

@nex3 nex3 added a commit that referenced this issue Jul 11, 2014

@nex3 nex3 Support "--suffix" for selector-append.
This has a side effect of supporting most "--foo"-style identifiers.

Closes #1310
See #1128
1dbbbdf

Guys, this should be top priority thing. Since you're declaring full CSS compatibility you're lying already.
Moreover, since Polymer 1.0 uses custom CSS mixins, it doesn't seem to be possible to write in SCSS at all:

--some-mixin : {
    font-size   : 10px;
    font-weight : bold;
};

Code above whould be compiled to exactly the same thing. It seems that check for -- prefix should be simple enough to implement, and if -- prefix found - leave it as is on current level.

I got it working in this way, though it is quite ugly and doesn't simplify anything at all:

--some-mixin : #{'{
    font-size   : 10px;
    font-weight : bold;
}'};
Contributor

nex3 commented Aug 14, 2015

@nazar-pc Unless you're willing to contribute work to the project, please try to avoid decrees about what our priorities should be.

chriseppstein added the Bug label Oct 7, 2015

Owner

chriseppstein commented Oct 7, 2015

@nex3 I don't like any of our options here but let's figure out a game plan for how we're going to support this. Failure to address this in the next few months will start to cause users to abandon Sass for alternatives that work.

Here's some options that I see:

  1. Don't allow interpolation or SassScript in a --var property. Thus ensuring maximal compatibility with CSS.

    If we do this, I think we should create a parser-level function called sass-script(...) within which any arbitrary sass script expression is allowed. We will parse any --var property without any SassScript processing unless the value is set to a sass-script(...).

  2. Treat --var properties as normal css properties that works with SassScript, interpolation, etc. For most users, this will be what they want.

    If we do this, I think we should introduce a new directive @raw or something similar which basically turns Sass parsing off and parses everything inside as a string that gets passed along to the css file. This has the side benefit of being an escape hatch for any future CSS incompatibilities.

  3. Like other places in Sass, allow only interpolation when access to SassScript is needed.

    If we do this, We should allow interpolation to be escaped (probably \#{ and a corresponding \} or maybe a double the hash sign ##{ ... }) and when it is, it is passed through to css untouched. This accounts for the use case where some custom property syntax tramples on Sass's interpolation syntax.

Other suggestions welcome, these are just at the top of my head.

nex3 was assigned by chriseppstein Oct 7, 2015

@chriseppstein To have a more explicit validation, All this will enable a state where Sass can accept the following to work correctly, right?

:root {
  --foo: {
    color: red;
   }
}

my-thing {
  @apply(--foo); // or @apply --foo;
}
Owner

chriseppstein commented Oct 8, 2015

@lozandier option 2 would not work with that code. For that option it would be the following:

:root {
  @raw {
    --foo: {
      color: red;
     }
  }
}

my-thing {
  @apply(--foo); // or @apply --foo;
}
Owner

chriseppstein commented Oct 8, 2015

After thinking more, I'm leaning towards option 3.

nazar-pc commented Oct 8, 2015

Second option is really broken, since CSS variables can be defined in other places and override value in runtime, so SASS just can't know what will happen.
Option 3 is fine for me.

Owner

chriseppstein commented Oct 8, 2015

@nazar-pc The @raw directive would work in any location. I don't think you understood the proposal for that option.

nazar-pc commented Oct 8, 2015

OK, I see.
Anyway, I can't agree with:

For most users, this will be what they want.

Polymer, for instance, encourages to expose support for variables and mixins to customize appearance of custom elements. This means that in most cases there will be no actual definition for variable in scope where it is used. So generally for compatibility reasons it is better not to treat CSS variables as SASS variables. CSS variables are much more powerful and such default behavior will just force many people to put a lot of @raw all over the place. Anyone who needs just simple variables already use them with existing syntax.

Contributor

nex3 commented Oct 9, 2015

I agree that option 3 is the best. It sucks that it won't work like other properties, and it sucks that it's breaking the superset rule, but I think it's the best compromise available.

Unfortunately, we kind of accidentally started supporting -- property names in 3.4.0 but parsing them as normal properties, which means that this will require a deprecation process and probably won't land in full until 4.0. Because this is an important feature to support, we should make sure to put out a 4.0 alpha with full support quickly.

Contributor

xzyfer commented Oct 13, 2015

If the assumption below is correct I would prefer to back @tabatkins !sass suffix suggestion, which would allow us to continue being a super set of CSS.

:root {
  --foo: {
    color: red;
   } !sass;
}

The assumption being that the UA's parser will hit the unrecognised ! and bail out until it reaches the ; or }. Not sure if this is how things work in this case, and I don't know that any UAs support this feature to test it. Any chance you can confirm or deny this behaviour @tabatkins?

Owner

chriseppstein commented Oct 13, 2015

If the assumption below is correct I would prefer to back @tabatkins !sass suffix suggestion, which would allow us to continue being a super set of CSS.

For my tastes, being a 100% absolutely pure superset of CSS even if that corner case makes the 99% use case annoying is not worth it. Beyond CSS values the primary use case demonstrated is javascript syntax. #{} is not a syntax in either of these languages (except if it were used in a string) so by allowing it to be used and also escaped we are optimizing for the 99% use case but not making the work around especially onerous. If this ever affects a user their workflow will be "Get an error, realize it's an interpolation, google for how to escape it, move on." I'm ok with this -- errors are a better workflow than all the failure scenarios that users will hit when #{} just fails silently for them because they didn't add a !sass suffix.

Contributor

nex3 commented Oct 16, 2015

I agree with everything @chriseppstein said.

Me too, FWIW.

donny-dont referenced this issue in less/less.js Dec 5, 2015

Open

CSS @apply #2715

ebidel commented Jan 22, 2016

/sub

Draccoz commented Feb 17, 2016

I've read briefly all the above and still miss 1 use case.
What if developer creates a SASS mixin to be used inside of SASS, but then will want to export that to be used outside (as CSS mixin). Ideally that would look like:

@mixin my-mixin {
  ...
}

:host {
  --my-mixin: {
    @include my-mixin;
  }
}

Sadly, none of the above would work, while this would be used a lot (I was actually in need of such thing myself). Any ideas if that will be possible and eventually when?

Contributor

nex3 commented Feb 19, 2016

@Draccoz Your code as written will almost certainly not work. Your --my-mixin declaration is valid plain CSS, and we want to limit the degree to which we step on plain CSS syntax as much as we possibly can. If we want to support people injecting statement-level CSS into custom properties—which I agree seems useful—we need to find a way to do it within #{}.

We've already talked about treating block-level CSS as a first-class object in #1582. Once that's in place, it would be a short step to add a function that converts a variable containing CSS into a string that you can interpolate here.

chriseppstein added this to the 3.5 milestone Mar 11, 2016

@nex3 nex3 added a commit that referenced this issue Mar 28, 2016

@nex3 nex3 Deprecate SassScript in CSS variable values.
See #1128
b671122

@nex3 nex3 added a commit that referenced this issue Mar 28, 2016

@nex3 nex3 Add support for the full CSS variable syntax.
Closes #1128
8247d55

nex3 closed this Mar 28, 2016

@nex3 nex3 added a commit that referenced this issue May 6, 2016

@nex3 nex3 Add a feature flag for custom properties. 2b4f5d6

@nex3 nex3 added a commit that referenced this issue May 6, 2016

@nex3 nex3 Add a feature flag for custom properties. ef3d4b0

eeue56 referenced this issue in rtfeldman/elm-css Sep 19, 2016

Closed

CSS Custom Properties #156

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment