CSS transform rotate on Y axis always showing the same face - css

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>

Related

CSS, switch left/right to transform/translate for better performance

I found this good CSS animation for a progress bar.
But I want to transform: translate instead of left/right.
How can I switch to transform it? I tried but it doesn't work:
https://codepen.io/shalimano/pen/wBmNGJ
body{
background:#ffffff;
margin:50px 300px;
}
.slider{
position:absolute;
width:1000px;
height:5px;
overflow-x: hidden;
}
.line{
position:absolute;
opacity: 0.4;
background:#4a8df8;
width:150%;
height:5px;
}
.subline{
position:absolute;
background:#4a8df8;
height:5px;
}
.inc{
animation: increase 2s infinite;
}
.dec{
animation: decrease 2s 0.5s infinite;
}
#keyframes increase {
from { left: -5%; width: 5%; }
to { left: 130%; width: 100%;}
}
#keyframes decrease {
from { left: -80%; width: 80%; }
to { left: 110%; width: 10%;}
}
<div class="slider">
<div class="line"></div>
<div class="subline inc"></div>
<div class="subline dec"></div>
</div>
First attempt:
#keyframes increase {
from { transform: translateX(-5%); width: 5%; }
to { transform: translateX(130%); width: 100%;}
}
#keyframes decrease {
from { transform: translateX(-100%); width: 80%; }
to { transform: translateX(1100%); width: 10%;}
}
But it's not the same.
You should consider the fact that percentage value with translate are related to the element size and not parent size like top/left and in order to have good performance you need to also replace the width by scale so that you only use transform and you will not trigger layout changes.
Here is an approximation of your code using only transform:
body {
background: #ffffff;
margin: 50px 10px;
position:relative;
}
.slider {
position: absolute;
left:0;
right:0;
height: 5px;
overflow-x: hidden;
background: rgba(74, 141, 248, 0.4);
}
.slider:before,
.slider:after {
content: "";
position: absolute;
background: #4a8df8;
height: 5px;
width:100%;
transform:scaleX(0);
animation: increase 2s infinite linear;
}
.slider:after {
animation-delay:1s;
}
#keyframes increase {
from {
transform:translateX(0%) scaleX(0);
transform-origin:left;
}
50% {
transform-origin:left;
}
60% {
transform:translateX(0%) scaleX(0.5);
transform-origin:right;
}
80% {
transform:translateX(20%) scaleX(0.3);
transform-origin:right;
}
100% {
transform:translateX(0%) scaleX(0);
transform-origin:right;
}
}
<div class="slider">
</div>
One of the main differences between the two methods (transform: translate and left ) of positioning elements is how they react to percentages. You can use px.

CSS Stepped Rotation on All Axes

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>

How can i create an animation like this in css

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>

The same CSS animations does not have the same durations (with animated background color)

I try to animate two blocks with css animation. Its have the same transform animation but one of it has background-color animation also. This animations splitted to two #keyframes.
See code (https://codepen.io/mctep/pen/Rgyaep):
<style>
.a {
position: absolute;
left: 0;
top: 0;
width: 100px;
height: 100px;
background-color: red;
animation: a 1s infinite;
}
.b {
position: absolute;
left: 0;
top: 0;
width: 100px;
height: 100px;
background-color: gray;
animation: b 1s infinite;
}
#keyframes a {
0% {
background-color: red;
transform: translateX(0);
}
50% {
background-color: green;
transform: translateX(100px);
}
100% {
background: red;
}
}
#keyframes b {
0% {
transform: translateX(0);
}
50% {
transform: translateX(100px);
}
}
</style>
<div class="a"></div>
<div class="b"></div>
Animation of colored block is lag from gray block In Google Chrome. In Safary and FF it works perfectly.
I can to make one #keyframes for background and other for transform and it solves problem. But I want to use single value of animation property for single element. If there are no any ways to fix it I'll separate moving and coloring animations.
Why this happens? Is it Google Chrome bug?
Couldn't give you a concrete reason why this happens, but we can un-confuse Chrome by simply specifying a background-color in animation B as well.
#keyframes b {
0% {
background-color: gray; /* add this */
transform: translateX(0);
}
}
.a {
position: absolute;
left: 0;
top: 0;
width: 100px;
height: 100px;
background-color: red;
animation: a 1s infinite;
}
.b {
position: absolute;
left: 0;
top: 0;
width: 100px;
height: 100px;
background-color: gray;
animation: b 1s infinite;
}
#keyframes a {
0% {
background-color: red;
transform: translateX(0);
}
50% {
background-color: green;
transform: translateX(100px);
}
100% {
background: red;
}
}
#keyframes b {
0% {
background-color: gray;
transform: translateX(0);
}
50% {
transform: translateX(100px);
}
}
<div class="a"></div>
<div class="b"></div>

Nested backface-visibility is not hidden

I've got a problem with "nested" backface-visibility.
I would like to have a flipping div, with content on both sides. For that, I use two div flipping, each one representing a face of my "two-faces" div (.face and .back).
The rotation works well.
Now, I want to hide their container, and reveal it when the page is loaded with another flip. But as you can see, my .face div is visible.
How could I avoid .face to be visible before my animation?
Here's the shorten working example I could made (Chrome favor):
.flip {
position: relative;
backface-visibility: hidden;
transform: rotateX(180deg);
animation: init 1s ease 2s 1 normal forwards;
}
.flip div {
backface-visibility: hidden;
transition: 1s;
margin: 0;
padding: 20px;
border: 1px solid;
width: 200px;
text-align: center;
}
.back {
position: absolute;
top: 0;
left: 0;
}
.face,
.flip:hover .back {
transform: rotateX(0deg);
}
.flip:hover .face,
.back {
transform: rotateX(180deg);
}
#keyframes init {
from { transform: rotateX(180deg); }
to { transform: rotateX(0deg); }
}
<div class="flip">
<div class="face">FACE</div>
<div class="back">BACK</div>
</div>
If you want it to work in a nested way, you need the property
transform-style: preserve-3d;
in he parent:
.flip {
position: relative;
backface-visibility: hidden;
transform: rotateX(180deg);
transform-style: preserve-3d;
animation: init 1s ease 2s 1 normal forwards;
}
.flip div {
backface-visibility: hidden;
transition: 1s;
margin: 0;
padding: 20px;
border: 1px solid;
width: 200px;
text-align: center;
}
.back {
position: absolute;
top: 0;
left: 0;
}
.face,
.flip:hover .back {
transform: rotateX(0deg);
}
.flip:hover .face,
.back {
transform: rotateX(180deg);
}
#keyframes init {
from { transform: rotateX(180deg); }
to { transform: rotateX(0deg); }
}
<div class="flip">
<div class="face">FACE</div>
<div class="back">BACK</div>
</div>

Resources