Directives should allow interpolation #46

Closed
thedjinn opened this Issue Feb 26, 2011 · 27 comments

Projects

None yet
@thedjinn

I want to create an SCSS mixin which makes me some @-webkit-keyframe sections. I can do the following:

@mixin animate($name) {
    @-webkit-keyframes foo {
        0% { color: red; }
        100% { color: blue; }
     }
}

This works fine. However, as I want the $name variable to be inserted as the animation name, I replace the second line with:

@-webkit-keyframes $name {

Sass doesn't understand this and gives a parse error:

Invalid CSS after "...bkit-keyframes ": expected "}", was "$name {"
@chriseppstein
Member

In selectors and normal directives, you need to use interpolation #{ ... } to insert scripted values. E.g.

@-webkit-keyframes #{$name} {
@thedjinn

Yes, this was something that popped up on my mind too. However, that doesn't work either! The error now is:

Invalid CSS after "...bkit-keyframes ": expected "}", was "#{$name} {"

I think there is an error in the way the @-webkit-keyframes is parsed. Using the code outside of a mixin (with a global variable) yields another error:

Invalid CSS after "...bkit-keyframes ": expected selector or at-rule, was "#{$name} {"
@chriseppstein
Member

hmm. my mistake, I guess we don't interpolate unknown at-rules. I reopened the issue.

@nex3
Collaborator
nex3 commented Apr 24, 2011

This is something we should support, but I don't think it's important enough to fit into 3.1.

@rbq
rbq commented May 31, 2011

To me this seems to be quite important. According to #79 using the media bubbling feature currently requires repeating your selectors over and over.

I'd like to do something like this instead:

@media ($iphone) and ($ipad) {
  ...
}

@media (iphone) {
  ...
}

@media ($ipad) and ($desktop) {
  ...
}
@chriseppstein
Member

Ah the issue is that this only works in .sass files. The SCSS parser is choking before interpolation runs.

@jacobrask

Just started out with SASS and immediately stumbled upon this. Not sure if I should report a separate bug for:

$mq-wide: "@media (min-width: 1280px)";
#{$mq-wide} {
    // code
}

The error I get is

Invalid CSS after "": expected selector, was "@media (min-wid..."

@yarmand
yarmand commented Aug 3, 2011

Just impossible to do properly dynamic responsive without this one implemented.

I use this workaround in mentime :

$global-width: 1200px
. container
  width: $global-width
  ...
@if $skeleton_global_width > 1100
  @media only screen
    @media (min-width: 960px)
      @media (max-width: 1009px)
        . container
          width: 960px

I'd rather do

@media only screen
  @media (min-width: 960px)
    @media (max-width: $global-width - 1)
      . container
        width: 960px
@ChrisNewton

Another vote for this one on responsive web design grounds, please.

It is very common to want a decision based on @media screen together with a min-width or max-width to select between layouts. Typically, we would then use lengths based on that same width value to size elements within the layout:

#responsive-page-element {
    width: $default-layout-width;

    @media screen and (min-width: $important-width-value) {
        width: $foo * $important-width-value + $bar - $baz;
    }
}

Often, there will be several such @media blocks for each responsive element, based on a series of widths where the layout changes.

Not being able to interpolate the length in the media query here is a significant problem, forcing repetition of those important width values throughout a SCSS file, or across a whole set of files for a larger site instead of storing all core data like that in a single file and @importing it elsewhere.

It might be considered a different issue depending on how the parser works, but for what it's worth, I agree that it would be very nice to interpolate an entire media query as well:

@media $ipad {
    // ...
}

For me personally this would have a much lower priority, though, because it is far less likely in practice that something like @media screen is going to change during routine development work.

@atrefz
atrefz commented Oct 15, 2011

The following (to create the different prefixed keyframes for all browsers) is not possible either :/

@mixin animate($prefix) {
    @#{$prefix}keyframes foo {
        0% { color: red; }
        100% { color: blue; }
     }
}
@pyrsmk
pyrsmk commented Oct 21, 2011

I agree too, it's a must-have behavior for responsive designs and flexible development...

@ZeeAgency

+1
Would love to do something like that...

@for $i from 1 through 4 {
    @media only screen and (max-width: $i * $width) {
        width: $width;
    }

}
@jgarber
jgarber commented Jan 11, 2012

+1

I'm trying to do:

@media only screen and (min-width: $mobile-nav-width) 

But I get

Line 39: Invalid CSS after "...nd (min-width: ": expected expression (e.g. 1px, bold), was "$mobile-nav-wid..."
@chriseppstein
Member

this is a blocker for building proper animation and media support.

@nathggns

Any plan to fix this?

@chriseppstein
Member

Yes.

@nathggns

How soon? This is really bugging me (I'm trying to make a keyframes mixin).

@chriseppstein
Member

It'll be fixed in 3.2. As a work around, you can do this in a .sass file -- this bug only affects the .scss syntax

@nex3 nex3 added a commit that closed this issue Jan 19, 2012
@nex3 nex3 Merge branch 'media-interp'
Closes #46
5f86952
@nex3 nex3 closed this in 5f86952 Jan 19, 2012
@nex3
Collaborator
nex3 commented Aug 3, 2012

#429 is tracking interpolation in all unknown directives.

@curtisblackwell

I'm on 3.2.1 and I tried 3.3.0.alpha.3, and i still get the bug using

@mixin keyframes($name) {
  @-webkit-keyframes #{$name} {
    @content;
  }
  @-moz-keyframes #{$name} {
    @content;
  }
  @-o-keyframes #{$name} {
    @content;
  }
  @keyframes #{$name} {
    @content;
  }
}
@steelx
steelx commented Jul 25, 2013

Is it going to get fixed ?

@Snugug
Snugug commented Jul 25, 2013

This has been fixed and has been working for a while. Go to http://sassmeister.com/ and try the following code:

@mixin animation($animation...) {
    @each $prefix in -webkit {
        #{$prefix}-animation: $animation;
    }
    animation: $animation;
}

@mixin keyframe($name) {
    @-webkit-keyframe #{$name} {
        @content;
    }
    @keyframe #{$name} {
        @content;
    }
}

.foo {
    @include animation(foo 30s infininte);
}

@include keyframe(foo) {
    0% {
        background-color: red;
    }
    100% {
        background-color: blue;
    }
}

For those curious, this is the reason I only have -webkit in there. Everywhere else it's unprefixed. Opera 2 versions back has the -o prefix, but opera users tend to be pretty good at upgrading. -moz is totally unneeded.

And, of course, this works with media queries as well. Take a look at Breakpoint's usage of a full media query interpolation.

Finally, for those still curious as to whether or not this is in, well, here's the official changelog about it getting in.

@QuyHP
QuyHP commented Apr 5, 2014

I keep receiving the "Invalid CSS after "@": expected identifier, was "#{$vendor}keyfr...")" error on this code:

@mixin keyframe($keyframe-name) {
    $vendors: (-webkit-, -moz-, -o-, -ms-, '');

    @each $vendor in $vendors {
        @#{$vendor}keyframes #{$keyframe-name} { 
            @include keyframe-content($vendor);
        }
    }
}

If I replace with this

#{'@' + $vendor}keyframes #{$keyframe-name} { 

then I get this error "Invalid CSS after "": expected selector, was "@-webkit-keyfra...")"

Is this going to be fixed?

@lolmaus
lolmaus commented Apr 6, 2014
  1. You're already using an outside mixin and an inside mixin.
  2. There are a limited number of prefixes to support.

Thus, while hoping for your feature request to be implemented, you can use an if-elseif-elseif-elseif-else construct to create prefixed keyframes.

@nex3
Collaborator
nex3 commented Apr 11, 2014

@QuyHP: you're looking for #966.

@srekoble

Is this bug fixed ? I'm on 3.3.7 and I'm trying to use

@mixin keyframes($animation-name) {
  @-webkit-keyframes $animation-name {
    @content;
  }
  @-moz-keyframes $animation-name {
    @content;
  }
  @-o-keyframes $animation-name {
    @content;
  }
  @keyframes $animation-name {
    @content;
  }
}

and I'm getting the same error:

Invalid CSS after "...bkit-keyframes ": expected "}", was "$animation-name {"

In sassmeister seems to work (codepen also)
http://sassmeister.com/gist/bb3f4dd20a9ea0b737ee

I tried to use both simple $ and intrepolation method #{name} but I still get the same error

@chriseppstein
Member

@srekoble I can't reproduce your issue. Must be a very old version of sass you're using this even works in 3.2

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