Stacking CSS3 transform functions from multiple selectors in stylesheet - css

Let's say I have 2 DIVs:
​<div class="div1"></div>
<div class="div2"></div>​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​
I want to rotate both of them:
div {
position: absolute;
width: 100px;
height: 100px;
-webkit-transform: rotate(30deg);
-moz-transform: rotate(30deg);
}
And then I want to move them independently:
.div1 {
background-color: red;
-webkit-transform: translate(100px,0px);
-moz-transform: translate(100px,0px);
}
.div2 {
background-color: green;
-webkit-transform: translate(0px,100px);
-moz-transform: translate(0px,100px);
}​
The problem is that both the rotating and the moving use the transform property, so the moving overrides the rotating. Is it possible to make the values stack together instead of overriding each other?
Notes:
I will be using complex transform functions, not merely simple translations, so I cannot substitute them with just left and top properties.
I have many DIVs, so it is much more efficient to select all of them and apply their common properties, before assigning their individual properties.
Reference: jsFiddle

Unfortunately, due to how the syntax and the cascade work, you won't be able to stack transforms as described. You will have to redeclare the rotations before the translations:
.div1 {
background-color: red;
-webkit-transform: rotate(30deg) translate(100px,0px);
-moz-transform: rotate(30deg) translate(100px,0px);
}
.div2 {
background-color: green;
-webkit-transform: rotate(30deg) translate(0px,100px);
-moz-transform: rotate(30deg) translate(0px,100px);
}​

How about using keyframes?
Demo: jsFiddle
Code:
.div1 {
background-color: red;
-webkit-animation: divone 2.0s ease-in-out forwards;
-webkit-animation-iteration-count: 1;
-webkit-animation-delay: 1.0s;
}
.div2 {
background-color: green;
-webkit-animation: divtwo 2.0s ease-in-out forwards;
-webkit-animation-iteration-count: 1;
-webkit-animation-delay: 1.0s;
}
#-webkit-keyframes divone
{
0% {-webkit-transform: rotate(0deg);}
50% {-webkit-transform: rotate(30deg);}
100% {-webkit-transform: rotate(30deg) translate(100px,0px);}
}
#-webkit-keyframes divtwo
{
0% {-webkit-transform: rotate(0deg);}
50% {-webkit-transform: rotate(30deg);}
100% {-webkit-transform: rotate(30deg) translate(0px,100px);}
}

You state, "I have many DIVs, so it is much more efficient to select all of them and apply their common properties, before assigning their individual properties." It may be more efficient for you coding, but unfortunately not for the results. The only way is to do them all in a single call (as BoltClock just beat me to posting).
To regain efficiency, look at using LESS or SCSS preprocessing. Another answer to a recent question regarding setting up LESS for multiple transitions may be helpful to you.

Related

Oscilatory Animation CSS: How to avoid abrupt transition from 100% to 0%?

I am trying to make an Oscillatory animation using css as shown below:
Here's how I have created my animation:
#keyframes rotateFeather {
0% {
transform: rotate(0deg);
}
25% {
transform: rotate(-180deg);
}
50% {
transform: rotate(-90deg);
}
75% {
transform: rotate(90deg);
}
100% {
transform: rotate(180deg);
}
}
Here is my class: (Using sccs)
.logo {
height: 5rem;
transition: all 0.3s ease;
&box {
position: absolute;
top: 4rem;
left: 4rem;
}
&:hover {
animation-name: rotateFeather;
animation-duration: 1s;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
}
Here I am facing this problem: When it reaches 180deg at 100% it abruptly resets to 0 which I want to make smooth.
How is it possible to do the same?
To ensure smooth transition, We need to make sure that transformation at 0 and 100% must match with the original state:
#keyframes rotateFeather {
0% {
transform: rotate(0deg); //-30
transform-origin: bottom;
}
20% {
transform: rotate(-30deg); //-60
transform-origin: bottom;
}
40% {
transform: rotate(0deg); //-30
transform-origin: bottom;
}
60% {
transform: rotate(30deg); // 0
transform-origin: bottom;
}
80% {
transform: rotate(60deg); //30
transform-origin: bottom;
}
100% {
transform: rotate(0deg); //30
transform-origin: bottom;
}
}
This helped me to solve my issue. I am not sure, if I need to add transform-origin in every stage, if someone can elaborate better on that, that would be helpful.
Here's a simplified version of your latest animation code (with a Codepen to see it in action):
#keyframes rotateFeather {
0% {
transform: rotate(0deg);
}
20% {
transform: rotate(-30deg);
}
80% {
transform: rotate(60deg);
}
100% {
transform: rotate(0deg);
}
}
.logo {
transform-origin: bottom;
&:hover {
animation: rotateFeather 1s linear infinite;
}
}
Some points about the above tweaks:
You don't need transform-origin at every keyframe. You can set it globally.
You can roll all of your animation properties into a single shorthand rule.
You can skip keyframes that are mathematically interpolating where the animation would be going anyway (notice I omitted 40% and 60% above and it looks the same).
You don't need any transition rules on elements that you are animating with keyframes. Unless you're using it for something else, but you want to be careful to avoid attempting to animate the same property on the same element with both animation and transition simultaneously, as it will break the animation in question.

Transition only for translate property

I have two transform operations (rotate and translate) and I want to make transition for translate only (rotate have to be instant).
Some suggestions? I prefer pure css.
Use keyframes to reach your desired effect, in addition to animation-fill-mode to keep the computed styles when the animation is finished.
.object {
width: 50px;
height: 50px;
background-color: #F00;
animation-fill-mode: forwards;
}
.object:hover {
animation: move 1s;
animation-fill-mode: forwards;
}
#keyframes move {
0% {
transform: translateY(0px) rotate(0deg);
}
1% {
transform: rotate(45deg);
}
100% {
transform: translateY(25px) rotate(45deg);
}
}
<div class="object"></div>

How to make CSS color transition time correctly with transform perspective?

So I have this cute little spinner made to signify when something is loading. The perspective changes and the background color are supposed to change at the same time. I am having trouble getting the Transform and Transition timings to line up so that you don't see the color change, it needs to be already changed when the square flips so that it is a smooth transition.
Link to JS Fiddle
HTML
<div class="spinner"></div>
CSS
.spinner {
width: 20px;
height: 20px;
-webkit-animation: rotateplane 1.2s infinite ease-in-out;
animation: rotateplane 1.2s infinite ease-in-out;
}
#-webkit-keyframes rotateplane {
0% { -webkit-transform: perspective(120px); background-color: #00b16a; }
50% { -webkit-transform: perspective(120px) rotateY(180deg); background-color: #f22613;}
100% { -webkit-transform: perspective(120px) rotateY(180deg) rotateX(180deg); background-color: #aaabae; }
}
#keyframes rotateplane {
0% {
transform: perspective(120px) rotateX(0deg) rotateY(0deg);
-webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg)
} 50% {
transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
-webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg)
} 100% {
transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
-webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
}
}
Two things to consider:
Transitions interpolate smoothly (well, according to the easing function) between keyframes.
If you do not specify an attribute at a keyframe, it will interpolate without interruption over that keyframe.
With those in mind, you can change the keyframes to apply your color change in the middle of your perspective change. In addition, you'll set two keyframes for the color change, very close to each other, to ensure the interpolation happens over a small time slice.
#-webkit-keyframes rotateplane {
0% { -webkit-transform: perspective(120px); background-color: #00b16a; }
24.9% {background-color: #00b16a;}
25.0% {background-color: #f22613;}
50% { -webkit-transform: perspective(120px) rotateY(180deg); background-color: #f22613;}
74.9% { background-color: #f22613; }
75% { background-color: #aaabae; }
100% { -webkit-transform: perspective(120px) rotateY(180deg) rotateX(180deg); background-color: #aaabae; }
}
Now, you'll notice that since you have the animation on infinite repeat, that you still get a color transition when the animation loops from 100% to 0%. You'll have to either specify animation-direction: alternate; or adjust your keyframes so that 100% ends at a reasonable tweening point between 100% and 0%.
DEMO using alternate

CSS Animation Oscillating Flip X axis

I have a CSS3 Animation for an indeterminate progress bar. In the animation I have a gradient oscillating back and forth along the progress bar. I would like to flip the image of gradient horizonally as it travels back to the left side of the progress bar. Basically the gradient always fades out the opposite direction the image is moving. Unfortunately I can't figure out a way for the image to flip horizontally BEFORE it starts moving back towards the left and am getting some odd transformations of the image as it flips.
I have created a JSFiddle to show how it looks right now.
http://jsfiddle.net/MtWzL/
Here is the CSS I'm currently using for the animation:
#-webkit-keyframes loader {
0% {
-webkit-transform: scaleX(1);
-webkit-transform: translateX(-100px);
-webkit-transform-origin:left;
}
50% {
-webkit-transform: translateX(300px);
}
100% {
-webkit-transform: translateX(-100px);
-webkit-transform: scaleX(-1);
}
}
#keyframes loader {
0% {
transform: scaleX(1);
transform: translateX(-100px);
transform-origin:left;
}
50% {
transform: translateX(300px);
}
100% {
transform: translateX(-100px);
transform: scaleX(-1);
}
}
.slider
{
animation: loader 2.5s infinite linear;
-webkit-animation: loader 2.5s infinite linear; /* Safari and Chrome */
background: url('http://s23.postimg.org/mglkwgxuv/indeterminate_bg.png') no-repeat;
border-radius: 10px;
height: 10px;
position: relative;
width: 100px;
z-index: 999;
opacity: .6;
}
.container {
background: -webkit-linear-gradient(#00c3ff,#0071bc);
background: linear-gradient(#00c3ff,#0071bc);
border-radius: 3px;
height: 10px;
overflow: hidden;
width: 300px;
}
.background {
background: rgba(0,0,0,0.7);
border-radius: 3px;
display: inline-block;
padding: 10px;
}
There are 2 issues that need to be fixed
first of all, this
-webkit-transform: scaleX(1);
-webkit-transform: translateX(-100px);
won't work as you expect; the second property over-rides the first one, as you can not set 2 different values for a property in separate lines.
the correct syntax would be
-webkit-transform: translateX(-100px) scaleX(1);
And second, if you want a sudden change in some value, you need to set it from a keyframe to another keyframe close enough to the first one.
So, the solution would be
#-webkit-keyframes loader {
0% { -webkit-transform: translateX(-100px) scaleX(1); }
50% { -webkit-transform: translateX(300px) scaleX(1); }
51% { -webkit-transform: translateX(300px) scaleX(-1); }
100% { -webkit-transform: translateX(-100px) scaleX(-1); }
}
corrected fiddle
I have corrected only the webkit transforms, but the same concept applies to the rest.
I was watching for your problem since you put it here, but I guess its some kind of bug we won't solve or maybe I just dont understand why it is working like that.
Since I had no clue how to solve it I manage to do example for you with alternative solution
EXAMPLE
As you can see I modified your jsfiddle, simple words, created another slide loader .sliderBack that goes backwards. Hope it will helps you somehow. Peace :)

how to avoid break between different steps of keyframe animation?

I would like my animation to not stop at 50%, how to avoid this short iterruption?
#-webkit-keyframes PLAY {
0% {
-webkit-transform: translate(0px,0);
}
50% {
-webkit-transform: translate(-60px,0) rotate(-1080deg) scale(2);
}
100% {
-webkit-transform: translate(-120px,0) rotate(-2060deg) scale(1);
}
}
.play {
-webkit-animation-name: PLAY;
-webkit-animation-duration: 2s;
-webkit-animation-timing-function: ease-out;
}
I think right now it's using ease-in-out, or something similar, for its "timing function".
Try adding this CSS property:
-webkit-animation-timing-function: linear;
2ND EDIT: So now that I see your class declaration it seems the easing is intentional. Since that applies to each phase of the animation though, it needs to be applied a little differently. Here's my full change - you might as well remove the timing function inside of the class:
#-webkit-keyframes PLAY {
0% {
-webkit-transform: translate(0px,0);
-webkit-animation-timing-function: ease-in;
}
50% {
-webkit-transform: rotate(-1080deg) scale(2);
-webkit-animation-timing-function: ease-out;
}
100% {
-webkit-transform: rotate(-2060deg) scale(1);
}
}
1ST EDIT: Actually, having admired your "Meanwhile, at the batcave...!" animation in my test page for a moment, I think there's a bit more to improve. I'm guessing that the translation is meant to offset the off-center spinning caused by the default "center point" position. So, you can add this CSS property, and remove the translations. Then it's not even dependent on image size.
transform-origin: 50% 50%;
-moz-transform-origin: 50% 50%;
-webkit-transform-origin: 50% 50%;
-o-transform-origin: 50% 50%;
-ms-transform-origin: 50% 50%;
In fact, the 0% can just be "-webkit-transform: none"
Changed to use the correct cross-browser CSS property

Resources