I want my StyledModalWrapper to animate scale().
My StyledComponent has this properties:
top: 50%;
left: 50%;
max-width: ${(props:IModal) => props.width};
min-height: auto;
transform: translate(-50%, -50%);
animation: ${(props:IModal) => props.closing ? popOut : popIn} .3s linear;
The animation:
0% {
transform: scale(0);
}
80% {
transform: scale(1.25);
}
100% {
transform: scale(1);
}
In this case the box is scaling perfect only the positioning isn't.
I tried adding
0% {
transform: scale(0) translate(100%, 100%);
}
80% {
transform: scale(1.25) translate(25%, 25%);
}
100% {
transform: scale(1) translate(50%, 50%);
}
In this case it swipes with a curve.
The center of the box should always stay in the middle of the parent.
The parent has a width/height of 100vw/100vh.
If you're using transform, this is your friend: transform-origin
It allows you to change to transform position from left/top to anywhere else.
In your case it's likely center you need.
MDN docs: https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin
Related
I have an SVG with a simple CSS animation which works perfectly in every browser.
Except Safari (tested on Safari 15.3 on a MacOS M1).
.foobar {
position: absolute;
top: 0;
right: 0;
width: 40%;
animation: rotate 10s linear infinite;
}
#keyframes rotate {
0% {
transform: translate(50%, -50%);
}
100% {
transform: translate(50%, -50%) rotate(-360deg);
}
}
The first keyframe is applied (the translate), but it stays frozen on this frame.
Oddly enough, Safari requires to specify the rotate on the first keyframe:
#keyframes rotate {
0% {
transform: translate(50%, -50%) rotate(0deg);
}
100% {
transform: translate(50%, -50%) rotate(-360deg);
}
}
And now it works 🤷♂️
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.
Using this example, is there a way to stop this CSS animation to a fixed point on the screen? So for instance, it's moving across and I decide to have it stop like 20px from the top right of the screen. Is this possible with just CSS?
.bird {
background-image: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/174479/bird-cells.svg);
background-size: auto 100%;
width: 88px;
height: 125px;
will-change: background-position;
animation-name: fly-cycle;
animation-timing-function: steps(10);
animation-iteration-count: infinite;
}
.bird--one {
animation-duration: 1s;
animation-delay: -0.5s;
}
.bird-container {
position: absolute;
top: 20%;
left: -10%;
transform: scale(0) translateX(-10vw);
will-change: transform;
animation-name: fly-right-one;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
.bird-container--one {
animation-duration: 15s;
animation-delay: 0;
}
#keyframes fly-cycle {
100% {
background-position: -900px 0;
}
}
#keyframes fly-right-one {
0% {
transform: scale(0.3) translateX(-10vw);
}
10% {
transform: translateY(2vh) translateX(10vw) scale(0.4);
}
20% {
transform: translateY(0vh) translateX(30vw) scale(0.5);
}
30% {
transform: translateY(4vh) translateX(50vw) scale(0.6);
}
40% {
transform: translateY(2vh) translateX(70vw) scale(0.6);
}
50% {
transform: translateY(0vh) translateX(90vw) scale(0.6);
}
60% {
transform: translateY(0vh) translateX(110vw) scale(0.6);
}
100% {
transform: translateY(0vh) translateX(110vw) scale(0.6);
}
}
<div style="width:100%;">
<div class="bird-container bird-container--one">
<div class="bird bird--one"></div>
</div>
</div>
https://jsfiddle.net/14ndk5xg/
By changing the VW to a lower number, you can get it to stop a certain distance from the right side of the screen. If you always want the bird to stop when it's travelled approximately 90% of the screen width then you can change the VW to 90.
With the way it's currently setup, it's not easy to make it stop at a certain amount of pixels.
By setting your code like below at 50% and removing the higher percentages, you can get the bird to fly 90% to the right and fly up to the upper right corner.
50% {
transform: translateY(-20vh) translateX(90vw) scale(0.6);
}
#keyframes my-animation {
0% {
transform: translate(0, 40%) scale(0);
}
10% {
transform: scale(1.1);
}
20% {
transform: scale(1);
}
100% {
transform: translateY(0%);
}
}
I'm trying to make my element pop then move on the Y axis, but the above fails to work.
Where am I going wrong?
Transform property gets overridden during your animation. So even though the keyframe at 0% says translate by 40% in Y-axis, the second frame at 10% nullifies it. There is a movement between 0% and 10% but that is almost invisible because the element is just then coming into view.
You need to retain the translate(0, 40%) till the time the element needs to remain translated by 40% in the Y-axis. In the below snippet, I have retained it at the translated position till 20% of the animation duration and then from between 20% to 100% it goes back to the original position.
#keyframes my-animation {
0% {
transform: translate(0, 40%) scale(0);
}
10% {
transform: translate(0, 40%) scale(1.1);
}
20% {
transform: translate(0, 40%) scale(1);
}
100% {
transform: translateY(0%);
}
}
div{
height: 100px;
width: 100px;
border: 1px solid;
animation: my-animation 4s linear forwards;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div>Some</div>
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 :)