Flipping Out! How to create a card that flips with React and CSS

Amie Foster
8 min readOct 9, 2021

For my most recent project, I was instructed to make an app using React. I decided to go with a fun, light-hearted joke app where users could find and share jokes! Rather than have the setup and punchline displayed all at once, I knew I wanted something a bit more dramatic. I scoured the internet looking for a cool way to make the site more interactive. Cue, the card flip!!!

I’m going to walk you through that process and share what I learned along the way. Sometimes deciphering code and putting things into digestible language can be extremely difficult. But never fear! I have done all the translations so you don’t have to.

Step 1: Make the card!

Here’s what we’ll need:

  1. Card container— a div element containing all of the cards that we can use to provide styling and structure to our card layout. className=”card-grid’
  2. Individual cards — this is where the individual content will appear probably using a .map() to render info in an array/object from whatever database or API you are using. className=’card’
  3. Within the cards themselves — a div element with the className=’front’ to hold the information that will be visible from the front of the card and another sibling div element with the className=’back’ to hold, you guessed it, the information that will be visible on the backside.

NOTE: For my project, I am rendering the setup on the front and the punchline on the back but this can be adapted for many other uses: a quiz with question/answer options on the front and the correct answer on the back, a storefront with the item name/photo on the front and its description on the back, a recipe list with the name and picture on the front and ingredients/step-by-step instructions on the back, or even a simple memory game where the front is blank and the user needs to match photos on the back from memory. This can be used for so many things! The options are really endless!

Step 2: Now we can focus on flipping the card. For this, were going to combine some CSS styling (via our super handy class names) and State.

1. Let's start off by creating a state to hold our flip! We're going to create a state and set its default value to false.

2. Now we need to be able to toggle the state of our flip between true and false. Let's first think about our flip. We want our flip state to be triggered by something. That is, there is going to be *SOME EVENT* that is going to change our state. For this example, were going to change our state (aka flip our card) when the card is clicked on. So, we can assume we're going to need an onClick event listener on our card to listen for the click and then jump into our toggle logic to switch from true to false.

3. Now that we’ve added our event listener, let's add our logic to toggle our state. What we want is to take the current state and set it to the opposite. We can use the logical operator (!), which means not. Essentially what we're saying is “hey, set flip(using the setter function) to not flip (because flip is false by default, not flip is true).

4. Now what we have this logic written out the last thing to do is figure out where it goes! Well, since we want to click anywhere on the card we can put it in the div that holds all of our information. In this case, we can add it to our div elements with the class name of “front” and “back”.

5. The last step that is related to the state is going to be changing our class name based on whether the card is flipped or not (if flipped is true or false). To do this we're going to edit our className=”card” to be a ternary. The logic here is asking “is the card flipped?”(aka: is the state of flip true?) IF IT’S TRUE, then make the class name “card flip” IF IT’S FALSE, keep the class name “card”. We can write this out with our ternary like this,

NOTES:

  1. We need to add the onClick to both front and back so the user is able to flip the card back and forth!
  2. You can add the event listener to specific elements on your card as well. It just means that the user will have to click on that specific element to flip it. This is helpful if you have multiple event listeners on one side of the card.
  3. We are using an anonymous function to set our flip because we want this logic to be executed ONLY on the click.
  4. We’re going to replace our className=”card” with this ternary because we want the class name to change based on if the card is flipped or not. This is how we can give it directions to flip using CSS. (This will make more sense later)

To summarize, basically what we're saying here is “HEY COMPUTER, when someone clicks on this card, the front or back, change the state to the opposite of what it is in this moment (if true, change it to false and if false, change it to true) if true, add “flip” on to the class name.”

Here is what everything should look like altogether!

Step 3: Now that we’ve added all our class names and our state, we can move on to where the magic happens, CSS! This is where we can make our cards actually flip.

Step 3A: Let’s start out by styling our card. Before we FLIP, we have to get our cards onto the page. I will not be going into too much detail about this but I will include the CSS I used as a reference. I would recommend at least setting a height and width to your cards so you can at least see where they are on the page, and get an idea of what your flip will look like so you can make adjustments to get the exact look you’re going for. You can also add additional styling to the card container which is our element with className=”card-grid”.

Step 3B: *I will be referencing different class names as .name and properties will be italicized

  1. The first CSS property we want to set is position. According to W3 Schools, position “specifies the type of positioning method used for an element”. Were going to set the position of .card to relative and the position of .front and .back to absolute. This is so we can separate the information on the back and front of our card and ensure they do not conflict with each other. (Line 15, 45)
  2. Next, we're going to flip around the text on the backside of our card. We are going to add the transform property to .back and set it to rotateY(180deg) aka: were rotating on the y-axis 180 deg. We need to do this so when the card flips you can read the text on the back. ~If you were to write on the inside of a window and then go outside to read it, it wouldn’t be facing the right way. We have the same problem here and using the transform property will take care of that. (Line 51)
  3. Now our text is flipped but it is still visible from the front. To fix this we can set the backface-visibility property on .front and .back to hidden. This will hide anything that is rotated 180 deg AKA on the backside. Why are we putting this on the front and back? Well, we don't want the text on the front to show up on the back either! This will also hide the “front” of the card when we flip the card over. The “back side” is referring to the “other side”. We just don't want the text from the other side to show on the side the user is currently looking at. (Line 47)
  4. Next, we're going to work on our flip! YAY! In .card, set the transform property to rotateY(var( — rotate-y, 0)) aka: rotate (our flip is our rotation) on the Y-axis — how much should we rotate? We’re going to use a variable to represent that value so we can tell it exactly how much to rotate later in our .flip, which will be triggered onClick with our ternary. See? It's all coming together! The variable is — rotate-y and 0 represents the default value. (We're also going to add perspective(1000px) this will tie into step 7 and make our flip look a little more 3D.) (Line 22)
  5. Then in .flip were going to set our variable — rotate-y equal to 180deg which will flip it around (Line 36)
  6. Almost there! Next, we need to set the transform style property in .card to preserve-3D. This will give us the look of flipping our card 180 deg and is what keeps the elements on the backside of our card when we flip it! (Line 19)
  7. Lastly, let’s slow down our transformation because by default it’s a bit too quick to pick up on. We can ser the transition property in .card to 150 ms. which will make the flip more appealing and noticeable. (Line 20)

NOTES:

  1. I ran into some issues with the back not showing all of my text. I fixed this by setting a max-width to the p element on the back of the card which allowed for more text to show up.
  2. On line 23, we used another variable ( — translate-y) that is set in our card:hover. I’d recommend looking into this and testing yourself to figure out what it's doing!

And that’s it! Now you have a beautiful flip animation! You can use the CSS to the left as a guide to the styling I used for the cards and for the grid layout! As well as a few extra features I added like the box-shadow and hover.

I hope this was helpful!

I’d like to give credit to Web Dev Simplified on youtube for solidifying my understanding of how to accomplish this. You can check out that video here: https://www.youtube.com/watch?v=hEtZ040fsD8&t=2118s

Lets connect on LinkedIn!

https://www.linkedin.com/in/amie-n-foster/

As always, if you've made it this far please enjoy a joke!

Why did the child component have such great self-esteem?

\/

\/

\/

\/

\/

\/

Because its parent kept giving it PROPS!

--

--

Amie Foster

Junior Software Engineer | Narrativ | Flatiron School