CSS card flip animation - javascript

I am trying to build an animation where each time a card is clicked the card flips over and reveals the opposite side. The words on each side of the card will change every time the card is flipped. The problem I am having is that the front face of my card only is visible on sporadic occasions. I cannot find any logic to why the front face is normally not visible but occasionally will be visible.
This is my jsfiddle: https://jsfiddle.net/tdammon/ucf6mx1q/
Here is the HTML structure:
<body>
<section>
<div id="headerSection">
<h1>Heard At Prime</h1>
</div>
<div id='whiteBlock'>
<div id='front'>hey</div>
<div id='back'>hi</div>
</div>
</section>
</body>
</html>
Here is the flipping logic for the #whiteBlock div:
$(document).ready(onReady);
function onReady(){
$('#whiteBlock').on('click', flipIt)
}
quotesArray=['hey','cool saying','funny thing','hahaha'];
function flipIt() {
console.log('flip')
$('#front').empty();
$('#back').empty();
let firstQuote= quotesArray[Math.floor(Math.random()*quotesArray.length)]
let secondQuote= quotesArray[Math.floor(Math.random()*quotesArray.length)]
$('#front').append(firstQuote);
$('#back').append(secondQuote);
$('#whiteBlock').toggleClass('flip');
};
And the CSS animations:
body {
background-color: blue;
}
section{
perspective: 500px;
}
#whiteBlock{
background-color:white;
height: 100px;
width:100px;
transform: scale(1);
transform-style: preserve-3d;
/* transition: transform .5s; */
display: flex;
justify-content: center;
align-items: center;
/* position: absolute;
animation: move 3s linear infinite; */
}
#whiteBlock:active{
transform:scale(.97);
transition: transform .2s
}
#whiteBlock.flip{
transform:rotateY(180deg)
}
#front{
transform: rotateY(180deg);
backface-visibility: hidden;
}
#back{
position:absolute;
backface-visibility: hidden;
}

backface-visibility still requires vendor prefixes. So you'll need -webkit-backface-visibility for Chrome and Safari and -moz for Firefox.
With a couple changes this more of less works for me in Safari and should be a good starting point:
$(document).ready(onReady);
function onReady() {
$('#whiteBlock').on('click', flipIt)
}
let quotesArray = ['hey', 'cool saying', 'funny thing', 'hahaha'];
function flipIt() {
console.log('flip')
$('#front').empty();
$('#back').empty();
let firstQuote = quotesArray[Math.floor(Math.random() * quotesArray.length)]
let secondQuote = quotesArray[Math.floor(Math.random() * quotesArray.length)]
$('#front').append(firstQuote);
$('#back').append(secondQuote);
$('#whiteBlock').toggleClass('flip');
};
section {
perspective: 500px;
}
#whiteBlock {
border: 1px solid #333;
height: 100px;
width: 100px;
transition: 0.6s;
transform-style: preserve-3d;
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
position: relative;
}
#whiteBlock.flip {
transform: rotateY(180deg)
}
#front {
transform: rotateY(0deg);
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
}
#back {
transform: rotateY(180deg);
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section>
<div id="headerSection">
<h1>Heard At Prime</h1>
</div>
<div id='whiteBlock'>
<div id='front'>hey</div>
<div id='back'>hi</div>
</div>
</section>

Related

How to align center with smaller size parent that has a 3d style

My code is about Filping Card. I have 3 elements "flipperContainer" ,"flipper", "CarbBack"("CardBack" is put on page with rotateY 180 first).
I was run into problem when try to align "CardBack"'s center with flipper, when the size of "CardBack" is bigger than "flipper", it seems that "CardBack" always align left with "Flipper".
I have try many methods, using flex layout or using fixed position with "CardBack", but it just doesn't work, seems to because that its parent "flipper" has a 3d style.
Following is my code, I really need some help that can center "CardBack" with "Flipper" while maintaining all the 3d style, thanks!
const root = document.querySelector("#root");
class Card extends React.Component {
constructor(props){
super(props);
}
render(){
return (
<div className="flipperContainer">
<div className="flipper">
<div className="cardBack">
</div>
</div>
</div>
)
}
}
ReactDOM.render(<Card/>, root);
.flipperContainer{
-webkit-perspective: 1000px;
perspective: 1000px;
width: 80px;
height: 50px;
margin: auto;
border-radius:35px;
background-color: black;
}
.flipperContainer:hover .flipper, .flipperContainer.hover .flipper {
-webkit-transform: rotateY(180deg);
transform: rotateY(180deg);
}
.flipper {
width: 40px;
height: 60px;
background-color: red;
-webkit-transition: 1s;
-o-transition: 1s;
transition: 1s;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
border-radius:35px;
right:50%;
position:relative;
}
/* back, initially hidden pane */
.cardBack {
background-color: green;
-webkit-backface-visibility: visible;
backface-visibility: visible;
-webkit-transform: rotateY(180deg);
transform: rotateY(180deg);
width: 70px;
height: 90px;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Multiple Flip Boxes - But only flip the one clicked on

my challenge is that I have two rows of boxes that I want to flip independently. Can't use hover as that is too chaotic, visually, for some users. So I have a JQuery script that toggles between classes, BUT, when applied to multiple boxes I get all of the boxes turning at once. I'd like to be able to turn over only the one clicked on like the hover effect. I can get that to happen if I give each box a separate class but that is a lot of extra CSS and I know that there has to be a better, cleaner way. Please help. :)
Here is the jquery code: $('.card') is what I'd like to use instead of ('cardOne', '.cardTwo', etc.)
function flip() {
$('.card').toggleClass('flipped');
}
And here is the CSS (it's too cumbersome):
.container {
width: 200px;
height: 200px;
position: relative;
border: 1px solid #ccc;
-webkit-perspective: 800px;
-moz-perspective: 800px;
-o-perspective: 800px;
perspective: 800px;
}
.cardOne, .cardTwo, .cardThree, .cardFour, .cardFive, .cardSix, .cardSeven, .cardEight {
width: 100%;
height: 100%;
position: absolute;
-webkit-transition: -webkit-transform 1s;
-moz-transition: -moz-transform 1s;
-o-transition: -o-transform 1s;
transition: transform 1s;
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-o-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transform-origin: 50% 50%;
}
.cardOne div {
display: block;
height: 100%;
width: 100%;
/*line-height: 200px;*/
color: #000;
text-align: center;
/*font-weight: bold;*/
font-size: 18px;
position: absolute;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-o-backface-visibility: hidden;
backface-visibility: hidden;
}
.cardOne .front, .cardTwo .front, .cardThree .front, .cardFour .front, .cardFive .front, .cardSix .front, .cardSeven .front, .cardEight .front {
background: #9ddae5;
line-height: 180px;
}
.cardOne .back, .cardTwo .back, .cardThree .back, .cardFour .back, .cardFive .back, .cardSix .back, .cardSeven .back, .cardEight .back {
background: blue;
line-height: 18px;
-webkit-transform: rotateX( -180deg );
-moz-transform: rotateX( -180deg );
-o-transform: rotateX( -180deg );
transform: rotateX( -180deg );
}
.cardOne.flipped, .cardTwo.flipped, .cardThree.flipped, .cardFour.flipped, .cardFive.flipped, .cardSix.flipped, .cardSeven.flipped, .cardEight.flipped {
-webkit-transform: rotateX( -180deg );
-moz-transform: rotateX( -180deg );
-o-transform: rotateX( -180deg );
transform: rotateX( -180deg );
}
And then, of course, the HTML (but I'll cut it to two boxes):
<div class="container">
<div class="cardOne" onclick="flipOne()">
<div class="front">
<!-- front content -->
<p>anxiety</p>
</div>
<div class="back">
<!-- back content -->
<p>Occasional anxiety is a normal part of life. You might feel anxious when faced with a problem at work, before taking a test, or making an important decision. But anxiety disorders involve more than temporary worry or fear. </p>
</div>
</div><!-- end flipper -->
</div>
</div> <!-- end col-1 -->
<div class="col-1">
<div class="container">
<div class="cardTwo" onclick="flipTwo()">
<div class="front">
<!-- front content -->
<p>infertility</p>
</div>
<div class="back">
<!-- back content -->
<p>Grief is a real part of infertility. It may be heightened in miscarriages or stillbirths, but it is just as real when a couple cannot conceive.</p>
</div>
</div>
</div>
</div><!-- end col-1 -->
Use the following:
$('.container').on('click', '.card', function(){
$(this).toggleClass('flipped');
});
Using this logic, we bind with the script an event handler to the parent container of the cards. Any time a card is clicked, it will toggle the flipped class on the card that was clicked.
$('.container').on('click', '.card', function() {
$(this).toggleClass('flipped');
});
.card {
display: inline-block;
min-width: 100px;
min-height: 80px;
border: 1px solid black;
}
.card.flipped { background-color: red; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="card"></div>
<div class="card"></div>
</div>
Try this:
$('.card').on('click', function() {
$(this).toggleClass('flipped');
}
And you'll only need one class .card reducing writng and so on.
Ps: remove the function declation and replaced it with the code above and remove all onclick="flip()" from your HTML.

backface visibility not working in safari

I am trying to uss cssflip animation in my code in which the element rotates when hovered upon. I have used transition and backface-visibilty property. It is working fine on chrome but it is not working properly on safari. I have used webkit prefix as well for safari browser.
`.card-container{
margin-top: 9%;
perspective: 900px;
-webkit-perspective: 900px;
z-index: 1;
}
.card{
float: left;
width: 78.5%;
height: 35%;
margin-top: 25%;
border: 1px solid #A08C87;
transition: all 0.6s ease;
-webkit-transition: all 0.6s ease;
transform-style: preserve-3d;
-webkit-transform-style: preserve-3d;
}
#front #back{
color: white;
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
}
front{
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
}
back{
display: flex;
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
font-size: 20px;
}
.card-container:hover .card{
transform: rotateY(180deg);
-webkit-transform: rotateY(180deg);
}
back{
transform: rotateY(180deg);
-webkit-transform: rotateY(180deg);
}`
I think the issue here is with the
backface-visibility: hidden;
It's not being supported in ios and in safari.
In your code just replace the code with
#front #back {
color: white;
-webkit-perspective: 0;
-webkit-backface-visibility: hidden;
-webkit-transform: translate3d(0,0,0);
visibility:visible;
backface-visibility: hidden;
}
I hope this will help you.

Card flip animation Internet Explorer 11

I am trying to make a card flip and show its backside. It works in all other browsers but not in Internet Explorer 11.
I've tried adding -ms- prefaces, but that didn't help. The problem seems to be that IE does not support the css attribute transform-style: preserve-3d.
Here is a jsfiddle: https://jsfiddle.net/gbkq94hr/
HTML
<body>
<article>
<div id="card0" class="card">
<figure class="front">
</figure>
<figure class="back">
</figure>
</div>
</article>
</body>
JS
$(document).ready(function () {
var flipped = false;
var card = $("#card0");
card.click(function() { flipFunction();});
function flipFunction() {
if (flipped) {
flipped = false;
card.removeClass('flip');
} else {
card.addClass('flip');
flipped = true;
}
};
});
CSS
html {
height: 100%;
}
.flip {
transform: rotateY(180deg);
}
.card {
float:left;
width: 110px;
height: 139px;
cursor: pointer;
transform-style: preserve-3d;
transition: transform 1s;
position: relative;
}
figure {
margin: 0;
display: block;
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
-ms-backface-visibility:hidden;
}
.back {
background-color: blue;
transform: rotateY(-180deg);
}
.front {
z-index: 2;
background-color: red;
transform:rotateY(0deg);
}
article {
height: 114px;
width: 114px;
perspective: 1000;
}
EDIT:
As suggested in the comments, I tried following David Walshes instructions, but still couldn't get it to work. https://jsfiddle.net/w9o2chmn/2/
Hi I changed the jQuery code to perform card flip on click. Kindly check https://jsfiddle.net/w9o2chmn/6/
HTML
I added class flip-container to article tag
<article class="flip-container">
<div id="card0" class="card">
<figure class="front">
front
</figure>
<figure class="back">
back
</figure>
</div>
</article>
CSS
I have removed the CSS :hover code and placed it in jQuery click
/* entire container, keeps perspective */
.flip-container {
perspective: 1000;
transform-style: preserve-3d;
color:#fff;
}
/* UPDATED! flip the pane when hovered */
/*.flip-container:hover .back {
transform: rotateY(0deg);
}
.flip-container:hover .front {
transform: rotateY(180deg);
}*/
.flip-container, .front, .back {
width: 200px;
height: 200px;
}
/* flip speed goes here */
.card {
transition: 0.6s;
transform-style: preserve-3d;
position: relative;
}
/* hide back of pane during swap */
.front, .back {
backface-visibility: hidden;
transition: 0.6s;
transform-style: preserve-3d;
position: absolute;
top: 0;
left: 0;
}
/* UPDATED! front pane, placed above back */
.front {
z-index: 2;
transform: rotateY(0deg);
background:red;
}
/* back, initially hidden pane */
.back {
transform: rotateY(-180deg);
background:blue;
}
/*
jQuery
$(document).ready(function() {
var flipped=false;
$('.flip-container').on('click', function(){
if(!flipped){
$('.back').css('transform','rotateY(0deg)');
$('.front').css('transform','rotateY(180deg)');
flipped=true;
console.log('true part :'+flipped);
}
else{
$('.back').css('transform','rotateY(180deg)');
$('.front').css('transform','rotateY(0deg)');
flipped=false;
console.log('else part :'+flipped);
}
});
});
Kindly let me know if its working for you...
PS: I tested this on IE11 and its working for me
Not sure why the second animation is delaying so long as I have used this method in my own code exactly the same. Maybe someone can clean this up.
Basically wanting to add a slight delay to change the z-index so it appears, as the animation is on it's edge (50% through animation), the z-index changes and allows it to have the correct card on top.
$(document).ready(function() {
$('.flip-container').on('click', function(){
if(!$(".front").hasClass("front_flip")) {
$(".front").delay(200).queue(function(){
$(this).addClass("flip_z_index").dequeue();
});
$('.front').addClass('front_flip');
$('.back').removeClass('back_flip');
} else {
$(".front").delay(200).queue(function(){
$(this).removeClass("flip_z_index").dequeue();
});
$('.front').removeClass('front_flip');
$('.back').addClass('back_flip');
}
});
});
.flip-container {
perspective: 1000;
color:#fff;
}
.flip-container, .front, .back {
width: 200px;
height: 200px;
}
.card {
transform-style: preserve-3d;
}
.front, .back {
transition: 0.6s;
transform-style: preserve-3d;
position: absolute;
top: 0;
left: 0;
}
.front {
z-index: 3;
background:red;
}
.back {
z-index:2;
background:blue;
}
.front_flip {
transform: rotateY(-180deg);
}
.back_flip {
transform: rotateY(180deg);
}
.flip_z_index {
z-index:1 !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<article class="flip-container">
<div id="card0" class="card">
<div class="front">
front
</div>
<div class="back back_flip">
back
</div>
</div>
</article>

Adding preventDefault() and stopPropagation()

I am new in coding in general, most especially javascript.
I made a flip div effect. But I noticed that when clicking one .button to trigger the flip effect, all the other divs that are similar in a page are also triggered. So I am trying to add both .preventDefault() and .stopPropagation() when flipping a div, so far its a big FAIL
As a starter, I came up with this code..
$('.insidecontent .button').click(function () {
$('.insidecontent').addClass('flipped');
$('.insidecontent').removeClass('unflipped');
});
$('.insidecontent .button-c').click(function () {
$('.insidecontent').removeClass('flipped');
$('.insidecontent').addClass('unflipped');
});
Demo here: http://jsfiddle.net/uriri/ke7kqvvk/3/
A friend of mine suggested that I should use .parents() on the current target inside the .click() function. But after reading the jQuery documentation, I am totally lost!
You don't need to stop click event or prevent default. You just need to flip right element. Right not you are adding/removing classes to/from all .insidecontent, while you need to select only parent element of the clicked button:
$('.insidecontent .button').click(function () {
$(this).closest('.insidecontent').addClass('flipped').removeClass('unflipped');
});
$('.insidecontent .button-c').click(function () {
$(this).closest('.insidecontent').removeClass('flipped').addClass('unflipped');
});
Demo: http://jsfiddle.net/ke7kqvvk/5/
Or shorter optimized version can be:
$('.insidecontent').find('.button, .button-c').click(function () {
$(this).closest('.insidecontent').toggleClass('flipped unflipped');
});
Demo: http://jsfiddle.net/ke7kqvvk/6/
preventDefault() and stopPropagation() won't help here. You need to use a selector that's more specific than all the elements with the same class.
$('.insidecontent .button').click(function () {
$(this).closest('.insidecontent').addClass('flipped').removeClass('unflipped');
});
$('.insidecontent .button-c').click(function () {
$(this).closest('.insidecontent').removeClass('flipped').addClass('unflipped');
});
.content{
position: relative;
background: #ffffff;
width:100%;
text-align:center;
display: -webkit-box;
display: -moz-box;
display: box;
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
box-orient: vertical;
-webkit-box-align: center;
-moz-box-align: center;
box-align: center;
}
._hasdata .insidecontent {
position: relative;
background: #ffffff;
margin-bottom:30px;
-webkit-perspective: 1000px;
-moz-perspective: 1000px;
-o-perspective: 1000;
perspective: 1000px;
}
._hasdata .insidecontent .front {
position: relative;
z-index: 900;
width: 200px;
height: 200px;
background: #ededed;
-webkit-transform: rotateX(0deg) rotateY(0deg);
-moz-transform: rotateX(0deg) rotateY(0deg);
transform: rotateX(0deg) rotateY(0deg);
}
._hasdata .insidecontent .front .fcontent {
position:relative;
top:30%;
}
._hasdata .insidecontent.flipped .front {
z-index: 900;
-webkit-transform: rotateX(0deg) rotateY(180deg);
-moz-transform: rotateX(0deg) rotateY(180deg);
transform: rotateX(0deg) rotateY(180deg);
}
._hasdata .insidecontent .back {
position: absolute;
width: 200px;
height: 200px;
top: 0;
left: 0;
z-index: 800;
-webkit-transform: rotateX(0deg) rotateY(-180deg);
-moz-transform: rotateY(-180deg);
transform: rotateX(0deg) rotateY(-180deg);
}
._hasdata .insidecontent.flipped .back {
z-index: 1000;
background: #E7E7E7;
-webkit-transform: rotateX(0deg) rotateY(0deg);
-moz-transform: rotateX(0deg) rotateY(0deg);
transform: rotateX(0deg) rotateY(0deg);
}
._hasdata .insidecontent .front,
._hasdata .insidecontent .back {
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
backface-visibility: hidden;
-webkit-transition: all .8s ease-in-out;
-moz-transition: all .8s ease-in-out;
transition: all .8s ease-in-out;
}
._hasdata .insidecontent .button,
._hasdata .insidecontent.flipped .button-c {
z-index: 15;
display: block;
position: absolute;
bottom: 0;
margin: -30px 20px 20px;
opacity: 0;
-webkit-transition: opacity .1s linear;
-moz-transition: opacity .1s linear;
transition: opacity .1s linear;
}
._hasdata .insidecontent:hover .button,
._hasdata .insidecontent.flipped:hover .button-c {
opacity: 0.8;
}
._hasdata .insidecontent.unflipped .button-c {
display: none;
}
._hasdata .insidecontent.flipped ._lar {
height: 100%;
}
._hasdata .insidecontent.unflipped .bcontent {
display: none;
}
._hasdata .insidecontent.flipped .bcontent {
top: 30%;
position: relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="content">
<div class="_hasdata">
<div class="insidecontent initalized unflipped">
<div class="front">
<span class="fcontent">FRONT CONTENT<br />HERE</span>
<a class="btt button">info</a>
</div>
<div class="back _lar">
<div class="bcontent">BACK INFO HERE</div>
<a class="btt button-c">go back</a>
</div>
</div>
</div>
<div class="_hasdata">
<div class="insidecontent initalized unflipped">
<div class="front">
<span class="fcontent">FRONT CONTENT<br />HERE</span>
<a class="btt button">info</a>
</div>
<div class="back _exif">
<div class="bcontent">BACK INFO HERE</div>
<a class="btt button-c">go back</a>
</div>
</div>
</div>
</div>
Have you learned about the "this" keyword yet? In a JQuery click handler, $(this) refers to the element that the handler is called on. So, if you put removeClass and addClass methods on $(this) it will only affect that one element. You can traverse using this too... so your code would look like this:
$('.insidecontent .button').click(function () {
$(this).parent().find('.insidecontent').addClass('flipped');
$(this).parent().find('.insidecontent').removeClass('unflipped');
});
$('.insidecontent .button-c').click(function () {
$(this).parent().find('.insidecontent').removeClass('flipped');
$(this).parent().find('.insidecontent').addClass('unflipped');
});
you may not even need the find method in your case, but it is better to be explicit.

Categories

Resources