We have a lot of animation planned and am looking for a cleaner way to address all browsers. Something sass-y like this would be great:
#each $browser in '-webkit-', '-moz-', '-o-', '-ms-' {
##{$browser}keyframes rotate {
from { #{$browser}transform: rotate(0deg);}
to { #{$browser}transform: rotate(360deg);}
}
}
Except that the ##{$vendor}keyfr... produces an error expecting a number or function after the #. Is there a way to force the # through to the css?
Otherwise, has anyone come up with a cleaner way to accomplish this with #each, #mixin or anything else that would save from listing every animation for every browser (i.e. below)?
#-webkit-keyframes rotate {
from { -webkit-transform: rotate(0deg);}
to { -webkit-transform: rotate(360deg);}
}
#-moz-keyframes rotate {
from { -moz-transform: rotate(0deg);}
to { -moz-transform: rotate(360deg);}
}
#-o-keyframes rotate {
from { -o-transform: rotate(0deg);}
to { -o-transform: rotate(360deg);}
}
#-ms-keyframes rotate {
from { -ms-transform: rotate(0deg);}
to { -ms-transform: rotate(360deg);}
}
You could do that with a mixin, where you pre-define the vendor keyframes instead of dynamically generating the vendors in a loop. Something along these lines maybe:
#mixin keyframes($animationName) {
#-webkit-keyframes #{$animationName} {
$browser: '-webkit-'; #content;
}
#-moz-keyframes #{$animationName} {
$browser: '-moz-'; #content;
}
#-o-keyframes #{$animationName} {
$browser: '-o-'; #content;
}
#keyframes #{$animationName} {
$browser: ''; #content;
}
} $browser: null;
#include keyframes('rotate') {
from { #{$browser}transform: rotate(0deg);}
to { #{$browser}transform: rotate(360deg);}
}
DEMO
Just to keep the mods going...
http://sassmeister.com/gist/554597ba07c49dbd92ce
#include makeKeyframes('badgeGlow') {
from { #include box-shadow(0px 0px 10px rgba($glowToColor, 0.3), 0px 1px 2px rgba(0, 0, 0, .80));color:$glowBaseColor;border-color: $glowBaseColor;}
50% { #include box-shadow(0px 0px 16px rgba($glowToColor, 0.8), 0px 1px 2px rgba(0, 0, 0, .80));color:white;border-color: lighten($glowBaseColor, 20);}
to { #include box-shadow(0px 0px 10px rgba($glowToColor, 0.3), 0px 1px 2px rgba(0, 0, 0, .80));color:$glowBaseColor;border-color: $glowBaseColor;}
}
button.glow {
#include setKeyframeType('badgeGlow',1.5s,infinite);
}
Note here that you invoke the keyFrame generator once and you can refer to the keyframes from anywhere else in your classes with the setKeyframeType mixin and provide some basic parameters. Great when you've got many elements that may share the same type of transitions.
Related
I have the following scss file in my project
&.care-loading-icon{
.glyphicon-refresh-animate {
#include care-loading-animation
}
#keyframes spin {
from {
transform: scale(1) rotate(0deg);
}
to {
transform: scale(1) rotate(360deg);
}
}
#-webkit-keyframes spinw {
from {
-webkit-transform: rotate(0deg);
}
to {
-webkit-transform: rotate(360deg);
}
}
#-moz-keyframes spinm {
from {
-moz-transform: rotate(0deg);
}
to {
-moz-transform: rotate(360deg);
}
}
}
I'm wondering if there is any way to simplify this with bourbon?
Looks like, from the documentation that you can use the mixin keyframes to simplify your keyframes implementation.
Like such
#include keyframes(spin) {
from { #include transform(0deg); }
to { #include transform(360deg); }
}
This question already has answers here:
Sass Keyframes animation mixin generating invalid CSS
(2 answers)
Closed 7 years ago.
I currently have a simple keyframes mixin that looks like this:
#mixin keys($animationName) {
#-webkit-keyframes $animationName {
#content;
}
#-moz-keyframes $animationName {
#content;
}
#-ms-keyframes $animationName {
#content;
}
#-o-keyframes $animationName {
#content;
}
#keyframes $animationName {
#content;
}
}
Which I am using for simple fade in animations like this
#include keys(fadeIn) {
0% { opacity: 0; }
100% { opacity: 1; }
}
For some reason, the variable is not translating properly in the css. The css file looks like this:
#-webkit-keyframes $animationName {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#-moz-keyframes $animationName {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#-ms-keyframes $animationName {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#-o-keyframes $animationName {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#keyframes $animationName {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
I feel like this is something super simple I am missing but I can't seem to figure it out. All my other variables work except this one. What do you think would be causing this? Thank you.
I fixed it by adding #{animationName} to everything.
#mixin keys($animationName) {
#-webkit-keyframes #{$animationName} {
#content;
}
#-moz-keyframes #{$animationName} {
#content;
}
#-ms-keyframes #{$animationName} {
#content;
}
#-o-keyframes #{$animationName} {
#content;
}
#keyframes #{$animationName} {
#content;
}
}
I have this Less mixin:
.keyframes (#name, #fromRules, #toRules) {
#-webkit-keyframes ~'#{name}' { from { #fromRules(); } to { #toRules(); } }
#keyframes ~'#{name}' { from { #fromRules(); } to { #toRules(); } }
}
I call for example:
.keyframes(fade-in,
{
opacity: 0;
},
{
opacity: 1;
}
);
The result is:
#-webkit-keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
But how can I use Less mixins so I can use keyframes-selector different from 0%, 100% and also more than 2 keyframes-selector so result will look like this:
#keyframes fade-in {
0% {
opacity: 0;
}
50% {
opacity: 0.5;
}
100% {
opacity: 1;
}
}
Thanks for help.
You could achieve this by passing the rules for the entire list of keyframe selectors (like 0%, 50%, 100% etc) as a single rule-set to the mixin along with the name of the animation.
Also as mentioned by seven-phases-max in the comments, #-webkit-keyframes ~'#{name}' is not required and it can simply be written as #-webkit-keyframes #name.
.keyframes (#name, #rules) {
#-webkit-keyframes #name { #rules(); }
#keyframes #name { #rules(); }
}
div{
.keyframes(fade-in,
{
0% { opacity: 0;}
50% { opacity: 1;}
100% { opacity: 0;}
});
}
CodePen Demo - Click on the eye icon in the CSS box to see the compiled output.
Note:
Passing rulesets to a mixin was introduced in Less v1.7.0 and hence the above code will not work with lower versions.
Here is the standard CSS I am trying to produce but want to use a SASS Mixin to do the work.
STANDARD CSS
#-webkit-keyframes crank-up {
100% { -webkit-transform: rotate(360deg);}
}
#-moz-keyframes crank-up {
100% { -moz-transform: rotate(360deg);}
}
#-o-keyframes crank-up {
100% { -o-transform: rotate(360deg);}
}
keyframes crank-up {
100% { transform: rotate(360deg);}
}
I'm using the same mixin as in the following post SASS keyframes not compiling as wanted which is shown below.
MIXIN
#mixin keyframes($name) {
#-webkit-keyframes #{$name} {
#content;
}
#-moz-keyframes #{$name} {
#content;
}
#-ms-keyframes #{$name} {
#content;
}
#keyframes #{$name} {
#content;
}
}
The above is OK, as long as none of the keyframes include a property that requires a vendor prefix. Like the transform property as all the vendor prefixed keyframes get applied with (in this case) the -webkit- prefix.
For example:
SCSS
#include keyframes(crank-up) {
100% { -webkit-transform: rotate(360deg);}
}
CSS
#-webkit-keyframes crank-up { 100% { -webkit-transform: rotate(360deg); } }
#-moz-keyframes crank-up { 100% { -webkit-transform: rotate(360deg); } }
#-ms-keyframes crank-up { 100% { -webkit-transform: rotate(360deg); } }
#keyframes crank-up { 100% { -webkit-transform: rotate(360deg); } }
Notice the above, -webkit- with a -moz-keyframe. Should be -moz-
So, my first thought was to alter the above mixin to:
ALTERED MIXIN
#mixin keyframes($first-name, $last-name, $argument) {
#-webkit-keyframes #{$first-name} {
-webkit-#{$last-name}: #{$argument};
}
#-moz-keyframes #{$first-name} {
-moz-#{$last-name}: #{$argument};
}
#-o-keyframes #{$first-name} {
-o-#{$last-name}: #{$argument};
}
#keyframes #{$first-name} {
#{$last-name}: #{$argument};
}
}
With a call to the mixin looking like
SCSS
#include keyframes(crank-up, transform, rotate(360deg)) { }
CSS
#-webkit-keyframes crank-up { -webkit-transform: rotate(360deg); }
#-moz-keyframes crank-up { -moz-transform: rotate(360deg); }
#-o-keyframes crank-up { -o-transform: rotate(360deg); }
#keyframes crank-up { transform: rotate(360deg); }
This works all ok if there is only ONE Keyframe 'stage' (see in original code - top of page, there's only the 100% mark), excuse if my terminology is slightly off in reference to keyframe 'stage'.
PROBLEM
I want a mixin like the above to work with something like.
#-webkit-keyframes crank-up {
20%,
40% { -webikit-transform: translateY(34px); }
80% { opacity: .8; }
100% { -webkit-transform: rotate(360deg);}
}
I have also looked into the two Compass Animate plugins; compass-animation and the newer compass-animate but not really sure if these can help. I need some way of adding in a variable and testing for this with a mixin but don't know if it's possible to pass variable into mixins.
Any help much appreciated. Thanks
I've been playing around with the following but neither work, just thought I'd add them up to see if anyone knows where I'm going wrong.
EXPERIMENTAL MIXINS:
#mixin vendor-prefix($name, $argument, $webkit: "-webkit-", $moz: "-moz-",$o: "-o-", $stale: ""){
#{$webkit}: #{$name}: #{$argument};
#{$moz}: #{$name}: #{$argument};
#{$o}: #{$name}: #{$argument};
#{$stale}: #{$name}: #{$argument};
}
#mixin vendor-prefix($last-name, $argument){
#if $name == webkit {
-webkit-#{$name}: #{$argument};
} #else if $name == moz {
-moz-#{$name}: #{$argument};
} #else if $name == o {
-o-#{$name}: #{$argument};
} #else {
#{$name}: #{$argument};
}
}
To deal with vendor-prefixers I recommend to use Autoprefixer instead of sass mixins.
Autoprefixer interface is simple: just forget about vendor prefixes and write normal CSS according to latest W3C specs. You don’t need a special language (like Sass) or special mixins.
Because Autoprefixer is a postprocessor for CSS, you can also use it with preprocessors, such as Sass, Stylus or LESS.
So, in your case, you just need to write this:
#keyframes crank-up {
20%,
40% { -webkit-transform: translateY(34px); }
80% { opacity: .8; }
100% { -webkit-transform: rotate(360deg);}
}
And autoprefixer converts it automatically to:
#-webkit-keyframes crank-up {
20%, 40% {
-webkit-transform: translateY(34px);
}
80% {
opacity: .8;
}
100% {
-webkit-transform: rotate(360deg);
}
}
#keyframes crank-up {
20%, 40% {
-webkit-transform: translateY(34px);
}
80% {
opacity: .8;
}
100% {
-webkit-transform: rotate(360deg);
}
}
Autoprefixer is widely supported, you can process your scss or css styles with this tool through Compass, Grunt, Sublime Text, node.js, Ruby, Ruby on Rails, PHP...
Here is more info about the project
If you are already using Compass and don't want to load whole bounce of extra library and just want to write some mixing then THIS is the best option.
/* animation mixing
keyframe animation
#include animation('animation-name .4s 1')*/
#mixin animation($animate...) {
$max: length($animate);
$animations: '';
#for $i from 1 through $max {
$animations: #{$animations + nth($animate, $i)};
#if $i < $max {
$animations: #{$animations + ", "};
}
}
-webkit-animation: $animations;
-moz-animation: $animations;
-o-animation: $animations;
animation: $animations;
}
And here is the keyframe Mixing to include CSS3 properties inside particular browser vender prefix, instead of #include translate, we use the full css (Note: if you're using Sass 3.3 or older, you'll need to remove the !global flag):
#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;
For your reference here is the SASS example:
#include keyframes(animation-name) {
0% {
#{$browser}transform: translate3d(100%, 0, 0);
}
100% {
#{$browser}transform: translate3d(0%, 0, 0);
}
}
And here how you include your animation to the particular class or ids
.new-class {
#include animation('animation-name 5s linear');
}
That's all.
I use this class for animating div/img and other: http://daneden.me/animate/
I need activation ".animated bounce" class on mouse hover but with pseudo div, this is not problem call when is page load
<div class="first">
<div class="second animated bounce">
For example content
</div>
<div>
I try this but this of course does not work this is for show what i need.
.first:hover > .second
{.animated bounce}
Add this additional selector .first:hover>.second to that CSS code:
.animated {
-webkit-animation-fill-mode:both;
-moz-animation-fill-mode:both;
-ms-animation-fill-mode:both;
-o-animation-fill-mode:both;
animation-fill-mode:both;
-webkit-animation-duration:1s;
-moz-animation-duration:1s;
-ms-animation-duration:1s;
-o-animation-duration:1s;
animation-duration:1s;
}
.animated.hinge {
-webkit-animation-duration:1s;
-moz-animation-duration:1s;
-ms-animation-duration:1s;
-o-animation-duration:1s;
animation-duration:1s;
}
#-webkit-keyframes bounce {
0%, 20%, 50%, 80%, 100% {
-webkit-transform: translateY(0);
}
40% {
-webkit-transform: translateY(-30px);
}
60% {
-webkit-transform: translateY(-15px);
}
}
#-moz-keyframes bounce {
0%, 20%, 50%, 80%, 100% {
-moz-transform: translateY(0);
}
40% {
-moz-transform: translateY(-30px);
}
60% {
-moz-transform: translateY(-15px);
}
}
#-o-keyframes bounce {
0%, 20%, 50%, 80%, 100% {
-o-transform: translateY(0);
}
40% {
-o-transform: translateY(-30px);
}
60% {
-o-transform: translateY(-15px);
}
}
#keyframes bounce {
0%, 20%, 50%, 80%, 100% {
transform: translateY(0);
}
40% {
transform: translateY(-30px);
}
60% {
transform: translateY(-15px);
}
}
.bounce,
.first:hover > .second {
-webkit-animation-name: bounce;
-moz-animation-name: bounce;
-o-animation-name: bounce;
animation-name: bounce;
}
http://jsfiddle.net/gFXcm/8/
I'm not sure but you can try copying all css rules for .bounce element from animate.css into such selector:
.first:hover > .second {
...
}
You can also use JS if it doesn't work (dunno, haven't tested it)
var first = document.getElementsByClassName("first")[0];
var second = document.getElementsByClassName("second")[0];
var nobounce = second.className;
var bounce = second.className + " bounce";
first.onmouseover=function(){
second.setAttribute("class", bounce);
}
first.onmouseout=function(){
second.setAttribute("class", nobounce);
}
or simplier with jQuery
$(".first").hover(function(){
$(".second").addClass("bounce");
}, function() {
$(".second").removeClass("bounce");
});
Hope it helps
EDIT
Forgot that it will animate constantly, I quess you may probably want to stop it on mouseout event. I found some mistakes in pure JS attempt as well - updated code above
Maybe
.animated.bounce {
animation-name:dont-bounce
}
.first:hover > .animated.bounce {
animation-name: bounce
}
You need all vendor prefixes also. But jQuery version is better.
Sorry, can't use code tag, I'm writting from cellphone.