Interpolation of prefixes on #keyframes in Sass - sass

I'm trying to workaround Bourbon not supporting #keyframe by generating my own prefixes version with a Sass loop like this:
$list: '' -ms- -webkit- -moz- -o-
$at: # //at sign
#each $prefix in $list
#{$at}#{$prefix}keyframes moveclouds
from
#{$prefix}transform: translateX(2400px)
to
#{$prefix}transform: translateX(-400px)
and expecting to generate css:
#keyframes moveclouds from {
transform: translateX(2400px);
}
#keyframes moveclouds to {
transform: translateX(-400px);
}
#-moz-keyframes moveclouds from {
-moz-transform: translateX(2400px);
}
#-moz-keyframes moveclouds to {
-moz-transform: translateX(-400px);
}
....
the issue is that I cannot figure out how to force Sass output # (at sign) in start of a line
if I do
$at: # // wont work, error
$at: \# // will generate \#keyframes = not good
$at: "\#" // wont work error
$at: ## // will generate ##keyframes = not good
so anyone got an idea how to output at sign in Sass ?

This simply isn't possible using variable interpolation. You can get around the # assignment like this:
$at: unquote("#"); // either of these will work
$amp: #{"#"};
But then you end up with this error:
error sass/test.scss (Line 4: Invalid CSS after "": expected selector_comma_sequence, was "#-ms-keyframes ...")
Interpolation on #keyframes is not currently supported, but will be in the future. You can track the progress of that on GitHub. In the mean time, you'll have to write out your keyframe information by hand. A simple example looks like this:
#mixin keyframes($name) {
#-webkit-keyframes #{$name} {
#content;
}
#keyframes #{$name} {
#content;
}
}
Usage:
#include keyframes(foo) {
0% {
color: red;
}
100% {
color: blue;
}
}
A more complex example can be found in Eric Meyer's Sass Animation library.

Related

How to prefix SASS blocks with a specific scope ID via mixin

Looking to be able to add the app scope id to my sass files when we have multiple apps reusing class names.
That way I can have the following definition:
$app-scope-id: 'appOne';
And then write my SCSS in that app
.blockName{
background: blue;
&__element{
color: orange;
}
}
And call a mixin or something else to just go
#include prefixMixin(){
.blockName{
background: blue;
&__element{
color: orange;
}
}
}
And that render out css like:
.appOne-blockName{ background: blue; }
.appOne-blockName__element{ color: orange }
I'm aware I can use interpolation at the beginning of my block, but was hoping I could keep it cleaner with just a mixin call where necessary and only call it once for an entire SASS file if I wanted.
I don't think it's possible to do what you want with SASS. You could maybe do something like this:
$app-scope-id: 'appOne';
#mixin prefix($selectorType: ".") {
#at-root {
#{$selectorType}#{$app-scope-id}-#{&} {
#content;
}
}
}
blockName {
#include prefix() {
background: blue;
&__element{
color: orange;
}
}
}
Which compiles as:
.appOne-blockName { background: blue; }
.appOne-blockName__element { color: orange; }
But you would still need to include it for each selector that needs the prefix. I'm not sure this can be called "clean" either.

Foundation 6 - Using MotionUI Custom Mixins for Animate

I've installed Foundation 6 for Sites using SASS and I'm compiling with Gulp. I'm trying to use the Motion-UI library for some animation effects, and I've got a lot of it working.
Working Demo of Pre-built Animations:
http://jsfiddle.net/4a9kux0r/7/
The problem I'm having is trying to use the SASS mixins available for the Motion-UI library to create custom effects.
I have the following in my Gulpfile in order to process it...
var PATHS = {
...
sass: [
'bower_components/foundation-sites/scss',
'bower_components/motion-ui/src/'
],
...
};
So, with this in mind, the rest of my .scss files I'm using are set up into partials:
and my app.scss file...
#import 'settings';
#import 'foundation';
#import 'motion-ui';
...
#include motion-ui-transitions;
#include motion-ui-animations;
#import 'partials/base';
#import 'partials/typography';
#import 'partials/utilities';
#import 'partials/animations';
So, all said and done, an animation that is pre-built is working fine, such as:
MotionUI.animateOut($('#foo'), 'fade-in');
But if I try to make a custom mixin for it to combine effects, like this SASS I've placed into my _animations.scss partial
.combineAnimate {
#include mui-animation(fade, spin, slide($direction: up, $amount: 120%));
}
Something like this isn't working...
MotionUI.animateOut($('#foo'), 'combineAnimate');
It's probably just something in where I'm defining the custom animation, or not importing something properly, etc. This is my first time using gulp and foundation 6 and I'm still trying to piece it all together, so any help is sincerely appreciated!
Docs: https://github.com/zurb/motion-ui/blob/master/docs/animations.md
It is only compiling into this css code:
.combineAnimate {
-webkit-animation-name: custom-1;
animation-name: custom-1; }
#-webkit-keyframes custom-1 {
0% {
opacity: 0;
-webkit-transform: rotate(-1turn) translateY(120%);
transform: rotate(-1turn) translateY(120%); }
100% {
opacity: 1;
-webkit-transform: rotate(0) translateY(0);
transform: rotate(0) translateY(0); } }
#keyframes custom-1 {
0% {
opacity: 0;
-webkit-transform: rotate(-1turn) translateY(120%);
transform: rotate(-1turn) translateY(120%); }
100% {
opacity: 1;
-webkit-transform: rotate(0) translateY(0);
transform: rotate(0) translateY(0); } }
As stated in the official documentation for Motion-UI plugin:
"Note that in order to play properly, the element must have at least the property animation-duration applied to it as well."
Being new to CSS3 Animations, I had ignored this very bold stated prerequisite. My SASS was compiling just fine.
#include motion-ui-transitions;
.combineAnimate {
#include mui-animation(fade, spin, slide($direction: up, $amount: 120%));
animate-duration: 2s;
}
Resolves the issue.

SASS Invalid top level expression on #-ms-keyframes [duplicate]

This question already has an answer here:
Sass won't compile because of an "invisible" error
(1 answer)
Closed 7 years ago.
I have a basic scss file that contains (among other things) this:
#keyframes fade{
0% { opacity: 0; }
100% { opacity: 1; }
}
#-moz-keyframes fade{
0% { opacity: 0; }
100% { opacity: 1; }
}
#-webkit-keyframes fade{
0% { opacity: 0; }
100% { opacity: 1; }
}
#-ms-keyframes fade{
0% { opacity: 0; }
100% { opacity: 1; }
}​
// <--- Error thrown on this line
#-o-keyframes fade{
0% { opacity: 0; }
100% { opacity: 1; }
}
When trying to compile, I get an invalid top level expression on the line that I indicated in my code above. Okay, so I tried removing the following code:
#-ms-keyframes fade{
0% { opacity: 0; }
100% { opacity: 1; }
}​
And now it compiles just fine. Why would sass have an issue with this block of code? I'm using node-sass (libsass 3.2).
I think you may have copy pasted an accidental character in your SASS or someone is purposely messing with you. Your SASS compiles perfectly fine on SassMeister with Libsass 3.1.0. Notice however if you copy paste your code snippet into SassMeister, you get this weird unknown character right where the error is thrown. Upon further inspection there was a ​ entity in your code snippet on here. So... That's either an SO bug or an accidental copy paste.
...please tell I'm not insane.

Variable after # in scss [duplicate]

I'm trying to workaround Bourbon not supporting #keyframe by generating my own prefixes version with a Sass loop like this:
$list: '' -ms- -webkit- -moz- -o-
$at: # //at sign
#each $prefix in $list
#{$at}#{$prefix}keyframes moveclouds
from
#{$prefix}transform: translateX(2400px)
to
#{$prefix}transform: translateX(-400px)
and expecting to generate css:
#keyframes moveclouds from {
transform: translateX(2400px);
}
#keyframes moveclouds to {
transform: translateX(-400px);
}
#-moz-keyframes moveclouds from {
-moz-transform: translateX(2400px);
}
#-moz-keyframes moveclouds to {
-moz-transform: translateX(-400px);
}
....
the issue is that I cannot figure out how to force Sass output # (at sign) in start of a line
if I do
$at: # // wont work, error
$at: \# // will generate \#keyframes = not good
$at: "\#" // wont work error
$at: ## // will generate ##keyframes = not good
so anyone got an idea how to output at sign in Sass ?
This simply isn't possible using variable interpolation. You can get around the # assignment like this:
$at: unquote("#"); // either of these will work
$amp: #{"#"};
But then you end up with this error:
error sass/test.scss (Line 4: Invalid CSS after "": expected selector_comma_sequence, was "#-ms-keyframes ...")
Interpolation on #keyframes is not currently supported, but will be in the future. You can track the progress of that on GitHub. In the mean time, you'll have to write out your keyframe information by hand. A simple example looks like this:
#mixin keyframes($name) {
#-webkit-keyframes #{$name} {
#content;
}
#keyframes #{$name} {
#content;
}
}
Usage:
#include keyframes(foo) {
0% {
color: red;
}
100% {
color: blue;
}
}
A more complex example can be found in Eric Meyer's Sass Animation library.

Passing a list to a mixin in SASS as parameters?

I'm trying to make a SCSS stylesheet easily configurable by defining a set of constants that will be used in a number of mixins and with the Compass library. Ideally, I'd like to be able to do the following:
$item-bgs: linear-gradient(white, black), #ccc;
#mixin some-mixin() {
#include background-with-css2-fallback($item-bgs*);
}
The background-with-css2-fallback is a Compass mixin that accepts up to 10 params. I'm assuming that SASS does not currently support passing a list parameter as the argument list, otherwise Compass would probably use it, but I'm wondering if I can get the $item-bgs list to be the first 2 arguments to the background-with-css2-fallback mixin. Is there a way to do this currently, or is it even planned for SASS in the future?
It may not be supported by SASS natively, but Compass does support passing a list as the first argument to the background-with-css2-fallback mixin. If you look at the source for the mixin, you'll see that it uses a compact function that handles the logic for collapsing the arguments into a single list, whether passed individually or in a single list parameter.
For example, this works fine for me:
#import "compass";
$item-bgs: (linear-gradient(white, black), #ccc);
.test {
#include background-with-css2-fallback($item-bgs);
}
Examples of useing maps as arguments:
Example 1 (list)
#mixin transition($property...){
#if $property {
transition-property: $property;
}
#else {
transition-property: all;
}
transition-timing-function: ease-in-out;
transition-duration: .3s;
transition-delay: 0;
}
.btn {
color: black;
border: 1px solid black;
#include transition(color, border-color);
&:hover {
color: red;
border-color: red;
}
}
Example 2 (Custom params)
#use 'sass:meta';
#mixin example2($args...) {
#each $key, $value in meta.keywords($args) {
#{$key}: #{$value};
}
}
.shape {
#include example2($width:200px, $height:100px);
}
Example 3 (map)
#mixin colors($args:()) {
#if length($colors) > 0 {
#each $key, $val in $args{
.txt-#{$key} {
color: #{$value};
}
.bg-#{$key} {
background-color: #{$value};
}
}
}
}
$colors_map: (
primary: blue,
secondary: green,
accent: red,
light: white,
dark: black
);
#include colors($colors_map);

Resources