Learn How to Create Quick and Simple React Flipping Card

Learn How to Quickly Create Simple React Flipping Card

Table of Contents

How cool would it be to know how to build React flipping card? Your own interactive business card! Imagine how you could use this card to make your portfolio stand out! In this tutorial, I will take you through all the steps necessary to create this card. I tried to make the code simple ad easy to understand. So, I hope that even beginners without much knowledge of React will be able to finish this tutorial. If you already know React very well, take this as a practice. Enjoy it!

Live demo on CodePen.

Source code on GitHub.

Briefing

Today, we will be building React flipping card. Let me give you some more details. We will build something like an interactive business card. This card will be composed of two sides. The frontside will contain two columns. One column will contain full-width and full-height image. The second will contain short bio of hypothetical design. The backside of our will contain contact form and links to social media profiles. I’m sure there will be plenty of smart ways you can use this card.

HTML and assets

Let’s start with the easiest part of this React flipping card tutorial. First, we need to get together necessary assets. In terms of CSS, we will need three external resources. These are Font Awesome for the icons for links to social media profiles, Bootstrap 3 for grid system and font Montserrat for typography. None of these resources is necessary for our getting React flipping card up and running. So, feel free to replace them with your own. Or, don’t use any at all.

One thing I have to mention is that Bootstrap also contains normalize sheet. This stylesheets modifies some styles to minimize the number of browser inconsistencies. If you remember, we discussed whether to use normalize or reset stylesheet in CSS best practices. So, if you don’t use Bootstrap, or normalize, it is possible that your version may differ a bit. However, these differences are not so eye-catching.

When it comes to JavaScript, we will need three resources. These are React and ReactDOM and Babel compiler. First two are necessary, Babel is optional. I used it because I wanted to write this React flipping card tutorial in ES6 JavaScript syntax. Although browser support is very good, it is not ideal. So, I used Babel to compile ES6 syntax to older ECMAScript 5. This is it for assets. HTML, it will be even faster. We need just one div as a container for React. Let’s give it class “react-card”.

Code:

<div class="react-card"></div>

CSS (Sass)

To make the CSS (Sass) part of our React flipping card easier, let’s split it into smaller parts. As first, we will take care about typography and some rests. Bootstrap sets font-size to “14px” and font-family to “Helvetica”. Let’s change that to 16px and Montserrat. Let’s change the background-color of body to “#fff”, just to make sure. Finally, we will set some default styles for h1 and h2 headings we will use in our React flipping card.

Code:

/*- Typograpy and resets -*/
html {
 font-size: 16px;
}

body {
 font-family: "Montserrat", "Helvetica Neue", Helvetica, Arial, sans-serif;
 font-size: 100%;
 background-color: #fff;
}

h1,
h2 {
 margin-top: 0;
}

h1 {
 margin-bottom: 16px;
 font-size: 24px;
 font-weight: 700;
}

h2 {
 margin-bottom: 12px;
 font-size: 18px;
 font-weight: 400;
}

Styling the card container

In the second part, we will style the container of our React flipping card, card body and flipping effect. For the container will set position to “relative” because we will later use absolute “position” for front and backside. Z-index is here to avoid any glitches while rotating the card. Margin is just for centering and offsetting it from the top of the screen. So, this line is optional. The max-width of the React flipping card will be “720px” and height “420px”. Feel free to change these values.

Finally, we need to apply necessary perspective. We need to use perspective to allow the sides of the card to “live” in the same 3D space. Without this, you will still get the flipping effect. However, you will not see the card rotate in 3D. I decided to use an image in our React flipping card. To avoid any overlaps, let’s restrict its max-width and max-height to “100%”.

Code:

/*- Card container -*/
.card-container {
 position: relative;
 z-index: 1;
 margin: 32px auto;
 max-width: 720px;
 height: 420px;
 perspective: 1000px;
}

img {
 max-width: 100%;
 max-height: 100%;
}

Polishing the card body

Next is styling the body of the our React flipping card and creating flipping effect. Width and height of the body will be “100%”. The transform-style needs to be set to “preserve-3d”. Finally, we will use transition to animate the flipping effect. To make the effect working, we need to rotate the card-body around Y axis for “180” degrees. Also, to make sure the frontside will not overlap the back, when the card is flipped, let’s set its opacity to “0“ and visibility to “hidden”. And, let’s use transition to make this process smoother.

Code:

/*- Card body -*/
.card-body {
 width: 100%;
 height: 100%;
 transform-style: preserve-3d;
 transition: all .7s linear;
}

/*- Flipping the card -*/
.card-container:hover .card-body {
 transform: rotateY(180deg);
}

.card-container:hover > .card-body > .side-front {
 opacity: 0;
 visibility: hidden;
 transition: opacity 1s ease-in, visibility .75s linear;
}

Putting together the sides

Working React flipping card requires putting together the backside and frontside. For both sides, we will set position to “absolute”, overflow to “hidden”, width and height to “100%”, color to “#212121”, background-color to “#fff” and backface-visibility to “hidden”. Also, we can add light box-shadow to make the card stand out from the background a bit.

Code:

/*- Card sides -*/
.card-side {
 position: absolute;
 top: 0;
 overflow: hidden;
 width: 100%;
 height: 100%;
 color: #212121;
 background-color: #fff;
 backface-visibility: hidden;
 box-shadow: 0 10px 35px rgba(50,50,93,.1),0 2px 15px rgba(0,0,0,.07);
}

Adding styles for the frontside

The frontside of React flipping card will contain two sides. Side on the left will contain an image. Side on the right will contain bio of hypothetical designer. We need to use one override for Bootstrap grid. Every column has small padding on both sides. We have to reset left padding of the column containing the image. Otherwise, there would be a white line between the border of the card and image. Then, we will add top and bottom padding to the right side to add a bit of space.

Code:

/*- Frontside -*/
.side-front [class^=col-xs]:first-of-type {
 padding-left: 0;
}

.side-front-content {
 padding-top: 32px;
 padding-right: 32px;
 padding-bottom: 32px;
}

Adding styles for the backside

For the backside of our React flipping card we will set its z-index to “2”. This is just to make sure it is on the top of flipped card. Next, we will add some white space between the content and borders by setting padding to “32px”. Remember, consistency matters. The backside of our React flipping card will contain h1 heading and button. These elements should be centered. So, we can set the text-align property now and it will be applied to both elements. Finally, let’s rotate the backside around Y axis for “180” degrees.

Code:

/*- Backside -*/
.side-back {
 z-index: 2;
 padding: 32px;
 text-align: center;
 transform: rotateY(180deg);
}

Styling the contact form

Another piece of the backside is the contact form. We will use some custom styling for input elements, textarea and button. Yes, we want a custom-style React flipping card. We will begin with creating some space between form elements. Next, we will use material design to style the form elements. We will remove the borders except the bottom. Then, we will remove the outline on focus and indicate active element by changing the color of border.

Code:

/*- Form -*/
.card-form {
 margin-top: 32px;
}

.card-form .row + .row,
.card-form .row + fieldset,
.card-form fieldset + fieldset {
 margin-top: 16px;
}

input,
textarea {
 padding: 8px;
 width: 100%;
 border-top: 0;
 border-right: 0;
 border-bottom: 1px solid #eee;
 border-left: 0;
 
 &:focus {
  outline: 0;
  border-bottom: 1px solid #0c81f6;
 }
}

textarea {
 max-height: 80px;
 resize: vertical;
}

Now, we will style the button. Remember, we are using Bootstrap. So, there are some styles already applied to buttons (to inputs as well). In other words, we are going to customize the button instead of styling it from scratch. We will start by increasing its padding and font-size. Then, we will change the background-color and also remove the border added by Bootstrap. Finally, let’s add light box-shadow. We can also add styles for hover state. For example, we can change the background-color and box-shadow. Let’s also use transition to make these changes smoother.

Code:

.btn-primary {
 padding: 8px 16px;
 font-size: 16px;
 background-color: #0c81f6;
 border: none;
 box-shadow: 0 10px 35px rgba(50,50,93,.1),0 2px 15px rgba(0,0,0,.07);
 transition: background-color .25s ease-in, box-shadow .25s ease-in;
 
 &:focus,
 &:hover {
  background-color: lighten(#0c81f6, 15%);
  box-shadow: 0 18px 35px rgba(50,50,93,.1),0 8px 15px rgba(0,0,0,.07);
 }
}

Polishing the social media links

Finally, it is time to style the list with links to profiles on social media. This will be relatively quick. First, we will remove any padding from the list and the dots. Then, we will add margin to add space above the list. After that, we will set the display to “flex” and justify-content to “center”. Next, we will add margin to the left to every list item, except the first one.

For each link will set the default color to “#212121“. For hover state, we will change the opacity to “.5”. And, we will again use transition to animate the change between the default and hover states. Finally, let’s increase the font-size of icons (i element).

Code:

/*- Social links -*/
.social-links {
 padding: 0;
 margin-top: 32px;
 display: flex;
 justify-content: center;
 list-style-type: none;
 
 li:nth-of-type(n+2) {
  margin-left: 24px;
 }
 
 a {
  color: #212121;
  transition: opacity .25s ease-in;
 
  &:focus,
  &:hover {
   opacity: .5;
  }
 }
 
 i {
  font-size: 24px;
 }
}

Putting the CSS (Sass) together

This is all we need to do in case of CSS (Sass). As the final step, let’s put all the bits and pieces together so you can see it all at one place.

Code:

/*- Typograpy and resets -*/
html {
 font-size: 16px;
}

body {
 font-family: "Montserrat", "Helvetica Neue", Helvetica, Arial, sans-serif;
 font-size: 100%;
 background-color: #fff;
}

h1,
h2 {
 margin-top: 0;
}

h1 {
 margin-bottom: 16px;
 font-size: 24px;
 font-weight: 700;
}

h2 {
 margin-bottom: 12px;
 font-size: 18px;
 font-weight: 400;
}

/*- Card container -*/
.card-container {
 position: relative;
 z-index: 1;
 margin: 32px auto;
 max-width: 720px;
 height: 420px;
 perspective: 1000px;
}

img {
 max-width: 100%;
 max-height: 100%;
}

/*- Card body -*/
.card-body {
 width: 100%;
 height: 100%;
 transform-style: preserve-3d;
 transition: all .7s linear;
}

/*- Flipping the card -*/
.card-container:hover .card-body {
 transform: rotateY(180deg);
}

.card-container:hover > .card-body > .side-front {
 opacity: 0;
 visibility: hidden;
 transition: opacity 1s ease-in, visibility .75s linear;
}

/*- Card sides -*/
.card-side {
 position: absolute;
 top: 0;
 overflow: hidden;
 width: 100%;
 height: 100%;
 color: #212121;
 background-color: #fff;
 backface-visibility: hidden;
 box-shadow: 0 10px 35px rgba(50,50,93,.1),0 2px 15px rgba(0,0,0,.07);
}

/*- Frontside -*/
.side-front [class^=col-xs]:first-of-type {
 padding-left: 0;
}

.side-front-content {
 padding-top: 32px;
 padding-right: 32px;
 padding-bottom: 32px;
}

/*- Backside -*/
.side-back {
 z-index: 2;
 padding: 32px;
 text-align: center;
 transform: rotateY(180deg);
}

/*- Form -*/
.card-form {
 margin-top: 32px;
}

.card-form .row + .row,
.card-form .row + fieldset,
.card-form fieldset + fieldset {
 margin-top: 16px;
}

input,
textarea {
 padding: 8px;
 width: 100%;
 border-top: 0;
 border-right: 0;
 border-bottom: 1px solid #eee;
 border-left: 0;
 
 &:focus {
  outline: 0;
  border-bottom: 1px solid #0c81f6;
 }
}

textarea {
 max-height: 80px;
 resize: vertical;
}

.btn-primary {
 padding: 8px 16px;
 font-size: 16px;
 background-color: #0c81f6;
 border: none;
 box-shadow: 0 10px 35px rgba(50,50,93,.1),0 2px 15px rgba(0,0,0,.07);
 transition: background-color .25s ease-in, box-shadow .25s ease-in;
 
 &:focus,
 &:hover {
  background-color: lighten(#0c81f6, 15%);
  box-shadow: 0 18px 35px rgba(50,50,93,.1),0 8px 15px rgba(0,0,0,.07);
 }
}

/*- Social links -*/
.social-links {
 padding: 0;
 margin-top: 32px;
 display: flex;
 justify-content: center;
 list-style-type: none;
 
 li:nth-of-type(n+2) {
  margin-left: 24px;
 }
 
 a {
  color: #212121;
  transition: opacity .25s ease-in;
 
  &:focus,
  &:hover {
   opacity: .5;
  }
 }
 
 i {
  font-size: 24px;
 }
}

JavaScript

The last and most important step to get our React flipping card up and running is about putting together the JavaScript or React code. Since the code is quite simple, we will be able to do it fast.

Starting with small components

First, we will store the card container inside variable. Then, we will create small components for inputs, textarea, button and list with link to profiles on social media. These components are very simple. They all use only render method with very simple HTML markup. The only exception might be the list of profiles on social media. Here, we will use map function to loop through array of social networks and generate list item with link for each.

All components will contain classic html attributes such as name, id, required, etc. These attributes will be “wired” to props with the same name.

Code:

const cardContainer = document.querySelector('.react-card');

// React component for form inputs
class CardInput extends React.Component {
 render() {
  return(
   <fieldset>
    <input name={this.props.name} id={this.props.id} type={this.props.type || 'text'} placeholder={this.props.placeholder} required />
   </fieldset>
  )
 }
}

// React component for textarea
class CardTextarea extends React.Component {
 render() {
  return(
   <fieldset>
    <textarea name={this.props.name} id={this.props.id} placeholder={this.props.placeholder} required ></textarea>
   </fieldset>
  )
 }
}

// React component for form button
class CardBtn extends React.Component {
 render() {
  return(
   <fieldset>
    <button className={this.props.className} type={this.props.type} value={this.props.value}>{this.props.value}</button>
   </fieldset>
  )
 }
}

// React component for social profile links
class CardProfileLinks extends React.Component {
 render() {
  const profileLinks = ['twitter', 'linkedin', 'dribbble', 'facebook'];
 
  const linksList = profileLinks.map((link, index) =>
   <li key={index}><a href='#'><i className={'fa fa-' + link}></i></a></li>
  );
 
  return(
   <div className='card-social-links'>
    <ul className='social-links'>
     {linksList}
    </ul>
   </div>
  )
 }
}

Creating component for the frontside

Next, we will create two bigger components. One for the frontside and one for the backside of our React flipping card. Component for the frontside will contain pure HTML markup. There will be an image in the left column and short bio in the right. Nothing fancy.

Code:

// React component for the frontside of the card
class CardFront extends React.Component {
 render() {
  return(
   <div className='card-side side-front'>
    <div className='container-fluid'>
     <div className='row'>
      <div className='col-xs-6'>
       <img src='https://source.unsplash.com/w8YICpz1I10/358x458' />
      </div>

      <div className='col-xs-6 side-front-content'>
       <h2>Czech based</h2>

       <h1>UI/UX Designer</h1>

       <p>Andrey is driven by turning ideas into scalable and and empowering experiences that solve real life problems.</p>

       <p>He is currently the founder of Dvorak Media. Previously, Andrey was a product designer at Dropbox.</p>

       <p>Over the years, Michael has been priviledged to have worked with Adobe, Evernote, Square and more.</p>
      </div>
     </div>
    </div>
   </div>
  )
 }
}

Creating component for the backside

The component for the backside of our React flipping card will be also simple. It will also contain a lot of HTML markup. However, it will also use the components for form and list we created earlier.

Code:

// React component for the backside of the card
class CardBack extends React.Component {
 render() {
  return(
   <div className='card-side side-back'>
    <div className='container-fluid'>
     <h1>Let's get in touch!</h1>
 
     <form formAction='' className='card-form'>
      <div className='row'>
       <div className='col-xs-6'>
        <CardInput name='contactFirstName' id='contactFirstName' type='text' placeholder='Your first name' />
       </div>

       <div className='col-xs-6'>
        <CardInput name='contactLastName' id='contactLastName' type='text' placeholder='Your last name' />
       </div>
      </div>

      <div className='row'>
       <div className='col-xs-6'>
        <CardInput name='contactEmail' id='contactEmail' type='email' placeholder='Your email address' />
       </div>

       <div className='col-xs-6'>
        <CardInput name='contactSubject' id='contactSubject' type='text' placeholder='Subject' />
       </div>
      </div>
 
      <CardTextarea name='contactMessage' id='contactMessage' placeholder='Your message' />
 
      <CardBtn className='btn btn-primary' type='submit' value='Send message' />
     </form>
 
     <CardProfileLinks />
    </div>
   </div>
  )
 }
}

Building the card and rendering it

The last piece of the puzzle is creating component for the card. This card will use the components we created for the backside and frontside. And, finally, we will render this card component inside the card container.

Code:

// React component for the card (main component)
class Card extends React.Component {
 render() {
  return(
   <div className='card-container'>
    <div className='card-body'>
     <CardBack />

     <CardFront />
    </div>
   </div>
  )
 }
}

// Render Card component
ReactDOM.render(<Card />, cardContainer);

Putting the JavaScript (React) together

Just like we did with CSS (Sass), let’s take all the bits and pieces of React we created above and put the together. As you will see, the code for React flipping card is really very simple.

Code:

const cardContainer = document.querySelector('.react-card');

// React component for form inputs
class CardInput extends React.Component {
 render() {
  return(
   <fieldset>
    <input name={this.props.name} id={this.props.id} type={this.props.type || 'text'} placeholder={this.props.placeholder} required />
   </fieldset>
  )
 }
}

// React component for textarea
class CardTextarea extends React.Component {
 render() {
  return(
   <fieldset>
    <textarea name={this.props.name} id={this.props.id} placeholder={this.props.placeholder} required ></textarea>
   </fieldset>
  )
 }
}

// React component for form button
class CardBtn extends React.Component {
 render() {
  return(
   <fieldset>
    <button className={this.props.className} type={this.props.type} value={this.props.value}>{this.props.value}</button>
   </fieldset>
  )
 }
}

// React component for social profile links
class CardProfileLinks extends React.Component {
 render() {
  const profileLinks = ['twitter', 'linkedin', 'dribbble', 'facebook'];
 
  const linksList = profileLinks.map((link, index) =>
   <li key={index}><a href='#'><i className={'fa fa-' + link}></i></a></li>
  );
 
  return(
   <div className='card-social-links'>
    <ul className='social-links'>
     {linksList}
    </ul>
   </div>
  )
 }
}

// React component for the frontside of the card
class CardFront extends React.Component {
 render() {
  return(
   <div className='card-side side-front'>
    <div className='container-fluid'>
     <div className='row'>
      <div className='col-xs-6'>
       <img src='https://source.unsplash.com/w8YICpz1I10/358x458' />
      </div>

      <div className='col-xs-6 side-front-content'>
       <h2>Czech based</h2>

       <h1>UI/UX Designer</h1>

       <p>Andrey is driven by turning ideas into scalable and and empowering experiences that solve real life problems.</p>

       <p>He is currently the founder of Dvorak Media. Previously, Andrey was a product designer at Dropbox.</p>

       <p>Over the years, Michael has been priviledged to have worked with Adobe, Evernote, Square and more.</p>
      </div>
     </div>
    </div>
   </div>
  )
 }
}

// React component for the backside of the card
class CardBack extends React.Component {
 render() {
  return(
   <div className='card-side side-back'>
    <div className='container-fluid'>
     <h1>Let's get in touch!</h1>
 
     <form formAction='' className='card-form'>
      <div className='row'>
       <div className='col-xs-6'>
        <CardInput name='contactFirstName' id='contactFirstName' type='text' placeholder='Your first name' />
       </div>

       <div className='col-xs-6'>
        <CardInput name='contactLastName' id='contactLastName' type='text' placeholder='Your last name' />
       </div>
      </div>

      <div className='row'>
       <div className='col-xs-6'>
        <CardInput name='contactEmail' id='contactEmail' type='email' placeholder='Your email address' />
       </div>

       <div className='col-xs-6'>
        <CardInput name='contactSubject' id='contactSubject' type='text' placeholder='Subject' />
       </div>
      </div>
 
      <CardTextarea name='contactMessage' id='contactMessage' placeholder='Your message' />
 
      <CardBtn className='btn btn-primary' type='submit' value='Send message' />
     </form>
 
     <CardProfileLinks />
    </div>
   </div>
  )
 }
}

// React component for the card (main component)
class Card extends React.Component {
 render() {
  return(
   <div className='card-container'>
    <div className='card-body'>
     <CardBack />

     <CardFront />
    </div>
   </div>
  )
 }
}

// Render Card component
ReactDOM.render(<Card />, cardContainer);

Closing thoughts on React flipping card and learning React

This is it! Congrats, you’ve built your own React flipping card! And, you also learn a bit about React. If not, I hope you at least had a chance to practice your skills. In the end, this is the best way to learn anything and improve what you already know, by practicing it. If you liked this tutorial on React, and the previous, I have good news for you. I’ve been coding in React for quite a while and I have a lot of material for you. So, expect more tutorials on React in the future. And, Redux as well.

If you liked this article, please subscribe so you don't miss any future post.

If you'd like to support me and this blog, you can become a patron, or you can buy me a coffee 🙂

By Alex Devero

I'm Founder/CEO of DEVERO Corporation. Entrepreneur, designer, developer. My mission and MTP is to accelerate the development of humankind through technology.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.