I'm trying to make a card flip effect with CSS keyframes but for some reason the transform: rotateY() doesn't rotate correctly. When it's rotated by the #keyframes, after it passes rotateY(90deg) the front side isn't shown, instead it shows the flipped back side. When flipping the card "manually" (in the inspect element), it works fine.
The card by default is showing the front side. But the animation starts with the back side and then it flips. The animation is keeping its ending state.
As far as I could see, for some reason, the front side is always behind the back side. (If you opacity the back side, the front side can be seen.)
I've tried:
Adding perspective: 1000px; to the parent element
(.cards).
Using positive rotateY() instead of negative.
Adding z-index to .front.
Adding transform: rotateY(0deg); to .front, so it knows that that's the front side.
Adding backface-visibility: hidden; to both, .front and .back.
Adding positon: relative; on one (and both), .front and .back.
But none of these fixed it.
Here you can see a video of the issue:
When #keyframes does it:
https://gyazo.com/7cd4e75c85ed5eba6b1e717a37ce95c2
Manually (When I do it with the Inspect Element):
https://gyazo.com/42e63ff2e4fe0149b917e895a633dd88
Here's the code:
HTML:
<div class="cards">
<div class="card">
<div class="front">
<div class="card-number">5</div>
<img src="https://bounty-assets.fra1.cdn.digitaloceanspaces.com/cards/clubs.png" alt="">
</div>
<div class="back">
<img src="https://bounty-assets.fra1.cdn.digitaloceanspaces.com/cards/back.png" alt="">
</div>
</div>
</div>
CSS:
.cards {
width: fit-content;
display: flex;
position: absolute;
top: 25px;
left: 0;
right: 0;
margin: 0 auto;
perspective: 1000px;
}
.cards .card {
min-width: auto;
width: 208px;
background: transparent;
border: 0;
border-radius: 0;
display: flex;
position: relative;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
margin-left: -30px;
transform: rotateY(0deg);
animation: flipcard 1s linear 0s 1 forwards;
}
.cards .card:first-child {
margin-left: 0;
}
.cards .card .front {
position: absolute;
backface-visibility: hidden;
transform: rotateY(0deg);
}
.cards .card .front .card-number {
position: absolute;
top: 30px;
left: 35px;
font-size: 32px;
font-weight: 600;
}
.cards .card .back {
position: absolute;
transform: rotateY(180deg);
}
#keyframes flipcard {
0% {
opacity: 0;
transform: translate(30vw, 30vh) rotateY(-180deg);
}
30% {
opacity: 1;
transform: translate(0, 0) rotateY(-180deg);
}
50% {
opacity: 1;
transform: translate(0, 0) rotateY(-180deg);
}
60% {
transform: translate(-20px, 0) rotateY(-180deg);
}
80% {
transform: translate(-30px, 0) rotateY(-90deg) scale(1.08);
}
90% {
transform: translate(0, 0) rotateY(0deg) scale(1.08);
}
100% {
transform: translate(0, 0) rotateY(0deg) scale(1);
}
}
I fixed it. Belive it or not, the opacity in the keyframes was causing this issue.
Related
This is supposed to be a memory game with cards with text on them.
The cards on the front should just be white (the background-image) and at the back there is a word. But since applying the backface-visibility-hidden, it actually just shows the background image and no text.
It supposed to have text only on the back, but out of curiosity I have placed text on one card on the back and on the front, only this one shows text from the front, but after flipping it does not show the back text, but only the mirror image of the front.
I have read the IE might cause problems, but not in this case, as it does not work in any browser.
I have tried playing with preserve-3d, but nothing brings me a solution.
<section class="memory-game">
<div class="memory-card">
<p class="front">un abricot</p>
<p class="back"></p>
</div>
</section>
.memory-game {
perspective: 1000px;
}
.memory-card {
position: relative;
transform: scale(1);
transition: transform 0.4s;
}
.memory-card:active {
transform: scale(0.95);
transition: transform 0.4s;
}
.memory-card.flip {
transform: rotateY(180deg);
}
.front,
.back {
position: absolute;
background-image: url("image.jpg");
backface-visibility: hidden;
}
.front {
transform: rotateY(180deg);
}
back
front
disappearing half
As you say, the solution is to add preserve-3d.
See it working in the snippet
.memory-game {
perspective: 1000px;
}
* {
transform-style: preserve-3d;
}
.memory-card {
position: relative;
transform: scale(1);
transition: transform 0.4s;
border: solid 1px black;
height: 50px;
width: 200px;
}
.memory-card:active {
transform: scale(0.95);
transition: transform 0.4s;
}
body:hover .memory-card {
transform: rotateY(180deg);
}
.front,
.back {
position: absolute;
background-image: url("image.jpg");
backface-visibility: hidden;
}
.front {
transform: rotateY(180deg);
}
<section class="memory-game">
<div class="memory-card">
<p class="front">FRONT</p>
<p class="back">BACK</p>
</div>
</section>
I want to expand the sides of a cube while it rotate like in this pen.
I have tried to create a cube that will spin along x axis but while doing so I want it to also expand its sides after some duration.
Below is my code...
.wrapper{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
.cube-wrap {
width: 40px;
height: 40px;
-webkit-perspective: 2000px;
-webkit-perspective-origin: 50% -500px;
}
.single-box {
display: block;
position: absolute;
width: 40px;
height: 40px;
background-color: #60c2ef;
-webkit-transform: rotateY(45deg) translateZ(-200px) rotateX(15deg);
-webkit-transform-origin: 50% 50% 0;
}
.box {
-webkit-transform-style: preserve-3d;
-webkit-animation: rotate 1.5s infinite linear;
}
.side-front {
background-color: blue;
-webkit-transform: translateZ(20px);
}
.side-back {
background-color: blue;
-webkit-transform: rotateY(180deg) translateZ(20px);
}
.side-top {
background-color: blue;
-webkit-transform: rotateX(90deg) translateZ(20px);
}
.side-bottom {
background-color: blue;
-webkit-transform: rotateX(-90deg) translateZ(20px);
}
.side-left {
background-color: blue;
-webkit-transform: rotateY(-90deg) translateZ(20px);
}
.side-right {
background-color: blue;
-webkit-transform: rotateY(90deg) translateZ(20px);
}
#-webkit-keyframes rotate {
0% { -webkit-transform: rotateY(0); }
100% { -webkit-transform: rotateY(360deg); }
}
<div class="wrapper">
<div class="cube-wrap">
<div class="box">
<div class="single-box side-back"></div>
<div class="single-box side-top"></div>
<div class="single-box side-bottom"></div>
<div class="single-box side-left"></div>
<div class="single-box side-right"></div>
<div class="single-box side-front"></div>
</div>
</div>
</div>
The above code will rotate along x axis. It is fine. Along with that, say after 3s or so, I want the cube to rotate slowly and expand along the sides... How can I do it? Could someone help me with this?
This might sound like a stupid answer.. but the answer is actually already in the Codepen that you provided yourself.
In case you're unfamiliair with sass/codepen.
In codepen you can select the dropdown icon and choose for view copiled css
I would suggest to copy the already existing code and then customize it to your own needs.
You could also fork the pen and change it in the codepen environment.
I try to do an animated box that will unfold itself on the page load.
I have a panel lifted up. I try to rotate it 90deg to the ground, and after, I would want to lift it up again based on the other edge 90deg.
I tried to change the origin (transform-origin: top) but it change the origin to the original origin. I had to add 2 translation to position it at the right place but it create a bump. The edge on the ground don't stick on the ground.
Here's my current fiddle: https://jsfiddle.net/hbnta1uj/2/
I also tried without modifying the origin but I still get a bump:
#keyframes slideFront2 {
0% {
transform: rotateX(-0deg);
}
50% {
transform: rotateX(-90deg);
}
100% {
transform: rotateX(-180deg) translateZ(-100px) translateY(100px);
}
}
I have another idea where I position the second panel flat already and I hide it (opacity 0) and at 50% when the first panel is flat I show the second and just 90deg it.
But I would want to know for more complex animations if there's a way to do it the way I describe it, by always start at the new position the new transformation?
Thanks
I would consider an animation on the container to make it easier where you only need one keyframe:
* {
box-sizing: border-box;
}
body {
margin: 0;
}
.container {
width: 90%;
margin: auto;
height: 100vh;
background-color: rgb(194, 194, 194);
}
.progressbar-wrapper {
width: 300px;
height: 100px;
top: calc(50% - 50px);
left: calc(50% - 150px);
position: absolute;
transform-style: preserve-3d;
transform: rotateX(-20deg) rotateY(-30deg);
}
.progressbar {
width: 100%;
height: 100%;
transform-origin: bottom;
animation: 0.5s ease-out 1 slideFront forwards;
transform-style: preserve-3d;
}
.side {
width: 100%;
height: 100%;
background-color: rgba(254, 254, 254, 0.3);
position: absolute;
top: 0;
left: 0;
}
#keyframes slideFront {
100% {
transform: rotateX(-90deg);
}
}
.bottom {
box-shadow: 10px 10px 50px 5px rgba(90, 90, 90, 0.7);
}
.back {
animation: 1s ease-out 0.5s 1 slideFront forwards;
transform-origin: top;
}
<div class="container">
<div class="progressbar-wrapper">
<div class="progressbar">
<div class="side back">
</div>
<div class="side bottom">
</div>
</div>
</div>
</div>
The thing I discover is that the order matter in the translate function. Everything is executed left to right so the origin of the rotation will be relative to the current position of the element if you execute everything left to right (Here's 2 boxes getting the same rotation translation but the order differ: https://codepen.io/anon/pen/oOQGPp)
So in my example, if you do:
50.001% {
transform: rotateX(90deg) translateZ(00px) translatey(100px) ;
transition-timing-function: linear;
}
100% {
transform: rotateX(0deg) translateZ(100px) translatey(00px) ;
transition-timing-function: linear;
}
The rotation will be applied before the translation so the rotation origin will not be the bottom line after the translation but it will be the position without the origin based on the translated part (So it will be the 0% position origin.) CSS will fail to make the path of the animation and it will add a little bump.
But if you do transform: TRANSLATE ROTATE, the rotation will be applied after the translation so the origin of the rotation will be related to the position with the translation. This is how I was able to rotate the item without getting the little bump bug.
Here's the full fixed css. You can run it in my original jsfiddle to see the result
* {
box-sizing: inherit;
margin: 0;
}
html {
box-sizing: border-box;
}
.container {
width: 90%;
margin: auto;
height: 100vh;
background-color: rgb(194, 194, 194);
}
.progressbar-wrapper {
width: 300px;
height: 100px;
top: 50%;
left: 50%;
position: absolute;
transform: translate(-50%, -50%);
}
.progressbar {
width: 100%;
height: 100%;
transform-style: preserve-3d;
transform: rotateX(-20deg) rotateY(-30deg);
}
.side {
width: 100%;
height: 100%;
background-color: rgba(254, 254, 254, 0.3);
position: absolute;
top: 0;
left: 0;
}
#keyframes slideBottom {
0% {
transform: rotateX(-0deg);
}
100% {
transform: rotateX(-90deg);
}
}
#keyframes slideFront {
0% {
transform: rotateX(-0deg);
}
50% {
transform: rotateX(-90deg);
}
50.001% {
transform: translateZ(100px) rotateX(90deg);
transition-timing-function: linear;
}
100% {
transform: translateZ(100px) rotateX(0deg) ;
transition-timing-function: linear;
}
}
.bottom {
animation: 0.5s ease-out 0s 1 slideBottom forwards;
box-shadow: 10px 10px 50px 5px rgba(90, 90, 90, 0.7);
transform-origin: bottom;
}
.back {
animation: 1s ease-out 0s 1 slideFront forwards;
transform-origin: bottom;
}
I have a diamond shape in one div with an image in it and there is a div with absolute positioned text. On hover, I want the diamond to spin, but not the text. Is it possible to achieve? I suppose I will have to change the HTML a bit.
Here are my attempts so far:
HTML:
<div class="rel">
<div class="dn-diamond">
<h4> Random text </h4>
<div class="dn-diamond-img">
<img src="../images/someImage.png" alt="">
</div>
</div>
</div>
CSS:
.rel {
position: relative;
display: inline;
}
.rel:hover {
animation: spin 3s infinite linear;
}
#keyframes spin {
from { transform: rotateY(0deg); }
to { transform: rotateY(360deg); }
}
.rel:hover .dn-diamond h4 {
-webkit-animation-name: none !important;
animation-name: none !important;
}
.dn-diamond h4 {
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
letter-spacing: 0.1em;
text-transform: uppercase;
position: absolute;
top: -20px;
left: 20px;
padding: 10px;
z-index: 10;
background: rgba(0, 0, 0, 0.4);
color: #fff;
}
.dn-diamond-img {
width: 420px;
height: 420px;
}
.dn-diamond-img img {
width: 100%;
height: auto;
-webkit-transform: rotate(45deg) translateX(-95px);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg) translateX(-100px) translateY(45px);
transform-origin: 50% 50%;
overflow: hidden;
}
Thanks for any help!
You refer to it as a diamond, so I assume you want to keep it upright. I think this is what you want: http://jsfiddle.net/t67c7ffq/1/
All I did was change .rel:hover to .dn-diamond-img:hover. This won't spin the h4.
I not sure if you are looking for this:
http://codepen.io/luarmr/pen/qdrvgM
My changes
.rel {
position: relative;
}
.rel:hover img{
animation: spin 3s infinite linear;
}
And as well the animation, because donĀ“t make sense for me the jump
#keyframes spin {
from {
transform: rotate(45deg) translateX(-100px) translateY(45px);
transform-origin: 50% 50%;
}
to {
transform: rotate(405deg) translateX(-100px) translateY(45px);
transform-origin: 50% 50%; }
}
}
Assign an id=myimage to your html <img src="../images/someImage.png" alt="" id="myimage">and then change the css from .rel to #myimage. You only need to spin the image, right?
I'm attempting to make a div appear by having it hidden forced via rotate and backface-visibility. The issue is that it is flickering and then disappears after a second. This happens on Chrome. On IE11 it is not appearing at all...
http://jsfiddle.net/1xq96btg/
It's working fine on Firefox.
EDIT: I'm using just backface-visibilty on its own as when I included its variants it became even more unstable and strange behaving.
EDIT 2: z-index doesn't seem to be helping either.
HTML
<div class="one-third-box" onclick="location.href='#'">
<div class="overlay"></div>
<img src="http://www.example.com/image/jpg" />
<div class="box-description">this is a test description</div>
</div>
CSS
.one-third-box {
float: left;
margin-bottom: 2px;
margin-right: 0.2%;
width: 33.2%;
position:relative;
perspective: 1000;
cursor:pointer;
}
.one-third-box:hover {
transform: rotateY(180deg);
transition: 0.6s;
transform-style: preserve-3d;
}
.one-third-box:hover img {
-moz-transform: scaleX(-1);
-o-transform: scaleX(-1);
-webkit-transform: scaleX(-1);
transform: scaleX(-1);
filter: FlipH;
-ms-filter:"FlipH";
position:relative;
top:-1px;
}
.one-third-box:hover .overlay {
backface-visibility: hidden;
}
.box-description {
backface-visibility: hidden;
background: none repeat scroll 0 0 #2f5d70;
bottom: 0;
color: #fff;
font-size: 18px;
font-weight: lighter;
height: 38%;
padding-left: 10%;
padding-top: 6%;
position: absolute;
transform: rotateY(-180deg);
width: 100%;
padding-right: 10%;
}
.overlay {
position:absolute;
width:100%;
height:100%;
background:url('images/overlay.png');
}
.one-third-box > img {
width: 100%;
}
I got it to work by changing the CSS a bit...okay, a lot.
I'm assuming that this was being caused by inconsistent hardware acceleration between the overlapping elements and/or that transform-style: preserve-3d; line. Either way, I've created a snippet that seems to work for me. I also chose to go with a CSS animation instead of a transition because it just makes it that much more readable in this case.
* { margin: 0; padding: 0; } /* Simple CSS reset */
.one-third-box {
position: relative;
display: inline-block;
cursor: pointer;
width: 33.2%;
}
.one-third-box > img {
transform-style: flat;
width: 100%;
transform: translate3d(0,0,0); /* Fixes blur from scaling */
}
.box-description {
position: absolute;
box-sizing: border-box;
backface-visibility: hidden;
background: none repeat scroll 0 0 #2f5d70;
bottom: 0;
color: #fff;
font-size: 18px;
font-weight: lighter;
height: 38%;
padding-left: 10%;
padding-top: 6%;
width: 100%;
padding-right: 10%;
transform: rotateY(-180deg);
}
/* ---------------------- Hover effects ---------------------- */
.one-third-box:hover > img,
.one-third-box:hover > .box-description {
-webkit-animation: flip 0.6s;
animation: flip 0.6s;
transform: rotateY(0deg);
}
/* flip animation */
#-webkit-keyframes flip {
from { transform: rotateY(180deg); }
to { transform: rotateY(0deg); }
}
#keyframes flip {
from { transform: rotateY(180deg); }
to { transform: rotateY(0deg); }
}
<div class="one-third-box" onclick="location.href='#'">
<div class="overlay"></div>
<img src="http://www.surgemedia.ie/portfolio-images/alci-clear.png" />
<div class="box-description">this is a test description</div>
</div>