I am trying to animate a sun with the outer rays slowly rotating. I have two images: sun_inner and sun_outer. I use absolute positioning and transform:translate to center the inner sun within the container. However, when I try to rotate the inner sun (which has a smiley face) a few degrees it is not rotating along the center axis, and the inner sun is moving up and down.
Any help in getting the rotation of the inner sun to be centered within the container is appreciated!
As an example here is a fiddle: https://jsfiddle.net/4mcdLcus/
.sun-inner {
position: absolute;
left: 50%;
top: 50%;
/*
In the animation I apply translateY(-50%) translateX(-50%)
to keep the inner circle centered, which is not working.
If I have translateY(-50%) translateX(-50%) without the rotation
it is centered properly
*/
animation-name: sun_inner_rotate;
animation-duration: 10s;
animation-iteration-count: infinite;
transform-origin: 50% 50%;
}
.sun-inner img {
height: 150px;
width: 150px;
}
.sun-outer {
animation-name: sun_outer_rotate;
animation-duration: 30s;
animation-iteration-count: infinite;
width: 300px;
height: 300px;
}
.sun-outer img {
width: 300px;
height: 300px;
}
#keyframes sunrise {
0% {
bottom: -130vh;
}
100% {
bottom: 0;
}
}
#keyframes sun_inner_rotate {
0% {
transform: rotate(0deg) translateY(-50%) translateX(-50%);
;
}
33% {
transform: rotate(12deg) translateY(-50%) translateX(-50%);
}
66% {
transform: rotate(-26deg) translateY(-50%) translateX(-50%);
}
100% {
transform: rotate(10deg) translateY(-50%) translateX(-50%);
}
}
#keyframes sun_outer_rotate {
0% {
transform: rotate(0deg);
}
33% {
transform: rotate(360deg);
}
66% {
transform: rotate(-30deg);
}
100% {
transform: rotate(-360deg);
}
}
.sunContainer {
width: 300px;
height: 300px;
position: relative;
margin-left: 10%;
margin-top: 7%;
animation-iteration-count: 1;
animation-name: sunrise;
animation-duration: 1.5s;
display: flex;
justify-content: center;
align-items: center;
}
<div class="sunContainer">
<div class="sun-inner">
<img src="https://upload.wikimedia.org/wikipedia/commons/b/b6/Compass_360_%28en%29.svg">
</div>
<div class="sun-outer">
<img src="https://upload.wikimedia.org/wikipedia/commons/b/b6/Compass_360_%28en%29.svg">
</div>
</div>
No, you don't need to use two animations or do anything additional to the #keyframes that is already configured. All that is required is to only set the transform-origin properly for the inner element.
The inner element is originally positioned at top: 50% and left: 50% of the parent element (which in other words means that the top left of the inner element is at the center point of the parent). Afterwards it is vertically and horizontally centered using transform: translateX(-50%) translateY(-50%) trick.
So, when you rotate the element the transform-origin should be set as left top for the element to rotate around the center point of the parent. Only then it will remain perfectly centered.
.sun-inner {
position: absolute;
left: 50%;
top: 50%;
height: 150px;
width: 150px;
animation-name: sun_inner_rotate;
animation-duration: 10s;
animation-iteration-count: infinite;
transform-origin: left top; /* note the change */
}
.sun-inner img, .sun-outer img {
height: 100%;
width: 100%;
}
.sun-outer {
animation-name: sun_outer_rotate;
animation-duration: 30s;
animation-iteration-count: infinite;
width: 300px;
height: 300px;
}
#keyframes sunrise {
0% {
bottom: -130vh;
}
100% {
bottom: 0;
}
}
#keyframes sun_inner_rotate {
0% {
transform: rotate(0deg) translateY(-50%) translateX(-50%);
}
33% {
transform: rotate(12deg) translateY(-50%) translateX(-50%);
}
66% {
transform: rotate(-26deg) translateY(-50%) translateX(-50%);
}
100% {
transform: rotate(10deg) translateY(-50%) translateX(-50%);
}
}
#keyframes sun_outer_rotate {
0% {
transform: rotate(0deg);
}
33% {
transform: rotate(360deg);
}
66% {
transform: rotate(-30deg);
}
100% {
transform: rotate(-360deg);
}
}
.sunContainer {
width: 300px;
height: 300px;
position: relative;
margin-left: 10%;
margin-top: 7%;
animation-iteration-count: 1;
animation-name: sunrise;
animation-duration: 1.5s;
display: flex;
justify-content: center;
align-items: center;
}
<div class="sunContainer">
<div class="sun-inner">
<img src="https://upload.wikimedia.org/wikipedia/commons/b/b6/Compass_360_%28en%29.svg">
</div>
<div class="sun-outer">
<img src="https://upload.wikimedia.org/wikipedia/commons/b/b6/Compass_360_%28en%29.svg">
</div>
</div>
Alternately, you can invert the order in which the transforms are applied on the element. You can apply the rotate first on the element and then apply translateX and translateY on the rotated element. This will also keep it perfectly centered. (When multiple transforms are specified, the first one from the right is always executed first and the last one from right is always executed last).
.sun-inner {
position: absolute;
left: 50%;
top: 50%;
height: 150px;
width: 150px;
animation-name: sun_inner_rotate;
animation-duration: 10s;
animation-iteration-count: infinite;
transform-origin: 50% 50%;
}
.sun-inner img, .sun-outer img {
height: 100%;
width: 100%;
}
.sun-outer {
animation-name: sun_outer_rotate;
animation-duration: 30s;
animation-iteration-count: infinite;
width: 300px;
height: 300px;
}
#keyframes sunrise {
0% {
bottom: -130vh;
}
100% {
bottom: 0;
}
}
#keyframes sun_inner_rotate { /* note the change to the order */
0% {
transform: translateY(-50%) translateX(-50%) rotate(0deg);
}
33% {
transform: translateY(-50%) translateX(-50%) rotate(12deg);
}
66% {
transform: translateY(-50%) translateX(-50%) rotate(-26deg);
}
100% {
transform: translateY(-50%) translateX(-50%) rotate(10deg);
}
}
#keyframes sun_outer_rotate {
0% {
transform: rotate(0deg);
}
33% {
transform: rotate(360deg);
}
66% {
transform: rotate(-30deg);
}
100% {
transform: rotate(-360deg);
}
}
.sunContainer {
width: 300px;
height: 300px;
position: relative;
margin-left: 10%;
margin-top: 7%;
animation-iteration-count: 1;
animation-name: sunrise;
animation-duration: 1.5s;
display: flex;
justify-content: center;
align-items: center;
}
<div class="sunContainer">
<div class="sun-inner">
<img src="https://upload.wikimedia.org/wikipedia/commons/b/b6/Compass_360_%28en%29.svg">
</div>
<div class="sun-outer">
<img src="https://upload.wikimedia.org/wikipedia/commons/b/b6/Compass_360_%28en%29.svg">
</div>
</div>
Related
Good day, there was the task to make the animation of an airplane flying around a path. I decided to take advantage of the opportunities in CSS3. But all I have achieved is one animation cycle. The plane flies one circle around the path and the animation stops. I tried using animation-iteration-count with infinite, but all I got was the flight of a plane in chaotic directions. Below is my code, please tell me how to loop this animation so that the plane constantly flies in a circle without stopping.
Code
.wrap {
margin: 100px;
}
.route {
height: 200px;
width: 400px;
border: 3px dotted #000;
position: relative;
}
.plane {
position: absolute;
bottom: -13px;
left: 100%;
animation-iteration-count: 3;
animation: flyLeft 1.5s linear forwards, rotatePlane 0.5s linear 1.5s forwards, flyUp 1s linear forwards 2s, RotateRight 0.5s linear 2.8s forwards, MoveRight 3s linear forwards 3s, RotateDown 1s linear 6s forwards, flyDown 1s linear forwards 7s, RotateLeft 1s linear 7.8s forwards;
}
#keyframes flyLeft {
100% {
left: -14px;
}
}
#keyframes rotatePlane {
100% {
transform: rotateZ(90deg);
}
}
#keyframes flyUp {
100% {
bottom: 100%;
}
}
#keyframes RotateRight {
0% {
transform: rotateZ(90deg);
}
100% {
transform: rotateZ(180deg);
}
}
#keyframes MoveRight {
0% {
left: -14px;
}
100% {
left: 380px;
}
}
#keyframes RotateDown {
0% {
transform: rotateZ(180deg);
}
100% {
transform: rotateZ(270deg);
}
}
#keyframes flyDown {
0% {
bottom: 100%;
}
100% {
bottom: -8%;
}
}
#keyframes RotateLeft {
0% {
transform: rotateZ(270deg);
}
100% {
transform: rotateZ(360deg);
}
}
<div class="wrap">
<div class="route">
<img class="plane" src="http://p36099-290-14699.s290.upress.link/wp-content/uploads/2020/05/plane.png">
</div>
</div>
You need to wrap all the animations in one #keyframes CSS at-rules to easily make repetitions. Here's a working solution below that wraps all the animations in one #keyframes.
.wrap {
margin: 100px;
}
.route {
height: 200px;
width: 400px;
border: 3px dotted #000;
position: relative;
}
.plane {
position: absolute;
right: 0;
bottom: 0;
transform: translate(50%, 50%);
animation: travelRoundTheBorder 10s linear infinite;
}
#keyframes travelRoundTheBorder {
30% {
bottom: 0;
right: 100%;
transform: translate(50%, 50%);
}
32.5% {
bottom: 0;
right: 100%;
transform: translate(50%, 50%) rotate(90deg);
}
47.5% {
right: 100%;
bottom: 100%;
transform: translate(50%, 50%) rotate(90deg);
}
50% {
right: 100%;
bottom: 100%;
transform: translate(50%, 50%) rotate(180deg);
}
80% {
right: 0;
bottom: 100%;
transform: translate(50%, 50%) rotate(180deg);
}
82.5% {
right: 0;
bottom: 100%;
transform: translate(50%, 50%) rotate(270deg);
}
97.5% {
right: 0;
bottom: 0;
transform: translate(50%, 50%) rotate(270deg);
}
100% {
right: 0;
bottom: 0;
transform: translate(50%, 50%) rotate(360deg);
}
}
<div class="wrap">
<div class="route">
<img class="plane" src="http://p36099-290-14699.s290.upress.link/wp-content/uploads/2020/05/plane.png">
</div>
</div>
Splitting the movement along the path and the turns into TWO separate keyframes makes this easier.
The math of the percentages is based on a square but with a rectangle the percentages change.
CSS variable could help here to work out those percentages but I haven't gone deeper into that for the demo purposes.
.wrap {
margin: 10px;
}
.route {
height: 150px;
width: 150px;
margin: auto;
border: 3px dotted #000;
position: relative;
}
.plane {
position: absolute;
transform: translate(-50%, -50%) rotate(180deg);
top: 0;
left: 0;
animation: path 6s linear infinite, turn 6s ease infinite;
}
#keyframes path {
0%,
100% {
left: 0;
top: 0;
}
25% {
left: 100%;
top: 0;
}
50% {
left: 100%;
top: 100%;
}
75% {
left: 0;
top: 100%;
}
}
#keyframes turn {
0%,
24% {
transform: translate(-50%, -50%) rotate(180deg);
}
25%,
49% {
transform: translate(-50%, -50%) rotate(270deg);
}
50%,
74% {
transform: translate(-50%, -50%) rotate(0deg);
}
75%,
99% {
transform: translate(-50%, -50%) rotate(90deg);
}
100% {
transform: translate(-50%, -50%) rotate(90deg);
}
}
<div class="wrap">
<div class="route">
<img class="plane" src="http://p36099-290-14699.s290.upress.link/wp-content/uploads/2020/05/plane.png">
</div>
</div>
Just to begin testing new CSS posibilities, offset-path (not supported in IE, experimental in FF)
reference
#container {
width: 400px;
height: 300px;
border: dotted 5px black;
margin: 30px;
}
#motion-demo {
offset-path: path('M0 -10 H400 A 10 10 1 0 1 410 0 V300 A 10 10 1 0 1 400 310 H0 A 10 10 1 0 1 -10 300 V0');
animation: move 10s infinite linear;
width: 40px;
height: 40px;
background: cyan;
}
#keyframes move {
0% {
offset-distance: 0%;
}
100% {
offset-distance: 100%;
}
}
<div id="container">
<div id="motion-demo">A</div>
</div>
I'm trying to get my head around transforms and 3d animation perspectives for css. I have created a piece of code that displays an 8 sided die and then rotates it for the viewer.
However, the die seems to rotate around an invisible center object,
rather than the center of the die being the center point for the rotation animation.
I realize that I must not be grasping something about the code I have written through trial and error.
Here is a fiddle to show what I mean about the way the shape seems to rotate around an invisible center: https://jsfiddle.net/4qbLct3b/
Instead, I want the center of the 3 dimensional object to be the center point of the rotation animation.
HTML
body {
perspective: 9000px;
padding-top: 10%;
}
.d8 {
height: 64px;
width: 64px;
margin: auto;
}
.tetra {
position: relative;
height: 86.6%;
width: 100%;
margin: 0 auto;
transform-style: preserve-3d;
transform: rotatex(0deg) rotateY(0deg) rotatez(0deg);
animation: rotate 10s linear infinite;
}
.tetra div {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
-webkit-clip-path: polygon(50% -2.5%, 102.5% 102.5%, -2.5% 102.5%);
clip-path: polygon(50% -2.5%, 102.5% 102.5%, -2.5% 102.5%);
-webkit-clip-path: border-box;
clip-path: border-box;
background: teal;
transform-origin: 0% 100%;
transform: rotatex(35deg);
transform-style: preserve-3d;
}
.tetra .face2 {
transform-origin: 0% 100%;
transform: rotatey(90deg) rotatex(-35deg);
background: gold;
}
.tetra .face3 {
transform-origin: 0% 100%;
left: 100%;
transform: rotatey(90deg) rotatex(35deg);
background: red;
}
.tetra .face4 {
transform-origin: 0% 100%;
transform: rotateY(-90deg) translateX(-100%) rotateY(90deg) rotatex(-35deg);
background: black;
}
.tetra .face5 {
transform-origin: 0% 100%;
transform: rotateY(-90deg) translateX(-100%) rotateY(90deg) rotatex(-145deg);
background: orange;
}
.tetra .face6 {
transform-origin: 0% 100%;
left: 100%;
transform: rotatey(90deg) rotatex(145deg);
background: green;
}
.tetra .face7 {
transform-origin: 0% 100%;
transform: rotatey(90deg) rotatex(-145deg);
background: brown;
}
.tetra .face8 {
background: grey;
transform-origin: 0% 100%;
transform: rotatex(145deg);
}
#keyframes rotate {
50% {
transform: rotatex(180deg) rotateY(180deg) rotatez(180deg);
}
100% {
transform: rotatex(360deg) rotateY(360deg) rotatez(360deg);
}
}
<div class="d8">
<div class="tetra">
<div class="face1"></div>
<div class="face2"></div>
<div class="face3"></div>
<div class="face4"></div>
<div class="face5"></div>
<div class="face6"></div>
<div class="face7"></div>
<div class="face8"></div>
</div>
</div>
I'm trying to create an animated text like bellow using css, how can i do this?
I already tried this:
span1 {
display: inline-block;
color: #e74c3c;
position: relative;
white-space: nowrap;
top: 0;
left: 0;
-webkit-animation: move 5s;
-webkit-animation-iteration-count: infinite;
-webkit-animation-delay: 1s;
}
#keyframes move {
0% {
top: 0px;
}
20% {
top: -50px;
}
40% {
top: -100px;
}
60% {
top: -150px;
}
80% {
top: -200px;
}
100% {
top: -300px;
}
}
<span1>
web developer<br /> css cowboy<br /> self-facilitating media node<br /> box inside a box<br /> part of the problem
</span1>
but it has a delay after last text that i need to remove!
See This:
*{
box-sizing: border-box;
}
body {
background-color: skyblue;
}
div {
overflow: hidden;
color: #fff;
text-align: center;
font-size: 20px;
position: relative;
height: 100px;
margin-top: 100px;
}
div p {
height: 100px;
animation: move 7s infinite linear;
position: relative;
bottom: -100px;
font-size: 36px;
margin: 0;
}
#keyframes move {
0% {bottom: -100px;}
10%, 20% {bottom: 0px}
40%,50% {bottom: 100px;}
70%,80% {bottom: 200px;}
100% {bottom: 300px}
}
<div>
<p>50% OFF</p>
<p>Some Text</p>
<p>Write by: Ehsan Taghdisi</p>
</div>
.anim1 {
animation: anim1 1.5s infinite;
}
.anim2 {
animation: anim2 1.5s infinite;
}
#keyframes anim1 {
0% {
transform: translateY(-10px);
}
50% {
transform: translateY(-80px);
}
100% {
transform: translateY(-10px);
}
}
#keyframes anim2 {
0% {
transform: translateY(0px);
}
50% {
transform: translateY(-80px);
}
100% {
transform: translateY(0px);
}
}
<div style="height:40px;overflow:hidden">
<h1 class="anim1">Hello animation 1</h1>
<h1 class="anim2">Hello animation 2</h1>
wondering if someone could help me with making this animation slightly better, it rotates of course at -30degrees but its it possible to rotate it like that but the start of the arm to not rotate as well so it looks more like an arm waving?
.santas-arm {
animation: wavingArm 2s ease-in-out infinite;
top: 100px;
left: 100px;
position: relative;
background: black;
width: 200px;
height: 50px;
}
#keyframes wavingArm {
0% {
transform: rotate(0deg) translate(0px);
}
50% {
transform: rotate(-30deg) translate(0px);
}
100% {
transform: rotate(0deg) translate(0px);
}
}
<div class="santas-arm"></div>
It's just a matter of setting the transform-origin:
transform-origin: left center
MDN reference:
The transform-origin property lets you modify the origin for
transformations of an element. For example, the transform-origin of
the rotate() function is the centre of rotation. (This property is
applied by first translating the element by the negated value of the
property, then applying the element's transform, then translating by
the property value.)
.santas-arm {
animation: wavingArm 2s ease-in-out infinite;
top: 100px;
left: 100px;
position: relative;
background: black;
width: 200px;
height: 50px;
transform-origin: left center;
}
#keyframes wavingArm {
0% {
transform: rotate(0deg) translate(0px);
}
50% {
transform: rotate(-30deg) translate(0px);
}
100% {
transform: rotate(0deg) translate(0px);
}
}
<div class="santas-arm"></div>
Use transform-origin (link)
.santas-arm {
animation: wavingArm 2s ease-in-out infinite;
top: 100px;
left: 100px;
position: relative;
background: black;
width: 200px;
height: 50px;
}
#keyframes wavingArm {
0% {
transform: rotate(0deg) translate(0px);
transform-origin: 0% 0%
}
50% {
transform: rotate(-30deg) translate(0px);
transform-origin: 0% 0%
}
100% {
transform: rotate(0deg) translate(0px);
transform-origin: 0% 0%
}
}
<div class="santas-arm"></div>
I'm trying out a CSS3 animation on a background image. Everything's working well, the problem is that on Chrome the text ends up being blurred when the animation is in progress:
During Animation:
Turning off the animation:
As you can see the text rendering is fine when the animation is turned off, I know there's the usual issue with text rendering but I can't understand why the rendering is poor on Chrome when the animation is in progress. I'm not sure there's anything I can do about it really. I've tested the animation on Firefox and IE and it's ok. By the way I'm working on Windows.
Firefox:
IE:
EDIT
.bg-div {
position: fixed;
width: 110%;
height: 110%;
transform: translate(-5%, -5%);
-moz-transform: translate(-5%, -5%) rotate(0.02deg); /* rotation to solve choppy animation on Firefox */
-ms-transform: translate(-5%, -5%);
background-image: url('images/colour-test.jpg');
background-size: cover;
-webkit-animation: bg-animation 10s linear infinite;
-moz-animation: bg-animation 10s linear infinite;
-ms-animation: bg-animation 10s linear infinite;
}
#-webkit-keyframes bg-animation {
25% { transform: translate(-5.5%, -5.5%); }
50% { transform: translate(-5.3%, -4.9%); }
75% { transform: translate(-4.8%, -4.3%); }
}
#-moz-keyframes bg-animation {
25% { -moz-transform: translate(-5.5%, -5.5%) rotate(0.02deg); }
50% { -moz-transform: translate(-5.3%, -4.9%) rotate(0.02deg); }
75% { -moz-transform: translate(-4.8%, -4.3%) rotate(0.02deg); }
}
#-ms-keyframes bg-animation {
25% { -ms-transform: translate(-5.5%, -5.5%); }
50% { -ms-transform: translate(-5.3%, -4.9%); }
75% { -ms-transform: translate(-4.8%, -4.3%); }
}
.content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 50%;
height: 65%;
text-align: center;
}
After reading the question and answer posted in the comments I've tried to adding -webkit-font-smoothing: subpixel-antialiased; to .bg-div but that didn't make any difference.
EDIT 2
Okay so this is a bit of a weird one, during the animation apparently the position: fixed is making the text blurry. I don't know how that is possible, anyway once I removed the position: fixed and the background was animating the text was displayed correctly. It's still not what I want because I need the background to be fixed.
In my testing, the problem is fixed if the transform is not used on .content. Luckily, you don't need to use transform to position your content div.
Use this margin: auto trick to position instead
Using this method, you do not need to use transform: translate(-50%, -50%)
The content is centered with the combination of top, right, bottom, left, margin: auto and the percentage width and height.
.content {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
width: 50%;
height: 65%;
text-align: center;
}
Working Example
body { margin: 0 auto; width: 500px }
.bg-div {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
width: 800px;
height: 800px;
transform: translate(-5%, -5%);
background: url('http://www.placehold.it/800') no-repeat;
-webkit-animation: bg-animation 2s linear infinite;
animation: bg-animation 2s linear infinite;
}
#-webkit-keyframes bg-animation {
0% {
transform: translate(-5.5%, -5.5%);
}
50% {
transform: translate(-5%, -5%);
}
100% {
transform: translate(-5.5%, -5.5%);
}
}
#keyframes bg-animation {
0% {
transform: translate(-5.5%, -5.5%);
}
50% {
transform: translate(-5%, -5%);
}
100% {
transform: translate(-5.5%, -5.5%);
}
}
.content {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
width: 50%;
height: 65%;
text-align: center;
}
<div class="bg-div"></div>
<div class="content">
<h1>This looks better</h1>
<input value="Text" />
</div>