This question already has answers here:
How to apply multiple transforms in CSS?
(9 answers)
Closed 6 years ago.
I'm trying out the css animation using #keyframes, however the css Transform rotate and translate properties aren't working together.
Please advise on what has gone wrong here. Thanks!!
You can check the code on codepen:
http://codepen.io/anon/pen/XdzwZB
following is my #keyframes code:
#keyframes slideIn {
0%, 100% {
transform: translate(10px);
transform: rotate(0deg);
color: red;
}
25% {
transform: translate(125px);
transform: rotate(360deg);
color: green;
}
}
The correct way to apply multiple transforms is to simply place them all in one transform property, with each transform separated by a space:
#keyframes slideIn {
0%, 100% {
transform: translate(10px) rotate(0deg);
color: red;
}
25% {
transform: translate(125px) rotate(360deg);
color: green;
}
}
Updated codepen
Related
I tried to rotate an animated font arrow when the window reached a min/max size, but when the rotate takes place the animation stops, also just for testing I tried replacing transform: rotate(90deg) to transform: rotate(0deg) which maintains the same arrow's direction but it causes to stop the animation too. The issue is with transform: rotate() and it can be easily tested by inspecting the element and activating/deactivating it in the browsers developer tools.
An easy way to bypass this can be using two <p> each one with an arrow in different direction and with vertical and horizontal animation each, and using display: none; to alternate between them when the min/max size switches, but what I want is to know why this is happening and how to solve this using this approach
.text-center {
text-align: center;
}
.lnr-x3 {
font-size: 2.4rem;
}
#media (max-width: 991px) {
#catalogArrow_h {
transform: rotate(90deg) !important;
transform-origin: center !important;
}
}
.animated-h {
text-decoration: none;
outline-style: none;
-webkit-animation: movingHorizontally 1.7s ease-in-out infinite;
animation: movingHorizontally 1.7s ease-in-out infinite;
}
#keyframes movingHorizontally {
0% {
transform: translateX(0px);
-webkit-transform: translateX(0px);
}
50% {
transform: translateX(-10px);
-webkit-transform: translateX(-10px);
}
100% {
transform: translateX(0px);
-webkit-transform: translateX(0px);
}
}
#-webkit-keyframes movingHorizontally {
0% {
transform: translateX(0px);
-webkit-transform: translateX(0px);
}
50% {
transform: translateX(-10px);
-webkit-transform: translateX(-10px);
}
100% {
transform: translateX(0px);
-webkit-transform: translateX(0px);
}
}
<!-- Font Icons -->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" type="text/css">
<link rel="stylesheet" href="https://cdn.linearicons.com/free/1.0.0/icon-font.min.css">
<div class="col-12">
<p class="text-center pt-3 px-5">
<span id="catalogArrow_h" class="lnr lnr-x3 lnr-arrow-right fas animated-h"></span>
</p>
</div>
Why does this happen
The transform property is "shared" for many transform functions and css doesn't combine any property's values.
Because your animation is made with transform: translateX(..), adding transform: rotate(..) will overwrite the property's value, not combine them. I.e. the resulting style is transform: rotate(..), not transform: translateX(..) rotate(..).
It would be the same if you were animating the box-shadow and then wanted an inset box-shadow too, it would overwrite one with the other. Or more simply - if you have .box { color: red; color: blue; } css will choose the last value (blue) to apply to the color property.
If there were css properties rotate: 90deg and translate: 4px (there are but not widely supported), then your animation would work, because the translate animation would be applying to a different property than the rotation, not overwriting one that is essentially shared amongst many transform functions.
Ways around it
There are many ways around this problem.
You can set the translate or rotate on the parent element
<div class="rotate-90">
<span class="translate-animate"></span>
</div>
You can add the rotate to your translate animation properties:
#keyframes movingHorizontallyRotated {
0%, 100% { transform: translateX(0px) rotate(90deg); }
50% { transform: translateX(-10px) rotate(90deg); }
}
You can animate a different property to translate the element:
#keyframes movingHorizontally {
0%, 100% { padding: 5px 10px 5px 0px; }
50% { padding: 5px 0px 5px 10px; }
}
You can use/make an already rotated arrow if your framework/ assets provides one.
This question already has an answer here:
How to keep origin in center of image in scale animation?
(1 answer)
Closed 1 year ago.
I couldn't find a solution for this simple problem, I changed the display to flex and block, that didn't work either. It works on parent element. But I guess there is something I can't see on this code.
.planets {
display: flex;
height: 100vh;
}
.pluton-orbit {
display: inline-block;
width: 70rem;
height: 70rem;
border: 1px solid rgba(0, 0, 0, 0.219);
border-radius: 50%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50% , -50%);
z-index: 4;
animation: Rotation 5s linear infinite;
}
#keyframes Rotation {
from {
transform: rotate(0);
}
to {
transform: rotate(360deg);
}
}
the transform here, doesn't work. I know how to center, my question is why doesn't the transform property work. this is react with Sass by the way. Everything else works in the code, just the transform has this weird problem. here is the component.
import React from "react";
const Planets: React.FC = () => {
return (
<div className="planets">
<div className="pluton-orbit">
<div className="pluton"></div>
</div>
<div className="neptun-orbit">
<div className="neptun"></div>
</div>
</div>
);
};
export default Planets;
It's because the animation is overriding the transform property. This is one limitation of transform. a solution is to add the translate(-50%, -50%) to the animation keyframes.
#keyframes Rotation {
from {
transform: translate(-50%, -50%) rotate(0);
}
to {
transform: translate(-50%, -50%) rotate(360deg);
}
}
I've used the following CSS taken from here.
:host {
animation: rotation 2s infinite linear;
border: 10px solid yellow;
}
#keyframes rotation {
from { transform: rotate(0deg); }
to { transform: rotate(359deg); }
}
I don't get to see any rotation, although I can see the border, so I know that I target the correct element. I don't think it's required to have an IMG (and mine is a custom thingy in Angular). It works on the IMG and also on a DIV. Not sure how to diagnose it further as rotations/animations aren't my strongest suite.
One approach is to put the custom component in a DIV and rotate that. However, it does rotate around the middle of the screen (wiiiide circle) instead of spinning around itself.
<div id="loading">
<my-icon-globe></my-icon-globe>
</div>
#loading { animation: rotation 2s infinite linear; }
#keyframes rotation {
from { -webkit-transform: rotate(0deg); }
to { -webkit-transform: rotate(359deg); }
}
You can adjust transform-origin of the DIV if you attempt the second approach.
I am trying to combine two animations smoothly for the title on the front page of my website to fadeIn and up, then slide to the left with the two 's being left aligned instead of center aligned. When trying to do so, I run into the problem of the two animations either running at the same time or one running over the other.
I have tried adding two separate CSS classes in the tags as well as creating only one to handle both 's. I believe creating two slideLeftTop and slideLeftBottom will work more efficiently because the text is longer at the bottom and the end goal is to have the two 's left-aligned instead of how they are center aligned at the start.
#-webkit-keyframes slideLeftTop{
0% {
-webkit-transform: translate3d(0,100%,0);
}
100% {
-webkit-transform: translateX(-20%)
}
}
https://jsfiddle.net/k2tvur84/1/
I expect the title to fadeIn and up, have a 3-second pause, and then slide to the left about 40% of the page.
You can combine all changes with the keyframe.
Is this what you want?
.animated {
-webkit-animation-duration: 7s;
animation-duration: 7s;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
#-webkit-keyframes fadeInUp {
0% {
opacity: 0;
-webkit-transform: translate3d(0,100%,0);
-ms-transform: translate3d(0,100%,0);
transform: translate3d(0,100%,0);
}
25% {
opacity: 1;
-webkit-transform: none;
-ms-transform: none;
transform: none;
}
70% { -webkit-transform: translate3d(0,100%,0);}
100% { -webkit-transform: translateX(-20%)}
}
You can have a look here for this approach. Hope that help!
When applying a CSS scale transform to an element, is it possible to set the 'from' value as the current scale?
For example, consider the following 2 CSS keyframes used to apply separate growing and shrinking animation transforms:
#-webkit-keyframes grow
{
from { -webkit-transform: scale(0,0); }
to { -webkit-transform: scale(1,1); }
}
#-webkit-keyframes shrink
{
from { -webkit-transform: scale(1,1); }
to { -webkit-transform: scale(0,0); }
}
This will successfully scale the element it's applied to, but always from 0 to 1 (or vice-versa). If the shrink keyframe gets applied before the grow keyframe has finished, it has the effect of 'jumping' the scale to 0 before the transform begins.
You can see this effect in this jsFiddle showing CSS scale transform on mouseover
Notice that if you mouse over the black square and then quickly mouse out, the scale transform is not smooth.
What I'm essentially after is something like the following:
#-webkit-keyframes grow
{
from { -webkit-transform: CURRENT_SCALE; }
to { -webkit-transform: scale(1,1); }
}
Your animation makes the element go from 0% scale to 100% scale on hover, and from 100% to 0% scale on mouseOut.
I think in this case, the solution could be setting the basic scale of the element according to its start point :
#output
{
width: 200px;
height: 200px;
border-radius: 50%;
background: #FF0000;
display: inline-block;
-ms-transform: scale(0,0);
transform: scale(0,0);
-webkit-transform: scale(0,0);
}
In this case, I would harldy recommend using pure CSS solution, using transition on :hover : http://jsfiddle.net/bg6aj/21/
You wont have any "jumping" effect :
#output
{
width: 200px;
height: 200px;
border-radius: 50%;
background: #FF0000;
display: block;
-ms-transform: scale(0,0);
transform: scale(0,0);
-webkit-transform: scale(0,0);
transition: all .2s;
-webkit-transition: all .2s;
}
#touchPad:hover + #output {
-ms-transform: scale(1,1);
transform: scale(1,1);
-webkit-transform: scale(1,1);
}
At this point, you'll have no more jumping effect.
Then : can we do something like :
#-webkit-keyframes grow
{
from { -webkit-transform: scale(0,0); }
to { -webkit-transform: scale(1,1); }
}
Answer : quite easy :
#-webkit-keyframes grow
{
0% { -webkit-transform: scale(1,1); }
50% { -webkit-transform: scale(0,0); }
100% { -webkit-transform: scale(1,1); }
}
Which means: take my element (as scale default is 100%), render it with 0% scale at 50% of the animation, and turn it back at 100%. Trying to set something like current_scale doesn't make sense.
Considering that, I'll definitely choose the Transition solution.