Creating a 3D card flip effect with CSS that scales the image without sacrificing clarity

Issue

I am aware that enlarging a small image using CSS will result in blurriness, but I believe there must be a way to achieve the effect I desire without sacrificing clarity. I suspect that adjusting the initial width/height and transform origins of the backside card may hold the solution, but I have not been successful in implementing it. Where am I going wrong?

Code Playground

https://jsfiddle.net/a9dpc05t/1/

Markup

<div class="cardWrapper">
  <div class="card">
    <div class="cardFace front"><img src="http://www.gannon.tv/cp_assets/3dplayingcardflip/images/hearts.png" width="129"></div>
    <div class="cardFace back"><img src="http://www.gannon.tv/cp_assets/3dplayingcardflip/images/spades.png" width="129"></div>
  </div>
</div>

Cascading Styles

body {
  background-color: black;
  margin:50px 150px;
  font-family:Arial, sans-serif;
}

.cardWrapper{
  width:129px;
  height:200px;
  position:relative;
  float:left;
  cursor:pointer;
}

.cardFace{
  position:absolute;
  width:129px;
  height:200px;
  overflow:hidden;
}

JavaScript Functions

TweenLite.set(".cardWrapper", {
  perspective: 800
});
TweenLite.set(".card", {
  transformStyle: "preserve-3d"
});
TweenLite.set(".back", {
  rotationY: -180
});
TweenLite.set([".back", ".front"], {
  backfaceVisibility: "hidden"
});

$(".cardWrapper").click(
  function() {
    TweenLite.to($(this).find(".card"), 1.2, {
      rotationY: 180,
      scale: 2.48,
      ease: Back.easeOut
    });
  }
);

Answer №1

REVISED V2:

Presenting an updated version addressing the feedback provided in the comment.

New jsFiddle Version


UPDATED CODE SNIPPET V2:

TweenLite.set(".cardWrapper", {
  perspective: 800
});
TweenLite.set(".card", {
  transformStyle: "preserve-3d"
});
TweenLite.set(".back", {
  rotationY: -180
});
TweenLite.set([".back", ".front"], {
  backfaceVisibility: "hidden"
});

$(".cardWrapper").click(
  function() {
    TweenLite.to($(this).find(".card"), 1.2, {
      rotationY: 180,
      scale: 1,
      ease: Back.easeOut
    });
  }
);
body {
  background-color: black;
  margin: 120px;
  font-family: Arial, sans-serif;
}
.cardWrapper {
  width: 387px;
  height: 600px;
  position: relative;
  float: left;
  cursor: pointer;
}
.cardFace {
  position: absolute;
  width: 387px;
  height: auto;
  overflow: hidden;
}
.cardFace img {
  width: 387px;
}
.card {
  transform: scale(0.248);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.4/TweenMax.min.js"></script>

<div class="cardWrapper">
  <div class="card">
    <div class="cardFace front">
      <img src="http://www.gannon.tv/cp_assets/3dplayingcardflip/images/hearts.png">
    </div>
    <div class="cardFace back">
      <img src="http://www.gannon.tv/cp_assets/3dplayingcardflip/images/spades.png">
    </div>
  </div>
</div>

<div class="cardWrapper">
  <div class="card">
    <div class="cardFace front">
      <img src="http://www.gannon.tv/cp_assets/3dplayingcardflip/images/hearts.png">
    </div>
    <div class="cardFace back">
      <img src="http://www.gannon.tv/cp_assets/3dplayingcardflip/images/spades.png">
    </div>
  </div>
</div>


V1:

The key is to first decrease the size of the card and then enlarge it on flip.


Updated jsFiddle


ADJUSTED CODE SNIPPET:

TweenLite.set(".cardWrapper", {
  perspective: 800
});
TweenLite.set(".card", {
  transformStyle: "preserve-3d"
});
TweenLite.set(".back", {
  rotationY: -180
});
TweenLite.set([".back", ".front"], {
  backfaceVisibility: "hidden"
});

$(".cardWrapper").click(
  function() {
    TweenLite.to($(this).find(".card"), 1.2, {
      rotationY: 180,
      scale: 1,
      ease: Back.easeOut
    });
  }
);
body {
  background-color: black;
  margin: 120px;
  font-family: Arial, sans-serif;
}
.cardWrapper {
  width: 144px;
  height: 220px;
  position: relative;
  float: left;
  cursor: pointer;
}
.cardFace {
  position: absolute;
  width: 432px;
  height: 660px;
  overflow: hidden;
}
.cardFace img {
  width: 432px;
}
.card {
  transform-origin: top right;
  transform: scale(0.248);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.4/TweenMax.min.js"></script>

<div class="cardWrapper">
  <div class="card">
    <div class="cardFace front">
      <img src="http://www.gannon.tv/cp_assets/3dplayingcardflip/images/hearts.png">
    </div>
    <div class="cardFace back">
      <img src="http://www.gannon.tv/cp_assets/3dplayingcardflip/images/spades.png">
    </div>
  </div>
</div>

Answer №2

To enhance the appearance of your div, make sure to include margin and padding in the CSS styles. For optimal layout, add margin to the .card class and padding to both the .front and .back classes.

If you're interested, I've created a flipping cards layout that you might find useful. Feel free to check it out here: http://codepen.io/aman_d1996/pen/WxJwoo

<html>
<head>
    <title>Cards</title>
</head>
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://cdn.rawgit.com/nnattawat/flip/master/dist/jquery.flip.min.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" integrity="sha384-fLW2N01lMqjakBkx3l/M9EahuwpSfeNvV63J5ezn3uZzapT0u7EYsXMjQV+0En5r" crossorigin="anonymous">
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
<link href='http://fonts.googleapis.com/css?family=Roboto' rel='stylesheet' type='text/css'>
<script src="main.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="style.css">

<body>
...

CSS

body>div>div>div>div>h4 {
    font-family: 'Roboto', sans-serif;
    text-transform: uppercase;
    font-size: 17px;
    font-weight: bolder;
    margin-left: 12px;
    color: white;
}

JS

$(function($) {
    // jQuery flip functionality for each card
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How to eliminate a line in an XML file with PHP

I have been struggling with a seemingly simple task and tried various methods to no avail. I now find myself seeking guidance on how to achieve my goal. My Objective: I am looking to remove a specific element from an XML file. The Current Situation: The ...

The toggle button for columns is not triggering the callback action

When working with the following JSFiddle, I noticed that the action function does not seem to fire whenever a button to select a column in the column visibility tool is selected. Check out the code snippet below for reference: $(document).ready(function( ...

Data loss may occur when transferring information to Cipher.update with DES encryption in Node.js

Listen up: So, I've got this Buffer of data set up like this: [39 bytes of header] + [body] + [padding] (according to my calculations). When I save it to a file, I can easily identify the structure and everything appears to be in order. Next, I nee ...

What are some ways to restrict the number of words per line?

I'm currently developing an online store using NextJS and Material UI. The issue I encountered is related to the long product names that are causing my Card component to stretch. As shown in this image: https://i.sstatic.net/07qNm.png If you obse ...

Execute a function on each item within a JavaScript array

I'm working with a JavaScript array and trying to figure out how to display each item in the array within an h1 element. Can anyone help me out? This is what I have come up with so far: names = ["Jeff", "Steve", "Bill"]; function show() { let c ...

Is it possible for the JavaScript DOM API to retrieve the exact casing of attribute and tag names?

Is it possible to retrieve the original casing of an attribute name or tag name from the source? The attribute name is in lowercase The tag name is in uppercase The local element name is in lowercase I am looking for a solution that doesn't require ...

How to present retrieved data with spaces or line breaks in PHP

I need help on how to display data with spaces or line breaks. Currently, I am using textarea for the news content when adding and editing, and the data type for my news content is text. This is how I want the content to be displayed: https://i.sstatic.ne ...

Utilizing Modifier Keys in jQuery for Form Submission

Imagine having a form structured like this: [ Animal name input field ] Add button Currently, when a name is entered and the enter key is pressed, a new animal with that name is added to a table. Now, I want to introduce a new feature called "slow add" ...

Tips for setting up Highcharts tooltip.headerFormat using the function getDate() plus 5

I'm facing a little challenge trying to understand how the JavaScript function getDate interacts with Highcharts datetime on xAxis. My goal is to show two dates in the tooltip header, forming a date range like this: 1960/1/1 - 1965/1/1. The first da ...

When changing the dropdown option on a separate page in React/Next JS, all checkboxes show the clicked style as a result of utilizing useState

I have implemented checkboxes for three different categories: "Types", "Price", and "Categories". They function correctly, with data being passed to a separate checkbox component without any issues. The problem arises when I click a checkbox and then inte ...

Enhance numbers with properties in ES2015 strict mode

Is there a way to achieve the following scenario? console.log(a, typeof a); // prints "3 'number'" console.log(typeof a.mymethod()); // prints 'foobar' In non-strict mode this can be done (at least in Node), but strict mode in ECMASc ...

Tips for displaying all 'ul li' lists in media queries to ensure responsiveness in design

When I view my navigation bar snippet on desktop mode, it displays all the list items. However, when I adjust the browser width to fit my media queries, only the Home list is shown in the nav bar. Here's an example of the issue: Before Clicking the ...

Selenium - Activating a flash button

Currently, I am facing an issue while trying to load a URL using Selenium on Mozilla browser. The webpage contains a 'Login' button created in flash that I need to click on. I have explored the following resources: 1.How to click an element in Se ...

Set the class of the list item to "active" class

My approach to styling involves using a UL and li class to contain form selection options. I plan on hiding the radio button and using its value upon form submission. I have managed to enable checking the radio box when the <li> is clicked, but for s ...

Change the class of each item in a list individually by hovering over them with the mouse using JavaScript

How to toggle classes in a list item one by one using the mouseover event in JavaScript? const items = document.querySelectorAll("ul li"); let currentItem; for (const item of items) { item.addEventListener("mouseover", e => { currentItem &am ...

Having trouble aligning elements in Bootstrap inline

I am trying to get certain elements to display in a single line. Here is the HTML code I have: h2 { color: Red; font-size: 30px; font-weight: bold; display: inline-block; } img { display: inline-block; } h2.class1 { color: green; font-si ...

The expanding Bootstrap Footer is overlapping the content on the page, causing it to be hidden

I have implemented a bootstrap footer with position:absolute to ensure it remains at the bottom of my single-page website at all times. The issue arises when I resize the screen width and reach around 980px, the footer height increases, obstructing most o ...

What is the best way to trigger an AJAX function every 15 seconds?

As part of my web application, I have implemented a JavaScript function that is triggered by the <body onload> event. Within this function, there is a while loop that continuously iterates until it receives the desired response from a PHP page. Unfo ...

Place a vertical arrangement of images within a horizontal row using flexbox

I am struggling to create a two-column layout with text on the left and a column of images on the right. The images should be the same height as the container and only take up the necessary width. Unfortunately, my attempts with various markup structures, ...

Extracting and retrieving information from a complex data structure obtained through an API call

Struggling with this one. Can't seem to locate a similar situation after searching extensively... My goal is to determine the author of each collection associated with a user. I wrote a function to fetch data from an API for a specific user, in this ...