I'm having a bit of a problem trying to make this idea work, if it is even possible in Sass syntax. I've seen similiar things being used in SCSS syntax and I've tried multiple things to make it work. All of them failed for now.
This is the code, you can see what the idea behind it is from the code:
#keyframes AdHop($from, $to)
0%
transform: scale($from)
100%
transform: scale($to)
So my question is; Is this even possible to do, if so, how?
You can make a mixin
DEMO
#mixin adHop($from, $to, $name) {
#keyframes #{$name} {
0% { transform: scale($from); }
100% { transform: scale($to); }
}
}
#include adHop(1, 2, cool);
button:hover { animation: cool 1s; }
While validating for CSS3, following error can be seen for my Website:
Sorry, the at-rule #-moz-keyframes is not implemented
Below is the CSS code:
Line 16:
#-moz-keyframes spin {
0% {
-moz-transform:rotate(0deg)
}
100% {
-moz-transform:rotate(359deg)
}
}
#-webkit-keyframes spin {
0% {
-webkit-transform:rotate(0deg)
}
100% {
-webkit-transform:rotate(359deg)
}
}
#-ms-keyframes spin {
0% {
-ms-transform:rotate(0deg)
}
100% {
-ms-transform:rotate(359deg)
}
}
#keyframes spin {
0% {
transform:rotate(0deg)
}
100% {
transform:rotate(359deg)
}
}
.fa-rotate-90 {
filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);
-webkit-transform:rotate(90deg);
-moz-transform:rotate(90deg);
-ms-transform:rotate(90deg);
transform:rotate(90deg)
}
I would like to know what kind of CSS validation Error is this and what can be the better solution for this error
According to caniuse, the -moz-animation (and corresponding #-moz-keyframes) was used by Firefox 5-15.
Most likely the validator you're using assumes (rightly) that effectively all serious users (at least 99.65% of Firefox users, even less in the total scope of things) will be using a more modern Firefox than Firefox 15.
As a result, it's pretty safe to leave it out if you're want to remove the "error".
If declare a keyframe in a less file is all ok, but if i declare another keyframe(no tiping errors, I just duplicate working keyframe then change the name) less tell me unrecognized input. Instead, with saas have expected "{", was "#keyframes error.
the code:
#keyframes cloud-animation-1 {
from { transform:translate(0px,0);}
to{transform:translate(1000px,0);}
}
#-moz-keyframes cloud-animation-1 {
from {transform:translate(10px,0);}
to{transform:translate(1000px,0);}
}
#-webkit-keyframes cloud-animation-1 {
from {-webkit-transform:translate(0px,0);}
to{-webkit-transform:translate(1000px,0);}
}
#keyframes 2cloud-animation-2 {
from {transform:translate(10px,0);}
to{transform:translate(1000px,0);}
}
#-moz-keyframes cloud-animation-2 {
from {transform:translate(0px,0);}
to{transform:translate(1000px,0);}
}
#-webkit-keyframes cloud-animation-2 {
from { -webkit-transform:translate(0px,0);}
to{ -webkit-transform:translate(1000px,0);}
}
Solutions? Have missing something?
Thanks
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.
I try to set up this LESS mixin for CSS animation keyframes:
.keyframes(#name, #from, #to) {;
#-webkit-keyframes "#name" {
from {
#from;
}
to {
#to;
}
}
}
but there is some problem with name pharse, is there any option to do this corectly?
As of LESS >= 1.7 you can use variables for keyframe keywords (names).
Some changes have been made in LESS 1.7 to how directives work, which allows to use variables for the name/keyword of #keyframes (so the example from the question should work now).
Unfortunately keyframes names can not be dynamically generated in LESS <= 1.6
Hence, the normal way of going about keyframes would use hardcoded names and you would only call for specific "for" and "to" mixins, like this:
.colors-mixin-frame(#from,#to){
from {color: #from;}
to {color: #to;}
}
.width-mixin-frame(#from,#to){
from {width: #from;}
to {width: #to;}
}
// keyframes with hardcoded names calling for specific mixin frames
#keyframes red-blue { .colors-mixin-frame(red, blue); }
#keyframes change-width { .width-mixin-frame(254px, 512px); }
But you can use a workaround to dynamically generate the names
where you inject the name into the rule name, this however requires an declaration of the next rule that supplies the closing bracket } at the end of the keyframes declaration. The most convenient is if you just build the animation calling that keyframe
.animation-keyframes(#name, #from, #to, #anim-selector) {
#keyf: ~"#keyframes #{name} { `'\n'`from ";
#anim: ~"} `'\n'`.#{anim-selector}";
#{keyf} {
.from(#name,#from);
}
to {
.to(#name,#to);
}
#{anim} {
animation-name:#name;
}
}
Note that you also need to define .from(){} and .to(){} mixins, and not just use #from and #to like you did in your example (because LESS also does not allow for dynamically generated properties) ... this mixins can now construct the desired properties and values ... to use specific property you can use guards or name-specific mixins like these:
// name-specific from and to mixins that are used if first argument equals "colors"
.from (colors, #color) {
color: #color;
}
.to (colors, #color) {
color: #color;
}
Now we can call our mixin in LESS:
// test
.animation-keyframes (colors, red, blue, my-colanim);
and get CSS:
#keyframes colors {
from {
color: #ff0000;
}
to {
color: #0000ff;
}
}
.my-colanim {
animation-name: colors;
}
this will work also in LESS 1.4, but note that we used javascript interpolation for line breaks, which requires a javascript implementation of LESS.
Edit: to your additional question about prefixes
Mixin with vendor prefixes
Here I made two mixins ... one without vendor prefixes and one with them both calling a general .keyframes mixin:
.keyframes (#name, #from, #to, #vendor:"", #bind:"") {
#keyf: ~"#{bind}##{vendor}keyframes #{name} { `'\n'`from ";
#{keyf} {
.from(#name,#from);
}
to {
.to(#name,#to);
}
}
.animation-keyframes-novendor (#name, #from, #to, #anim-selector) {
.keyframes (#name, #from, #to);
#anim: ~"} `'\n'`.#{anim-selector}";
#{anim} {
animation-name:#name;
}
}
.animation-keyframes (#name, #from, #to, #anim-selector) {
#bind: "} `'\n'`";
.keyframes (#name, #from, #to, "-moz-");
.keyframes (#name, #from, #to, "-webkit-", #bind);
.keyframes (#name, #from, #to, "-o-", #bind);
.keyframes (#name, #from, #to, "-ms-", #bind);
.keyframes (#name, #from, #to, "", #bind);
#anim: ~"} `'\n'`.#{anim-selector}";
#{anim} {
-moz-animation: #name;
-webkit-animation: #name;
-o-animation: #name;
-ms-animation: #name;
animation: #name;
}
}
.from (colors, #color) {
color: #color;
}
.to (colors, #color) {
color: #color;
}
/* keyframes with all vendor prefixes */
.animation-keyframes (colors, red, blue, my-colanim);
/* keyframes with no vendor prefix */
.animation-keyframes-novendor (colors, red, blue, my-colanim);
The .animation-keyframes will now produce keyframes for all vendor prefixes and an animation selector with vendor prefixed properties. And as expected the .animation-keyframes-novendor gives the same output as the above simple solution (without vendor prefixes).
Some notes:
For your animation to actually work you need to set other animation parameters like timing-function, duration, direction, iteration-count (requires at least a duration time in addition to the name that we already set).
For example:
animation: #name ease-in-out 2s infinite alternate;
If you wrap above mixins in namespaces make sure you change the mixin references inside other mixins to their whole path (including the namespaces).
For example:
#namespace > .keyframes () // see .less source in the demo for details
I am currently working on a mixin library
The source can be found here https://github.com/pixelass/more-or-less
My keyframe mixin looks like this:
WORKS FOR LESS 1.7.x
MIXIN
.keyframes(#name) {
#-webkit-keyframes #name {
.-frames(-webkit-);
}
#-moz-keyframes #name {
.-frames(-moz-);
}
#keyframes #name {
.-frames();
}
}
INPUT
& {
.keyframes(testanimation);.-frames(#-...){
0% {
left: 0;
#{-}transform: translate(10px, 20px);
}
100% {
left: 100%;
#{-}transform: translate(100px, 200px);
}
}
}
OUTPUT
#-webkit-keyframes testanimation {
0% {
left: 0;
-webkit-transform: translate(10px, 20px);
}
100% {
left: 100%;
-webkit-transform: translate(100px, 200px);
}
}
#-moz-keyframes testanimation {
0% {
left: 0;
-moz-transform: translate(10px, 20px);
}
100% {
left: 100%;
-moz-transform: translate(100px, 200px);
}
}
#keyframes testanimation {
0% {
left: 0;
transform: translate(10px, 20px);
}
100% {
left: 100%;
transform: translate(100px, 200px);
}
}
How about this:
#-webkit-keyframes some-animation {.mixi-frames;}
#-moz-keyframes some-animation {.mixi-frames;}
#-ms-keyframes some-animation {.mixi-frames;}
#-o-keyframes some-animation {.mixi-frames;}
#keyframes some-animation {.mixi-frames;}
.mixi-frames () {
from {width: 254px;}
to {width: 512px;}
}
You need to do it for each animation.
Taken from: http://radiatingstar.com/css-keyframes-animations-with-less
Also thanks to the great answer by Martin Turjak, (thank you for that) I just put on github a less mixin which generate keyframes and animation's css code without hacks and in a flexible way, you can find it here github.com/kuus/animate-me.less.
With this mixin you can write this code to obtain valid and cross browser css (see the github repo for a complete explanation):
.animate-me(ComplexAnimation; 0.4s ease; '.complex-animation';
'50%, 100%'; '%stransform: translateZ(-250px) rotateY(30deg)';
70%; '%stransform: translateZ(-250px) rotateY(30deg); opacity: .5; background: green';
30%; '%stransform: translateZ(-250px) rotateY(30deg); opacity: .2; background: yellow';
80%; '%stransform: translateZ(-250px) rotateY(30deg); opacity: 1; background: red'
);
Before-mentioned https://github.com/kuus/animate-me.less does things!
You can also check out this one written by me (seems to be neater):
https://github.com/thybzi/keyframes
I think you should do this
#-webkit-keyframes #name
{
code...
}
change "#name" to #name
and you should delete ; after
.keyframes(#name, #from, #to) {