I have a property #keyframes, I compiled with autoprefixer to add the needed prefixes.
What I would like to do, is to add an argument to the animation name (or wherever is possible) to change a value of properties into the keyframes key.
This is what I have right now :
#keyframes loader {
0% { transform: translate(0, -50%) rotate(0deg); }
100% { tranform: translate(0, -50%) rotate(360deg); }
}
And basically what I would like to do :
#keyframes loader(#transform) {
0% { transform: #transform rotate(0deg); }
100% { tranform: #transform rotate(360deg); }
Passing arguments to #keyframes cannot be done directly in Less. We can however wrap the whole #keyframes rule within a parent mixin, pass the argument to that mixin and use it within the frames.
.loader(#transform){ /* wrapper mixin which accepts input parameter */
#keyframes loader {
0% { transform: #transform rotate(0deg); }
100% { transform: #transform rotate(360deg); }
}
}
.loader(translate(0, -50%)); /* mixin call */
(Curt had provided an answer initially but had deleted it for reasons unknown to me.)
Just in case you are interested, generic keyframe mixins can also be written in Less like given below.
Sample 1:
.generickeyframe(#name; #from; #to){ /* takes name, from frame rules, to frame rules */
#keyframes #name{
0% { #from();}
100% { #to();}
}
}
.generickeyframe(loader; {transform: translate(0,-50%) rotate(0deg)};
{transform: translate(0,-50%) rotate(360deg)});
Sample 2:
.keyframefromto(#name; #from; #to){
#keyframes #name{
0% { transform: #from;}
100% { transform: #to;}
}
}
.keyframefromto(loader; translate(0,-50%) rotate(0deg); translate(0,-50%) rotate(360deg));
If multiple frames are required to be present within the #keyframes rule, we could make use of array-list and loops like in the below snippet. This mixin takes the name of the animation, the list of frames (their percentage numbers) and the properties for each frame (in the form of rulesets) as parameters.
.generickeyframe(#name; #framelist; #frameprops){
#keyframes #name{
.loop-framelist(#index) when (#index <= length(#framelist)){
#framepos: extract(#framelist, #index) * 1%;
#{framepos}{
#props: extract(#frameprops, #index);
#props();
}
.loop-framelist(#index + 1);
}
.loop-framelist(1);
}
}
.generickeyframe(loader;
0,25,50,75,100;
{transform: translateX(10px);},
{transform: translateX(20px);},
{transform: translateX(50px);},
{transform: translateX(20px);},
{transform: translateX(10px);}
);
Compiled CSS:
#keyframes loader {
0% {transform: translateX(10px);}
25% {transform: translateX(20px);}
50% {transform: translateX(50px);}
75% {transform: translateX(20px);}
100% {transform: translateX(10px);}
}
Related
I made a little CSS animation with a simple svg to transition my hamburger menu to a cross. It works as expected on Chrome and Firefox, but the translation is off in Safari. The animation plays, and even resets correctly so it has nothing to do with prefixes (I tried). The translate of the two lines making the cross is just wrong.
I'm guessing it has something to do with how safari handles the transform when scaling is also applied. Does anyone know if there is a work around / or what I'm doing wrong?
JSFiddle
Safari / Firefox / Chrome
#keyframes showCross {
0% {
transform: scale(1) rotate(0);
}
40% {
transform: scale(0.3) rotate(280deg);
}
100% {
transform: scale(1) rotate(360deg);
}
}
#keyframes showCross_P1 {
0% {
transform: rotate(0);
}
100% {
transform: rotate(-45deg) translate(-42%, -10%);
}
}
I fixed it by doing the following:
First I removed the groups surrounding the paths.
Then I gave all the paths the following values:
transform-origin:center center;
transform-box: fill-box;
Next I edited the animation keyframes to look as follows:
0% {
transform: translate(0rem,0rem) rotate(0);
}
100% {
transform: translate(-10rem,-38rem) rotate(-45deg) ;
}
Safari has problems with percents and also if you put the rotation before the translate it has inconsistency with other browsers, use rem instead!
I'm trying to animate some shapes made with CSS-Doodle which will be a part of my background. Basically, I want them to always float around the screen and always rotate but I want the two animations at different speeds.
With the code below I can only get either one to work by switching around the order of chaining.
animation: spin #r(3s, 10s) infinite, flow #r(20s, 40s) infinite linear;
#keyframes flow {
0%, 100%{
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0)
}
50% {
-webkit-transform: translate3d(#r(-500%, 1000%), #r(-500%, 1000%), 0);
transform: translate3d(#r(-500%, 1000%), #r(-500%, 1000%), 0);
}
}
#keyframes spin {
from {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
I'm hoping there's a way for both of them to be applied at the same time even if it's not pure CSS.
There's probably a better way but the simplest solution would be to put a wrapper around the element so that the wrapper gets one animation and the actual element gets the other animation.
How to run two animations at same time on one element for scalling (like zoom in) and rotate simultaneously.
I have tried that but not work
setTimeout(function(){
document.getElementById('container').style = '-webkit-transform:scale(0) rotate(0deg);';
},1000);
//here I need to scale in and rotate at same time
setTimeout(function(){
//That I have tried intitially and not woking
//document.getElementById('container').style = '-webkit-animation : kf_scale 1s, kf_rotate 1s';
//As suggested by #Terry I have edited after to this but still not working
document.getElementById('container').style = '-webkit-animation : kf_scale 1s';
},3000);
#-webkit-keyframes kf_scale {
100% {
-webkit-transform:scale(1) rotate(360deg);
}
}
#-webkit-keyframes kf_rotate {
100% {
-webkit-transform:rotate(360deg);
}
}
#container{
width:100px;
height:100px;
border:solid 1px;
-webkit-transition: all 1s;
}
<div id="container">
test animation scale + rotate
</div>
//That I have tried intitially and not woking
document.getElementById('container').style = '-webkit-animation : kf_scale 1s, kf_rotate 1s';
//As suggested by #Terry I have edited after to this but still not working
document.getElementById('container').style = '-webkit-animation : kf_scale 1s';
},3000);
If I understand the problem, you're overwriting the style property, so your initial transform is overwritten with the animation. So the animation won't s frtartom the point of the transition, it will start from the default style of the element. The animation is scale()ing from the default (1) to 1, so it doesn't scale. To get the animation to scale from the point where the previous transform ended, add the properties of the transform to the first step of the animation
setTimeout(function(){
document.getElementById('container').style = '-webkit-transform:scale(0) rotate(360deg);';
},3000);
//here I need to scale in and rotate at same time
setTimeout(function(){
document.getElementById('container').style = '-webkit-animation : kf_scale 1s';
},5000);
#-webkit-keyframes kf_scale {
0% {
-webkit-transform: scale(0) rotate(360deg);
}
100% {
-webkit-transform: scale(1) rotate(-360deg);
}
}
#container{
width:100px;
height:100px;
border:solid 1px;
-webkit-transition: all 1s;
}
<div id="container">
test animation scale + rotate
</div>
Just apply the following:
Your.html
<div class="pop"></div>
your.css
#keyframes popDiv {
0% {transform: scale(1) rotate(0deg);}
25% {transform: scale(2) rotate(120deg);}
50% {transform: scale(.5) rotate(240deg);}
100% {transform: scale(1) rotate(360deg);}
}
.pop{
animation: popDiv 8s alternate ease-in-out;
}
I'm relatively new to LESS. It's impressive, and I'm really enjoying working with it thus far, but I'm curious to know: Can I use results produced by mixin functions and concatenate them with strings. I'm including an example with LESShat, which offers a number of Mixin Functions, including a function that generates keyframe animations. The issue being that the Keyframe function needs to be passed a string including properties, and I'm wanting to use other mixins from the LESShat library instead of css properties to generate such keyframe animations.
Original .less File:
#import "css/lesshat.less";
.keyframes(~'myskew, from {.skew(0)} to {.skew(90)}');
.myskewclass {
.animation(myskew 3s linear alternate)
}
Resulting .css File:
lesshat-selector{-lh-property:0}
#-webkit-keyframes myskew{from{.skew(0)}to{.skew(90)}}
#-moz-keyframes myskew{from{.skew(0)}to{.skew(90)}}
#-o-keyframes myskew{from{.skew(0)}to{.skew(90)}}
#keyframes myskew{from{.skew(0)}to{.skew(90)}}
.myskewclass{
-webkit-animation:myskew 3s linear alternate;
-moz-animation:myskew 3s linear alternate;
-o-animation:myskew 3s linear alternate;
animation:myskew 3s linear alternate
}
Obviously not quite what I was going for as the keyframe animations still contain the skew functions and not the values returned by the skew functions. I believe the problem may be that I'm trying to pass other mixins from LESShat inside of the string. So, is there some manner of concatenating strings and mixin functions in LESS? Keep in mind, I'm a total NEWB to LESS. I would simply rather not have to write my own cross-browser transforms. It'd me cool if it could all be automated using LESS. I'm obviously doing it wrong.
The following link describes the .keyframes and .skew functions from LESShat, but I see nothing regarding the mixing of the two mentioned. Maybe I somehow missed that part.
https://github.com/madebysource/lesshat/blob/master/README.md
As far as i understand you should not use the skew() mixin inside or together with keyframes mixin, according the docs you mention, you should use:
.keyframes(~'animationName, 0%{ transform: skewX(0); } 100%{ transform: skewX(90deg) }');
The above will output the following CSS code:
lesshat-selector {
-lh-property: 0; }
#-webkit-keyframes animationName{ 0%{ -webkit-transform: skewX(0); } 100%{ -webkit-transform: skewX(90deg) }}
#-moz-keyframes animationName{ 0%{ -moz-transform: skewX(0); } 100%{ -moz-transform: skewX(90deg) }}
#-o-keyframes animationName{ 0%{ -o-transform: skewX(0); } 100%{ -o-transform: skewX(90deg) }}
#keyframes animationName{ 0%{-webkit-transform: skewX(0);-moz-transform: skewX(0);-ms-transform: skewX(0);transform: skewX(0); } 100%{-webkit-transform: skewX(90deg);-moz-transform: skewX(90deg);-ms-transform: skewX(90deg);transform: skewX(90deg);};
}
You should also notice that using the autoprefixer instead of mixin libraries such as Lesshat will be better practice in most cases.
You should run:
npm install less
npm install less-plugin-autoprefix
less input.less --autoprefix
With the autoprefix plugin:
#keyframes myskew {
0% {
transform: skewX(0);
}
100% {
transform: skewX(90deg);
}
}
Compiles into:
#-webkit-keyframes myskew {
0% {
-webkit-transform: skewX(0);
transform: skewX(0);
}
100% {
-webkit-transform: skewX(90deg);
transform: skewX(90deg);
}
}
#keyframes myskew {
0% {
-webkit-transform: skewX(0);
transform: skewX(0);
}
100% {
-webkit-transform: skewX(90deg);
transform: skewX(90deg);
}
}
The platform were I work does not support #keyframes because of security reasons with the #.
My question is if I can replace it with some other css trick.
For example I have this code:
.cubo {
animation:giro 25s infinite linear;
}
#keyframes giro {
0% {transform: rotateX(0deg) rotateY(0deg);}
100% {transform: rotateX(1080deg) rotateY(360deg);
}
}
Can I replace it with transitions or transforms to avoid using the #? (no javascript supported either).
You could instead make it a transition by multiplying the transition duration, rotateX, and rotateY values all by a common factor x and applying the transition class on page load. In my example I multiplied them by 40, but you can go as high as you want but I wouldn't go too high because the processor might overload at some point and break the page. This runs for 1000 seconds, not many people will stay on a page past that
Here is a live demo of that approach
/* CSS */
.cubo {
/* ...Your other code... */
transition: all 1000s linear;
}
.animate {
-webkit-transform: rotateX(43200deg) rotateY(14400deg);
-moz-transform: rotateX(43200deg) rotateY(14400deg);
-o-transform: rotateX(43200deg) rotateY(14400deg);
-ms-transform: rotateX(43200deg) rotateY(14400deg);
transform: rotateX(43200deg) rotateY(14400deg);
}
/* Javascript (ran on page load) */
document.getElementsByClassName('cubo')[0].classList.add('animate');