Are CSS prefixed keyframes stackable? - css

Are CSS prefixed keyframes stackable as long as they don't include any prefixed specific attributes in them?
Common
#-webkit-keyframes myAnimation{
to{ opacity:0; }
}
#-moz-keyframes myAnimation{
to{ opacity:0; }
}
#keyframes myAnimation{
to{ opacity:0; }
}
Stacked
#-webkit-keyframes myAnimation, #-moz-keyframes myAnimation, #keyframes myAnimation{
to{ opacity:0; }
}

Not natively in CSS but you can accomplish this by using a CSS preprocessor, for example LESS which supports the concept of "mixins" to remove some duplication.
More info can be found here, specifically the example from the article:
#-webkit-keyframes myAnimation {.mixi-frames;}
#-moz-keyframes myAnimation {.mixi-frames;}
.mixi-frames () {
opacity:0;
}

It wouldn't work unfortunately. If you group selectors, all of them have to be valid in order for any of them to be.
For instance, if you used your stacked example...
#-webkit-keyframes myAnimation, #-moz-keyframes myAnimation, #keyframes myAnimation{
to{ opacity:0; }
}
... on Firefox, it would read the webkit prefixed selector as invalid, which would make the rest of it, including the -moz- prefixed selector, also invalid.
Travis' preprocessor workaround in the other answer is probably the best way to write it cleanly as you'd like.
EDIT: This is misinformed, these can never be grouped as they are at-rules, not selectors. Same obviously goes for media queries (#media), #font-face, etc. Check out Boltclock's comment below.

Related

Using double vendor prefixes for animations and other attributes

I'm diddling with some css animations and I came to a small dilemma when it came to adding the vendor prefixes. I know that the "keyframes" property requires explicit defining with vendor prefixes just as much as some other CSS properties like "transform". However, what I've been wondering is whether I should include the vendor prefixes on both parts or the "keyframes" would be sufficient.
Here is an example of what I mean:
ex1:
#-webkit-keyframes animation_name {
0% {transform: rotateZ(0deg);}
100% {transform: rotateZ(180deg);}
}
ex2:
#-webkit-keyframes animation_name {
0% {-webkit-transform: rotateZ(0deg);}
100% {-webkit-transform: rotateZ(180deg);}
}
Which would be more correct?
Thanks in advance.
Example 2, as this is the style of output I would expect from an autoprefixer tool, for example: enter link description here

How do i add prefixes (transform) within prefixes (keyframes)?

If i'm using #keyframes to perform a transform animation, how would I lay out my prefixes?
If i have the following:
#keyframes animation {
0% { transform:rotate(0deg); }
100% { transform:rotate(360deg); }
}
Do i then need to add all my transform prefixes to each keyframe declaration? EG:
#keyframes animation {
0% {
-webkit-transform:rotate(0deg);
-ms-transform:rotate(0deg);
transform:rotate(0deg);
}
100% {
-webkit-transform:rotate(360deg);
-ms-transform:rotate(360deg);
transform:rotate(360deg);
}
}
#-webkit-keyframes animation {
0% {
-webkit-transform:rotate(0deg);
-ms-transform:rotate(0deg);
transform:rotate(0deg);
}
100% {
-webkit-transform:rotate(360deg);
-ms-transform:rotate(360deg);
transform:rotate(360deg);
}
}
Does this work? If this the best way to do this or is there a shorthand / quicker way? I'd imagine this way will look bulky and horrible very quickly with even mildly complex animations.
In general, prefixes are a mess especially when it comes to CSS animations and transforms. I have a comprehensive guide to managing prefixes for these two features which you can find here.
What you have certainly works, but it's unnecessary:
Browsers other than IE aren't going to recognize the -ms-transform declaration anyway, and the versions of IE that support CSS animations out of the box also support unprefixed transform.
This means the -ms-transform simply isn't needed, at all. You should remove all instances of it. You only really need it outside of CSS animations where you want the transforms to work statically in IE9. See the link above for details.
Animations and transforms were unprefixed in WebKit only very recently. However, versions of WebKit that support #keyframes unprefixed also support transforms unprefixed. You can remove the -webkit-transform declarations from your #keyframes rule.
I wouldn't touch the unprefixed transform declarations in both rules. Transforms were unprefixed slightly earlier than animations, so some WebKit versions that require #-webkit-keyframes do support unprefixed transforms.
Also, the unprefixed rule should come last. This applies both to properties (like transform) and to at-rules (like #keyframes). Here's your CSS with the above optimizations:
#-webkit-keyframes animation {
0% {
-webkit-transform:rotate(0deg);
transform:rotate(0deg);
}
100% {
-webkit-transform:rotate(360deg);
transform:rotate(360deg);
}
}
#keyframes animation {
0% {
transform:rotate(0deg);
}
100% {
transform:rotate(360deg);
}
}

Concatenate Classes with strings in LESS CSS

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);
}
}

CSS opacity animation safari bug?

I have a simple animation (only for Safari in this example):
h1 {
-webkit-animation: moveDown 1s ease-in-out;
}
#-webkit-keyframes moveDown {
0% {-webkit-transform: translateY(-20px); opacity: 0;}
100% {-webkit-transform: translateY(0px); opacity: 1;}
}
In the latest Safari (5.1.5) it works just fine.
But by accident I viewed the example in an older Safari (5.0.6) and saw nothing. The h1 was gone.
By kind of triggering eather by adding a none-rotate (opacity & animation works):
#-webkit-keyframes moveDown {
0% {-webkit-transform: translateY(-20px) rotate(0deg); opacity: 0;}
100% {-webkit-transform: translateY(0px) rotate(0deg); opacity: 1;}
}
or start at 1% (opacity doesn't work but animation):
#-webkit-keyframes moveUp{
1% {-webkit-transform: translateY(-20px); opacity: 0;}
100% {-webkit-transform: translateY(0px); opacity: 1;}
}
it worked again.
This now leads me to two serious questions:
Is there anything I did wrong in the first example?
Is there a known bug in older version of Safari which I should treat different?
Cause:
I don't mind if you can't see the animation in non-supporting browsers (it's just a nice add on) but it would be daring to not know when your animated element just doesn't show up anymore.
How could I be able to use animations in general as an add-on it without worrying?
If anybody askes for a fiddle: I tried recreating it. But here's another interesting thing: The exact same code will not have any effect in the old Safari in jsfiddle. Nor it animates or dissapears.
Edit:
I'm just seeing that the h1 is not dissapearing anymore with the original code (I can't reconstruct it) but doesn't do any animation eather. It just works with one of the described triggers.
JS-FIDDLE:
Here a working fiddle with the two examples.
I don't have an old version of Safari handy, but I recall playing with animations in older versions and encountered these types of bugs. I worked around them by putting the 'end state' in the selector, e.g. p {opacity: 1} http://jsfiddle.net/pkFaT/

Grouping CSS3 keyframes

I have realized that I can't simple accomplish the same code below by separating by coma #keyframes mymove, #-moz-keyframes mymove, etc... In order for them to work I need to declare it each one separately as below.
Is there any way to group them and make this code shorter?
#keyframes mymove
{
from {top:0px;}
to {top:200px;}
}
#-moz-keyframes mymove /* Firefox */
{
from {top:0px;}
to {top:200px;}
}
#-webkit-keyframes mymove /* Safari and Chrome */
{
from {top:0px;}
to {top:200px;}
}
no, I don't think so, but you could use a CSS language (aka CSS preprocessor) like SASS/SCSS/LESS/... - the output (CSS) would still be the same, but changing something would be much easier!
Check out
http://sass-lang.com/
http://coding.smashingmagazine.com/2011/09/09/an-introduction-to-less-and-comparison-to-sass/
if you're interested - the effort of installing them and setting them up is totally worth it!
EDIT: Using SCSS I did the following:
#mixin keyframes($name) {
#-webkit-keyframes #{$name} { #content; }
#-moz-keyframes #{$name} { #content; }
#keyframes #{$name} { #content; }
}
example of usage:
#include keyframes(pulse) {
0%,100% {
opacity: 0;
}
50% {
opacity: 1;
}
}
Although it should be added that you need the latest pre-release of SASS to be able to nest rules (we have got a "{" inside another "{" rule...) so you should update run "gem install sass --pre" which should get you "sass-3.2.0.alpha.104"

Resources