I have an app that has a two-sided HTML element. When a user clicks a button, I want to "flip" the element. I've been trying to get it to work as shown here. That example includes the following HTML, CSS, and JavaScript.
HTML
<div id="myApp">
<div class="flip-card">
<div class="flip-card-inner">
<div :class="{ 'flip-card-front':true, 'flipped':!isFlipped }">Side A</div>
<div :class="{ 'flip-card-back':true, 'flipped':isFlipped }">Side B</div>
</div>
</div>
<button #click="onButtonClick">Flip</button>
</div>
CSS
.flip-card {
background-color: transparent;
width: 300px;
height: 300px;
perspective: 1000px;
}
.flip-card-inner {
position: relative;
width: 100%;
height: 100%;
text-align: center;
transform: rotateY(180deg);
transition: transform 0.6s;
transform-style: preserve-3d;
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
}
.flipped {
transform: rotateY(180deg);
}
.flip-card-front, .flip-card-back {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.flip-card-front {
background-color: #bbb;
color: black;
}
.flip-card-back {
background-color: #2980b9;
color: white;
transform: rotateY(180deg);
}
JavaScript
const MyApp = {
data() {
return {
isFlipped: false
}
},
methods: {
onButtonClick() {
this.isFlipped = true;
}
}
}
Vue.createApp(MyApp).mount('#myApp');
There doesn't appear to be any errors. It's just not behaving as I'd expect. Everything looks correct. How do I get the card to flip when someone clicks the button?
UPDATE
This example cleared it up.
Your class is being applied as expected, but you have a CSS specificity problem.
Increase specificity like this:
.flip-card-front.flipped {
transform: rotateY(180deg);
}
Try to replace below code.
this.isFlipped = true;
To
this.isFlipped = !this.isFlipped;
Related
I have a container div with overflow: auto (this can't be removed) and within it there's another div that toggles between showing and hiding using an animation when a button is clicked. The problem is that when this div moves down it causes an overflow. Keep in mind that this div must be within the container.
Example of the problem
https://jsfiddle.net/wg3jzkd6/1/
The expected result:
Div moves down without causing overflow
#manuel can you move the absolute div inside the content div? if yes, try adding the overflow: hidden; on content div
document.getElementById('button').addEventListener('click', () => {
const absolute = document.getElementById('absolute-div')
const absoluteClass = absolute.getAttribute('class')
if(absoluteClass.includes('hidden'))
absolute.setAttribute('class', 'absolute-div shown')
else
absolute.setAttribute('class', 'absolute-div hidden')
})
#keyframes hide {
from {
transform: translateY(0);
}
to {
transform: translateY(100%);
}
}
#keyframes show {
from {
transform: translateY(100%);
}
to {
transform: translateY(0);
}
}
.container {
position: relative;
overflow: auto;
border: 1px solid black;
height: 80vh;
width: 40vw;
margin: 0 auto;
padding: 1rem;
}
.content {
display: flex;
justify-content: center;
align-items: center;
position: relative;
min-height: 100%;
background-color: green;
overflow:hidden;
}
.absolute-div {
background-color: blue;
min-height: 20%;
width: 100%;
position: absolute;
left: 0;
bottom:0;
display:inline;
}
.hidden {
animation: hide ease forwards 300ms;
}
.shown {
animation: show ease forwards 300ms;
}
<html>
<body>
<div id='container' class='container'>
<div class='content'>
<button id='button'>
SHOW/HIDE
</button>
<div id='absolute-div' class='absolute-div'>
Hello world
</div>
</div>
</div>
</body>
</html>
Hope this will solve the issue you are facing..
As far as I can understand your question, is that you have a container that has an extra overflow. Try using the overflow: hidden; property in your container div
Just change your overflow to hidden
document.getElementById('button').addEventListener('click', () => {
const absolute = document.getElementById('absolute-div')
const absoluteClass = absolute.getAttribute('class')
if(absoluteClass.includes('hidden'))
absolute.setAttribute('class', 'absolute-div shown')
else
absolute.setAttribute('class', 'absolute-div hidden')
})
#keyframes hide {
from {
transform: translateY(0);
}
to {
transform: translateY(100%);
}
}
#keyframes show {
from {
transform: translateY(100%);
}
to {
transform: translateY(0);
}
}
.container {
position: relative;
overflow: hidden;
border: 1px solid black;
height: 80vh;
width: 40vw;
margin: 0 auto;
padding: 1rem;
}
.content {
display: flex;
justify-content: center;
align-items: center;
position: relative;
min-height: 100%;
background-color: green;
}
.absolute-div {
background-color: blue;
min-height: 20%;
width: 100%;
position: absolute;
left: 0;
bottom:0;
}
.hidden {
animation: hide ease forwards 300ms;
}
.shown {
animation: show ease forwards 300ms;
}
<html>
<body>
<div id='container' class='container'>
<div class='content'>
<button id='button'>
SHOW/HIDE
</button>
</div>
<div id='absolute-div' class='absolute-div'>
Hello world
</div>
</div>
</body>
</html>
I do not quite understand, why overflow: auto cannot be changed. It works perfectly with the overflow attribute set to hidden.
If changing from auto invokes some kind of affect that is not explained here, I would kindly advise you to add this affect. But should there be such, it can probably be solved by putting this whole construct into another div container and isolating it, preventing any unwanted side effects.
I am trying to make nested flip-cards for a login-system - successful as far as Edge, Chrome, Opera and Firefox goes, but Safari...
I am aware of the "hack" for Apple Safari to propper rotate cards, so I applied the '-webkit-backface-visibility: hidden;' to all the cards.
Unfortunately, Safari still does show the rotated backface of my Cards. Can anyone help?
Here is my code:CSS
/* The OUTER & INNER flip */
.flip-o-card, .flip-i-card {
background-color: transparent;
width: 320px;
/*border: 1px solid #f1f1f1;*/
perspective: 1000px;
margin:0 auto;
}
.flip-o-card {
height: 480px;
}
.flip-i-card {
height: 400px;
}
.flip-o-card-inner, .flip-i-card-inner {
position: relative;
width: 100%;
height: 100%;
text-align: center;
transition: transform 0.8s;
transform-style: preserve-3d;
}
.flip-o-card.hover .flip-o-card-inner, .flip-i-card.hover .flip-i-card-inner {
transform: rotateY(180deg);
}
.login-forgot, .register, .login, .forgot {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.login-forgot, .login {
background-color: #bbb;
color: black;
}
.register {
background-color: #1eff73;
color: white;
transform: rotateY(180deg);
}
.forgot {
background-color: #ff1e1e;
color: white;
transform: rotateY(180deg);
}
/* ####################################### */
.toggle-o, .toggle-i {
text-align: center;
}
.toggle-o {
padding-top: 50px;
}
.toggle-i {
padding-top: 0px;
}
the jquery:
$(document).ready(function(){
$('.toggle-o').on('click', function(){
console.log('Flip button clicked...');
$('.flip-o-card').toggleClass('hover');
if( $('div.text-center.toggle-o p').html() === "Register" ){
$('div.text-center.toggle-o p').html("Log in");
} else {
$('div.text-center.toggle-o p').html("Register");
}
});
$('.toggle-i').on('click', function(){
console.log('Switch button clicked...');
$('.flip-i-card').toggleClass('hover');
if( $('div.text-center.toggle-i p').html() === "Forgot password" ){
$('div.text-center.toggle-i p').html("Back to log in");
} else {
$('div.text-center.toggle-i p').html("Forgot password");
}
});
});
the html:
<div class="flip-o-card">
<div class="flip-o-card-inner">
<div class="login-forgot">
<div class="flip-i-card">
<div class="flip-i-card-inner">
<div class="login">
<p>login</p>
</div>
<div class="forgot">
<p>forgot</p>
</div>
</div>
</div>
<div class="text-center toggle-i">
<p>Forgot password</p>
</div>
</div>
<div class="register">
<p>register</p>
</div>
</div>
</div>
<div class="text-center toggle-o">
<p>Register</p>
</div>
Using some jQuery to hide the flipped main Card did the trick! (see the fiddle that I added in the comments...) However, as T J mentioned, Safari is the new IE... Grrr
I am making a website in which I need to showcase the specs of a product so I am using flip cards to do so. The problem is I am trying to add multiple cards, my first one works fine, but then everything after just molds into the first one making a huge mess. I tried "googling" answers and couldn't find any that would work with me.
My HTML Code
<div class="flip-card">
<div class="flip-card-inner">
<div class="flip-card-front">
<img src="iPhone12Pro.png" alt="12pro" style="width:300px;height:300px;">
</div>
<div class="flip-card-back">
<h1>iPhone 12 Pro 5G</h1>
<p>6.1" Super Amoled Display</p>
<p>Good Cameras</p>
<p>A14, 5 Nanometer Chipset</p>
<p>Triple Camera Setup (UltraWide, Telephoto, Wide)</p>
<p>New Sqared Off Design</p>
<p>Price: $999 USD</p>
</div>
</div>
</div>
</div>
</div>
My CSS Code
.flip-card {
background-color: transparent;
width: 300px;
height: 300px;
perspective: 1000px;
padding-top: 20px;
padding-left: 50px;
}
.flip-card-inner {
position: relative;
width: 100%;
height: 100%;
text-align: center;
transition: transform 0.6s;
transform-style: preserve-3d;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
}
.flip-card:hover .flip-card-inner {
transform: rotateY(180deg);
}
.flip-card-front,
.flip-card-back {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.flip-card-front {
background-color: #bbb;
color: black;
}
.flip-card-back {
background-color: #bbb;
color: rgb(29, 27, 27);
transform: rotateY(180deg);
}
.flip-card-back h1 {
padding-top: 10%;
}
Any help would be greatly appreciated!
So first thing is that you just copied code from W3Schools and you copied it WRONG!
First HTML... you have 2 <div> more in your code then you are supposed to have.
Second thing is that your CSS total mess. Just use CSS that W3Schools gives you and everything works fine.
.flip-card {
background-color: transparent;
width: 300px;
height: 300px;
perspective: 1000px;
}
.flip-card-inner {
position: relative;
width: 100%;
height: 100%;
text-align: center;
transition: transform 0.6s;
transform-style: preserve-3d;
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
}
.flip-card:hover .flip-card-inner {
transform: rotateY(180deg);
}
.flip-card-front, .flip-card-back {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.flip-card-front {
background-color: #bbb;
color: black;
}
.flip-card-back {
background-color: #2980b9;
color: white;
transform: rotateY(180deg);
}
<div class="flip-card">
<div class="flip-card-inner">
<div class="flip-card-front">
<img src="https://picsum.photos/200/300" alt="12pro" style="width:300px;height:300px;">
</div>
<div class="flip-card-back">
<h1>iPhone 12 Pro 5G</h1>
<p>6.1" Super Amoled Display</p>
<p>Good Cameras</p>
<p>A14, 5 Nanometer Chipset</p>
<p>Triple Camera Setup (UltraWide, Telephoto, Wide)</p>
<p>New Sqared Off Design</p>
<p>Price: $999 USD</p>
</div>
</div>
</div>
I'm brand new here so I hope my question makes sense.
I need to adjust the hovering system for my images. I have 2 - front and back. When the user hovers (clicks on mobile) on the front it should display the back. When the cursor leaves the element it should display the front again.
This doesn't work on mobile. When the user clicks on the front, the back appears but then he/she has to click outside of the element to display the front again.
How can I make it that users can keep clicking on the image element to display the front and then the back?
Here's my code:
.flip-card {
background-color: transparent;
width: auto;
height: auto;
perspective: 1000px;
}
.flip-card-inner {
position: relative;
width: 100%;
height: 100%;
text-align: center;
transition: transform 0.8s;
transform-style: preserve-3d;
}
.flip-card:hover .flip-card-inner {
transform: rotateY(180deg);
}
.flip-card-front, .flip-card-back {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden; /* Safari */
backface-visibility: hidden;
}
.flip-card-front {
background-color: #bbb;
color: black;
}
.flip-card-back {
background-color: dodgerblue;
color: white;
transform: rotateY(180deg);
}
<div class="flip-card">
<div class="flip-card-inner">
<div class="flip-card-front">
<img src="https://petlifetoday.com/wp-content/uploads/2019/07/new-kitten-750x500.jpg" alt="Avatar" >
</div>
<div class="flip-card-back">
<img src="https://i.pinimg.com/originals/52/73/c8/5273c86755b215c1f3b4fac7bbad935c.jpg" alt="Avatar" >
</div>
</div>
</div>
Thank you
Use :focus where you set :hover
Doc: https://developer.mozilla.org/en-US/docs/Web/CSS/:focus
I have some flip cards and when you hover over the flip card, the card flips and enlarges (scales). However I don't want to the text inside the hovered card to scale so I put the text inside a child div. (I only want the parent card background to scale).
How can I stop my text and content from scaling and going blurry? I've tried to reset my child div to 1/2 of the scale size to reset it but it does not work.
HTML
<div class="c-flip-card">
<div class="c-flip-card__inner">
<div class="c-flip-card__front"><img src="img_avatar.png" alt="Avatar"</div>
<div class="c-flip-card__back">
<h1>John Doe</h1>
<p>Architect & Engineer</p>
<p>We love that guy</p>
</div>
</div>
</div>
SASS
.c-flip-card {
background-color: transparent;
width: 180px;
height: 200px;
border: 1px solid #f1f1f1;
perspective: 1000px;
/* Do an horizontal flip when you move the mouse over the flip box container */
&:hover {
z-index: 10;
position: relative;
}
&:hover .c-flip-card__inner {
transform: rotateY(180deg) scale(1.4);
}
/* This container is needed to position the front and back side */
.c-flip-card__inner {
cursor:pointer;
position: relative;
width: 100%;
height: 100%;
text-align: center;
transition: transform 0.8s;
transform-style: preserve-3d;
}
/* Position the front and back side */
.c-flip-card__front, .c-flip-card__back {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
}
/* Style the front side (fallback if image is missing) */
.c-flip-card__front {
background-color: #bbb;
color: black;
}
/* Style the back side */
.c-flip-card__back {
background-color: red;
color: white;
transform: rotateY(180deg);
}
.abc{
transform: scale(0.7);
h1, p{
color:#000;
}
}
}
jsfiddle
Edit
I think I found a workaround : Don't use scale() !
.c-flip-card .c-flip-card__inner {
transition: all 0.8s;
}
.c-flip-card:hover .c-flip-card__inner {
transform: rotateY(180deg) translate3d(40px,-40px,0);
/* Just change the width and height to 140% and have them transition
I used translate3d to position the card the same way scale() does */
width: 140%;
height: 140%;
}
And if you want to get the same positioning as scale() produce, you can add something like translate3d(40px,-40px,0) to your transform.
This way you don't have to manage the size of the text, the effect is the same (except for a little transition on the text position), and there is no bluriness.
.c-flip-card {
margin: 50px;
background-color: transparent;
width: 180px;
height: 200px;
border: 1px solid #f1f1f1;
perspective: 1000px;
}
.c-flip-card:hover {
z-index: 10;
position: relative;
}
.c-flip-card:hover .c-flip-card__inner {
transform: rotateY(180deg) translate3d(40px,-40px,0);
width: 140%;
height: 140%;
}
.c-flip-card .c-flip-card__inner {
cursor: pointer;
position: relative;
width: 100%;
height: 100%;
text-align: center;
transition: all 0.8s;
transform-style: preserve-3d;
}
.c-flip-card .c-flip-card__front,
.c-flip-card .c-flip-card__back {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
}
.c-flip-card .c-flip-card__front {
background-color: #bbb;
color: black;
}
.c-flip-card .c-flip-card__back {
background-color: red;
color: white;
transform: rotateY(180deg);
}
<div class="c-flip-card">
<div class="c-flip-card__inner">
<div class="c-flip-card__front">
<img src="img_avatar.png" alt="Avatar" style="width:300px;height:300px;">
</div>
<div class="c-flip-card__back">
<h1>John Doe</h1>
<p>Architect & Engineer</p>
<p>We love that guy</p>
</div>
</div>
</div>
Original
Putting the content of your back card inside a div and applying scale(0.7) on it seems to work but it really doesn't look good on the first hover.
<div class="c-flip-card__back">
<div class="notScale">
<h1>John Doe</h1>
<p>Architect & Engineer</p>
<p>We love that guy</p>
</div>
</div>
.c-flip-card:hover .notScale {
transform: scale(0.7);
}
So instead of applying transform on your text, since it's only shown on hover, why not simply change the font size for exemple using calc() and variables :
/* define variables for p and h1 */
body {
--sizeP : 16px;
--sizeH1 : calc(2.5 * var(--sizeP));
}
/* apply those variable one "regular" h1 and p */
h1 {
font-size: var(--sizeH1);
}
p{
font-size: var(--sizeP);
}
/* "scale" down the text for the backside by a factor of .7 */
.c-flip-card .c-flip-card__back h1{
font-size: calc(.7 * var(--sizeH1));
}
.c-flip-card .c-flip-card__back p{
font-size: calc(.7 * var(--sizeP));
}
For the blury part I did get some imporvement (though it's not enough for chrome) by adding :
.c-flip-card {
-webkit-filter: blur(0);
filter: blur(0);
}
body {
--sizeP: 16px;
--sizeH1: calc(2.5 * var(--sizeP));
}
h1 {
font-size: var(--sizeH1);
}
p {
font-size: var(--sizeP);
}
/* The flip card container - set the width and height to whatever you want. We have added the border property to demonstrate that the flip itself goes out of the box on hover (remove perspective if you don't want the 3D effect */
.c-flip-card {
margin: 50px;
background-color: transparent;
width: 180px;
height: 200px;
border: 1px solid #f1f1f1;
perspective: 1000px;
/* Do an horizontal flip when you move the mouse over the flip box container */
/* This container is needed to position the front and back side */
/* Position the front and back side */
/* Style the front side (fallback if image is missing) */
/* Style the back side */
-webkit-filter: blur(0);
filter: blur(0);
}
.c-flip-card:hover {
z-index: 10;
position: relative;
}
.c-flip-card:hover .c-flip-card__inner {
transform: rotateY(180deg) scale(1.39);
}
.c-flip-card .c-flip-card__inner {
cursor: pointer;
position: relative;
width: 100%;
height: 100%;
text-align: center;
transition: transform 0.8s;
transform-style: preserve-3d;
}
.c-flip-card .c-flip-card__front,
.c-flip-card .c-flip-card__back {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
}
.c-flip-card .c-flip-card__front {
background-color: #bbb;
color: black;
}
.c-flip-card .c-flip-card__back {
background-color: red;
color: white;
transform: rotateY(180deg);
}
.c-flip-card .c-flip-card__back h1 {
font-size: calc(.7 * var(--sizeH1));
}
.c-flip-card .c-flip-card__back p {
font-size: calc(.7 * var(--sizeP));
}
<div class="c-flip-card">
<div class="c-flip-card__inner">
<div class="c-flip-card__front">
<img src="img_avatar.png" alt="Avatar" style="width:300px;height:300px;">
</div>
<div class="c-flip-card__back">
<h1>John Doe</h1>
<p>Architect & Engineer</p>
<p>We love that guy</p>
</div>
</div>
</div>
For chrome I tried every solution from here and here but wasn't able to get a descent result.
The only one that worked for the blury part on chrome was :
#supports (zoom : 140%) {
.c-flip-card:hover {
zoom : 140%;
transform: translate3d(-40px,-40px,0);
}
.c-flip-card:hover .c-flip-card__inner {
transform: rotateY(180deg) scale(1);
}
.c-flip-card .c-flip-card__back h1{
font-size: calc(var(--sizeH1));
}
.c-flip-card .c-flip-card__back p{
font-size: calc(var(--sizeP));
}
}
But I wasn't able to transition the property zoom so the effect isn't great.
I followed Amarjits solutions and added scale:1.1 to .c-flip-card__back and this is the best result, however it is blurry using Saffari
.c-flip-card__back {
background-color: red;
color: white;
transform: rotateY(180deg) scale(1.1);
}
I found a better solution. Just don't use scaling on the back card, so the animation just tweens as the front card fades out it just shows the back card
This transitions around half way creates the illusion of it scaling when in fact it's just showing a div at set height and width.
It works in Chrome and Saffari and text is not blurry
.mycont{
/* How pronounced should the 3D effects be */
perspective: 500;
-webkit-perspective: 500;
-moz-perspective: 500;
-ms-perspective: 500;
-o-perspective: 500;
width:100%;
height:245px;
position:relative;
/*Some UI */
border-radius:6px;
-webkit-border-radius:6px;
-moz-border-radius:6px;
-ms-border-radius:6px;
-o-border-radius:6px;
font-size:28px;
line-height:150px;
vertical-align:middle;
cursor:pointer;
}
.box-front,.box-back{
/* Enable 3D transforms */
transform-style: preserve-3d;
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-ms-transform-style: preserve-3d;
-o-transform-style: preserve-3d;
transform-style: preserve-3d;
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-ms-backface-visibility: hidden;
-o-backface-visibility: hidden;
width:100%;
height:100%;
position:absolute;
background-color:#0090d9;
/* Animate the transitions */
-webkit-transition:0.8s; text-align:center;
-moz-transition:0.8s; text-align:center;
-ms-transition:0.8s; text-align:center;
-o-transition:0.8s; text-align:center;
transition:0.8s; text-align:center;
color:#FFF;
border-radius:5px;
-webkit-border-radius:6px;
-moz-border-radius:6px;
-ms-border-radius:6px;
-o-border-radius:6px;
}
.box-back{
/* The back side is flipped 180 deg by default */
transform:rotateY(180deg);
-webkit-transform:rotateY(180deg);
-moz-transform:rotateY(180deg);
-ms-transform:rotateY(180deg);
-o-transform:rotateY(180deg);
background-color:#f35958;
}
.mycont:hover .box-front{
/* When the mycont is hovered, flip the front side and hide it .. */
transform:rotateY(180deg);
-webkit-transform:rotateY(180deg);
-moz-transform:rotateY(180deg);
-ms-transform:rotateY(180deg);
-o-transform:rotateY(180deg);
}
.mycont:hover .box-back{
/* .. at the same time flip the back side into visibility */
transform:rotateY(360deg);
-webkit-transform:rotateY(360deg);
-moz-transform:rotateY(360deg);
-ms-transform:rotateY(360deg);
-o-transform:rotateY(360deg);
margin-left: -0%;
margin-top: -10%;
width: 300px;
height:430px;
}
<div style="width:300px; margin-top:100px; margin-left:100px;">
<div class="mycont">
<div class="box-front">Front :)</div>
<div class="box-back">
rtrtrtrt
</div>
</div>
</div>