Sass Keyframes animation mixin generating invalid

2019-01-20 12:09发布

问题:

I have the following keyframes mixin, but it seems to be generated invalid CSS:

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

@include keyframes(icon-one) {
        0% {
          opacity: 1;
        }
        33% {
          opacity: 0;
        }
        66% {
          opacity: 0;
        }
        100% {
          opacity: 0;
        }
}

Here's the output:

@-webkit-keyframes $animationName {
  0% {
    opacity: 1;
  }
  33% {
    opacity: 0;
  }
  66% {
    opacity: 0;
  }
  100% {
    opacity: 0;
  }
}
@-moz-keyframes $animationName {
  0% {
    opacity: 1;
  }
  33% {
    opacity: 0;
  }
  66% {
    opacity: 0;
  }
  100% {
    opacity: 0;
  }
}
@-o-keyframes $animationName {
  0% {
    opacity: 1;
  }
  33% {
    opacity: 0;
  }
  66% {
    opacity: 0;
  }
  100% {
    opacity: 0;
  }
}
@keyframes $animationName {
  0% {
    opacity: 1;
  }
  33% {
    opacity: 0;
  }
  66% {
    opacity: 0;
  }
  100% {
    opacity: 0;
  }
}

Instead of having the keyframes name of icon-one, it's writing out $animationName.

回答1:

You're required to use string interpolation on variables for keyframes names. Your keyframes mixin needs to be written like this:

@mixin keyframes($animationName)
{
    @-webkit-keyframes #{$animationName} {
        @content;
    }
    @-moz-keyframes #{$animationName}  {
        @content;
    }
    @-o-keyframes #{$animationName} {
        @content;
    }
    @keyframes #{$animationName} {
        @content;
    }
}

Note that the keyframes mixin that comes with Compass does this.

There is an issue on GitHub that indicates that interpolation was not required in certain versions of Sass (possibly limited to 3.3.x). However, the authors of Sass considered it to be a bug:

The previous behavior was a bug. Variables should never have been allowed uninterpolated in any directives.



回答2:

Same as above with prefixes:

@mixin keyframes($animationName) {
  @-webkit-keyframes #{$animationName} {
    $browser: '-webkit-' !global;
    @content;
  }
  @-moz-keyframes #{$animationName} {
    $browser: '-moz-' !global;
    @content;
  }
  @-o-keyframes #{$animationName} {
    $browser: '-o-' !global;
    @content;
  }
  @keyframes #{$animationName} {
    $browser: '' !global;
    @content;
  }
} $browser: null;

Full details here.

Or just use Autoprefixer instead.