CSS Stepped Rotation on All Axes - css

I want a step-wise rotation of:
180 degrees around the Z-axis;
180 degrees around the Y-axis; and
180 degrees around the X-axis.
So, I've written the CSS:
#keyframes rotate {
25% { transform: rotateZ(180deg); }
50% { transform: rotateY(180deg); }
75% { transform: rotateX(180deg); }
}
.content {
animation-name: rotate;
animation-duration: 9s;
}
However, I can't seem to manage it.
The first rotation (Z) works, but 2. looks like it's rotating around the X-axis not the Y-axis. And the 3rd rotation, well, that's just weird.
Please can someone explain to me what I'm doing wrong and how I can fix it?

Are you trying this? You should to keep other rotations till the end.
#keyframes rotate {
33% { transform: rotateZ(180deg); }
66% { transform: rotateZ(180deg) rotateY(180deg); }
100% { transform: rotateZ(180deg) rotateY(180deg) rotateX(180deg); }
}
.content {
animation-name: rotate;
animation-duration: 9s;
width: 45px;
height: 45px;
background-color: red;
position: relative;
}
.content div{
position: absolute;
}
.content div:nth-child(1){
width: 45px;
height: 10px;
background-color: green;
top: 0;
}
.content div:nth-child(2){
width: 10px;
height: 45px;
background-color: blue;
left: 0;
}
.content div:nth-child(3){
width: 45px;
height: 10px;
background-color: yellow;
bottom:0;
}
.content div:nth-child(4){
width: 10px;
height: 35px;
background-color: orange;
right:0;
bottom: 0;
}
<div class="content">
<div></div>
<div></div>
<div></div>
<div></div>
</div>

Related

CSS animations with transform: translate

Please help, when I'm trying to play animation with moving ball in position X and Y at the same time it doesn't work, some strange behaviour. I would like to look like a batted and falling ball
.ball {
position: absolute;
left: 18%;
bottom: 100px;
width: 40px;
height: 40px;
background-color: cadetblue;
border-radius: 50%;
animation: fly-ball-x 2s, fly-ball-y 2s;
}
#keyframes fly-ball-x {
100% {
transform: translateX(300px);
}
}
#keyframes fly-ball-y {
100% {
transform: translateY(100px);
}
}
<div class="ball"></div>
**The result I'm expecting is like the code below:**
#keyframes fly-ball-x {
100% {
left: 300px;
}
}
#keyframes fly-ball-y {
100% {
bottom: 0;
}
}
.ball {
position: absolute;
left: 18%;
bottom: 100px;
width: 40px;
height: 40px;
background-color: cadetblue;
border-radius: 50%;
animation: fly-ball-x 2s cubic-bezier(0.17, 0.67, 0.6, 1), fly-
ball-y 2s;
}
<div class="ball"></div>
.ball {
position: absolute;
left: 18%;
bottom: 100px;
width: 40px;
height: 40px;
background-color: cadetblue;
border-radius: 50%;
animation: fly-ball 2s
}
#keyframes fly-ball {
100% {
transform: translateX(300px) translateY(100px);
}
}
<div class="ball"></div>
It is because you weren't running the animations concurrently. Here both translations are just being run at the same time. You just had a bit more than you needed.
EDIT
Check out this blog post. It gives explanations on the kinds of curves it seems you are going for Curved Path Animations In CSS

CSS transform rotate on Y axis always showing the same face

I would like to make a slider a bit like this example:
https://codepen.io/zhangzor/pen/XWKxNJN?editors=1100
The squares should always show the same face and not move like a turnstile, but I can't seem to do that? When I update the rotate boxes individually, their position is reset.
Do you know how to do this with pure CSS (no Three.js or other libraries)?
Thank you and have a good day
body {
perspective: 1000px;
}
.box {
position: relative;
width: 300px;
height: 200px;
margin: 150px auto;
transform-style: preserve-3d;
animation: move 10s linear infinite;
}
.box:hover {
animation-play-state: paused;
}
#keyframes move {
0% {
transform: rotateY(0);
}
100% {
transform: rotateY(360deg);
}
}
div {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: skyblue;
}
.box div:first-child {
transform: rotateY(0) translateZ(300px);
}
.box div:nth-child(2) {
transform: rotateY(60deg) translateZ(300px);
}
.box div:nth-child(3) {
transform: rotateY(120deg) translateZ(300px);
}
.box div:nth-child(4) {
transform: rotateY(180deg) translateZ(300px);
}
.box div:nth-child(5) {
transform: rotateY(240deg) translateZ(300px);
}
.box div:last-child {
transform: rotateY(300deg) translateZ(300px);
}
<div class="box">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
Rotation of inner divs depends on .box rotation so controlling them directly becomes a mess since their X an Y axis rotates with a .box.
But You can apply alternate rotation to their inner elements, using divs as moving containers.
https://codepen.io/accwatcp-the-vuer/pen/eYRdWZz
To transfer parent pre-rotation parameter to children just put it in css-variable - then it can be used for all its children elements. That will be used in counter rotation animation styling.
Now every child have its --shift parameter and can evaluate --shift2 (shift to) final counter-rotation parameter.
Also put repeated Z coordinate for translation to variable, just for ease of use.
* {
margin: 0;
padding: 0;
}
body {
perspective: 1000px;
}
.box {
position: relative;
width: 300px;
height: 200px;
margin: 150px auto;
transform-style: preserve-3d;
animation: move 10s linear infinite;
transform-origin: center bottom;
}
.box:hover, .box:hover span {
animation-play-state: paused;
}
#keyframes move {
0% {
transform: rotateY(0);
}
100% {
transform: rotateY(360deg);
}
}
#keyframes backmove {
0% {
transform: rotateY(var(--shift));
}
100% {
transform: rotateY(var(--shift2));
}
}
div {
--shiftZ:350px;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: transparent;
transform-style: preserve-3d;
}
.box div:first-child {
--shift:0deg;
transform: rotateY(calc(var(--shift)*(-1))) translateZ(var(--shiftZ));
}
.box div:nth-child(2) {
--shift:60deg;
transform: rotateY(calc(var(--shift)*(-1))) translateZ(var(--shiftZ));
}
.box div:nth-child(3) {
--shift:120deg;
transform: rotateY(calc(var(--shift)*(-1))) translateZ(var(--shiftZ));
}
.box div:nth-child(4) {
--shift:180deg;
transform: rotateY(calc(var(--shift)*(-1))) translateZ(var(--shiftZ));
}
.box div:nth-child(5) {
--shift:240deg;
transform: rotateY(calc(var(--shift)*(-1))) translateZ(var(--shiftZ));
}
.box div:last-child {
--shift:300deg;
transform: rotateY(calc(var(--shift)*(-1))) translateZ(var(--shiftZ));
}
span{
--shift2:calc(var(--shift) - 360deg);
display:flex;
background-color: #f003;
border:1px dashed black;
min-width:100%;
min-height:100%;
animation: backmove 10s linear infinite;
justify-content:center;
align-items:center;
font-size:5rem;
}
<section class="box">
<div><span>1</span></div>
<div><span>2</span></div>
<div><span>3</span></div>
<div><span>4</span></div>
<div><span>5</span></div>
<div><span>6</span></div>
</section>

Form does not rotate around center axis (x,y)

Even though I have set [transform-origin: 100% 50%;] in css, the form does not rotate around its center in comparison to X- and Y- axis.
Question: How can I make the form rotate counted exactly from its midpoint.
.box {
background-color: pink;
margin: 300px 0 0 300px;
width: 200px;
height: 200px;
}
.box {
position: absolute;
animation: spin 10s;
animation-fill-mode: forwards;
}
.line-horizontal {
background-color: black;
width: 200px;
height: 5px;
margin: 100px 0 0 0;
}
.line-vertical {
background-color: black;
width: 5px;
height: 200px;
margin: -105px 0 0 100px;
}
#keyframes spin {
from {
transform:rotate(0deg);
transform-origin: 100% 50%;
}
to {
transform:rotate(360deg);
}
}
<div class="box">
<div class="line-horizontal"></div>
<div class="line-vertical"></div>
</div>
Change the tranform-origin to 50% 50% instead which means the center in both axis and don't put it inside the keyframes because it will get animated
.box {
background-color: pink;
width: 200px;
height: 200px;
}
.box {
position: absolute;
animation: spin 10s;
animation-fill-mode: forwards;
transform-origin: 50% 50%;
/*center*/
}
.line-horizontal {
background-color: black;
width: 200px;
height: 5px;
margin: 100px 0 0 0;
}
.line-vertical {
background-color: black;
width: 5px;
height: 200px;
margin: -105px 0 0 100px;
}
#keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
<div class="box">
<div class="line-horizontal"></div>
<div class="line-vertical"></div>
</div>
You can also simplify your code like below in case you need the same visual:
.box {
width: 200px;
height: 200px;
background:
linear-gradient(#000,#000) center/100% 5px,
linear-gradient(#000,#000) center/5px 100%,
pink;
background-repeat:no-repeat;
animation: spin 10s forwards;
transform-origin: 50% 50%; /* OR center*/
}
#keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
<div class="box">
</div>

Creating a 3d box effect, face keeps appearing over the other

How can I achieve the desired effect? I want to create a kind of box that flips around in 3d in the x axis and reveals the other face, all while conserving the same dimensions. Currently the effect is almost working but for some reason one face is always visible. Why does that happen and how to change that?
#div1 {
width: 100px;
height: 100px;
position: relative;
margin: 100px;
perspective: 300px;
perspective-origin: 50% 50%;
transition: all 1s;
}
#div2 {
width: 100px;
height: 100px;
position: absolute;
border: 1px solid black;
background-color: red;
transform-origin: 50% 50% -50px;
transition: all 1s;
}
#div3 {
width: 100px;
height: 100px;
position: absolute;
border: 1px solid black;
background-color: orange;
transform-origin: 50% 50% -50px;
transform: rotateX(90deg);
transition: all 1s;
}
#div1:hover {
//transform: rotate(180deg)
}
#div1:hover #div2 {
transform: rotateX(-90deg);
}
#div1:hover #div3 {
transform: rotateX(0deg);
}
hover me!
<div id="div1">
<div id="div2"></div>
<div id="div3"></div>
</div>
Just add this css properties,
#div2 { z-index: 1;}
#div1:hover #div2 { z-index: 0;}
#div1 {
width: 100px;
height: 100px;
position: relative;
margin: 100px;
perspective: 300px;
perspective-origin: 50% 50%;
transition: all 1s;
}
#div2 {
z-index: 1;
width: 100px;
height: 100px;
position: absolute;
border: 1px solid black;
background-color: red;
transform-origin: 50% 50% -50px;
transition: all 1s;
}
#div3 {
width: 100px;
height: 100px;
position: absolute;
border: 1px solid black;
background-color: orange;
transform-origin: 50% 50% -50px;
transform: rotateX(90deg);
transition: all 1s;
}
#div1:hover {
//transform: rotate(180deg)
}
#div1:hover #div2 {
transform: rotateX(-90deg);
z-index: 0;
}
#div1:hover #div3 {
transform: rotateX(0deg);
}
hover me!
<div id="div1">
<div id="div2"></div>
<div id="div3"></div>
</div>
Add backface-visibility:hidden;
div {
backface-visibility: hidden;
}
#div1 {
width: 100px;
height: 100px;
position: relative;
margin: 100px;
perspective: 300px;
perspective-origin: 50% 50%;
transition: all 1s;
}
#div2 {
width: 100px;
height: 100px;
position: absolute;
border: 1px solid black;
background-color: red;
transform-origin: 50% 50% -50px;
transition: all 1s;
}
#div3 {
width: 100px;
height: 100px;
position: absolute;
border: 1px solid black;
background-color: orange;
transform-origin: 50% 50% -50px;
transform: rotateX(90deg);
transition: all 1s;
}
#div1:hover {
//transform: rotate(180deg)
}
#div1:hover #div2 {
transform: rotateX(-90deg);
}
#div1:hover #div3 {
transform: rotateX(0deg);
}
<div id="div1">
<div id="div2"></div>
<div id="div3"></div>
</div>

How keep the image rotated during the reverse movement?

I'm having a trouble with the effect I want to create. My body in the HTML file it's just a div with two images.
I was trying to give animation to the first image in the following way:
in 0% it starts at the beginning of the div (the fish's head is on the right)
in 100% it ends in the end, but at this point I want to rotate the image and keep that effect until it gets 0% again. (that is, the fish should point towards the left during the reverse motion)
But it just rotates in 100% and no more. I don't know if this happens because I don't understand some concept of the animation property.
This is all my code:
#keyframes fish01 {
0% {
left: 0%;
transform: rotateY(180deg);
}
1% {
transform: rotateY(0deg);
}
99% {
transform: rotateY(0deg);
}
100% {
left: 90%;
transform: rotateY(180deg);
}
}
body {
background-color: black;
}
div {
position: absolute;
margin-left: 18%;
margin-top: 3%;
width: 800px;
height: 500px;
border: 5px double #DDDDDD;
border-radius: 1em 1em;
background-image: url("https://i.onthe.io/vllkyt28101smv87bg.349283fe.jpg");
}
div img:nth-child(1) {
float: left;
position: absolute;
margin: 0px;
top: 20%;
width: 100px;
height: 50px;
transform: scale(1.5, 1.5);
animation-name: fish01;
animation-duration: 5s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-timing-function: ease-in;
}
div img:nth-child(2) {
float: left;
position: absolute;
top: 20%;
left: 60%;
}
<section>
<div>
<img src="https://www.hyperone.com.eg/media/catalog/product/cache/4/thumbnail/9df78eab33525d08d6e5fb8d27136e95/f/i/fish_1.png" />
<img src="http://www.pets4homes.co.uk/images/fish_hero.png" />
</div>
</section>
I've tried everything in the #keyframes and looked into W3Schools website about animation property, but it didn't help me. Any suggestions?
Reason:
The behavior that is seen is expected one based on your #keyframes and the animation-direction setting. When the animation's direction is set to alternate, the UA executes the animation from 0 to 100 for the odd numbered iterations, 100 to 0 for the even numbered iterations.
As per your keyframes, the transform goes from rotateY(180deg) to rotateY(0deg) at 1% of the animation's duration itself and so during the odd numbered iterations you don't see any visible rotation (as duration is pretty small) and it goes from rotateY(180deg) (at 100%) to rotateY(0deg) (at 99%) because of which you don't get to see any visible rotation during even numbered iterations also.
The problem in writing keyframes for forward direction and re-using the same for the reverse (using animation-direction) is that it can be done only when the states are the same for both. In this case, it is not because the element should be in unrotated state during forward movement and should have rotateY(180deg) during the reverse movement.
Solution:
For the element to be seen in its rotated state, the transform must be retained for some time. So, for your case it is better to do away with the animation-direction: alternate setting and write both the forward and reverse motions within the keyframes itself like in the below snippet.
(Note: Since we are writing both forward and reverse motions within the keyframes, you may have to double the animation-duration).
#keyframes fish01 {
0% {
left: 0%;
transform: rotateY(0deg);
}
49.5% {
left: 90%;
transform: rotateY(0deg);
}
50.5% {
left: 90%;
transform: rotateY(180deg);
}
100% {
left: 0%;
transform: rotateY(180deg);
}
}
body {
background-color: black;
}
div {
position: absolute;
margin-left: 18%;
margin-top: 3%;
width: 800px;
height: 500px;
border: 5px double #DDDDDD;
border-radius: 1em 1em;
background-image: url("https://i.onthe.io/vllkyt28101smv87bg.349283fe.jpg");
}
div img:nth-child(1) {
float: left;
position: absolute;
margin: 0px;
top: 20%;
width: 100px;
height: 50px;
transform: scale(1.5, 1.5);
animation-name: fish01;
animation-duration: 10s; /* double of original time */
animation-fill-mode: forwards;
animation-iteration-count: infinite;
animation-timing-function: ease-in;
}
div img:nth-child(2) {
float: left;
position: absolute;
top: 20%;
left: 60%;
}
<section>
<div>
<img src="https://www.hyperone.com.eg/media/catalog/product/cache/4/thumbnail/9df78eab33525d08d6e5fb8d27136e95/f/i/fish_1.png" />
<img src="http://www.pets4homes.co.uk/images/fish_hero.png" />
</div>
</section>
The problem was that you had animation-direction: alternate; in your CSS. To compensate for removing this, you also need to make the img moving to left: 90% being at the 50% mark in the animation, not the 100% mark.
Hope this helps! :)
#keyframes fish01{
0% {
left: 0%;
transform: rotateY(0deg);
}
49% {
transform: rotateY(0deg);
}
50% {
left: 90%;
transform: rotateY(180deg);
}
99% {
transform: rotateY(180deg);
}
100% {
left: 0%;
transform: rotateY(0deg);
}
}
body {
background-color: black;
}
div {
position: absolute;
margin-left: 18%;
margin-top: 3%;
width: 800px;
height: 500px;
border: 5px double #DDDDDD;
border-radius: 1em 1em;
background-image: url("https://i.onthe.io/vllkyt28101smv87bg.349283fe.jpg");
}
div img:nth-child(1) {
float: left;
position: absolute;
margin: 0px;
top: 20%;
width: 100px;
height: 50px;
transform: scale(1.5, 1.5);
animation-name: fish01;
animation-duration: 5s;
animation-iteration-count: infinite;
animation-timing-function: ease-in;
}
div img:nth-child(2) {
float: left;
position: absolute;
top: 20%;
left: 60%;
}
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8"/>
<title>CSS rotate animation</title>
<link rel="stylesheet" href="Transicion02.css"/>
</head>
<body>
<section>
<div>
<img src="https://www.hyperone.com.eg/media/catalog/product/cache/4/thumbnail/9df78eab33525d08d6e5fb8d27136e95/f/i/fish_1.png"/>
<img src="http://www.pets4homes.co.uk/images/fish_hero.png"/>
</div>
</section>
</body>
</html>

Resources