SCSS – Flipping Card Component

Today, I am going to implement a CSS card that you can flip round when you hover the mouse using SCSS.
Please note that I have learned this from the udemy course by Jonas Schmedtmann.
Main CSS properties I use are perspective, backface-visibility, background-blend-mode.
Let’s jump to the code directly and explain each part

Example

HTML Code

<div class="card">
    <div class="card__side card__side--front">
        <div class="card__picture">
             
        </div>
        <h4 class="card__heading">
            <span class="card__heading-span">
                Front Side
            </span>
        </h4>
        <div class="card__details">
            <ul>
                <li>Lorem ipsum dolor sit amet consectetur adipisicing elit. Amet nemo, qui cum excepturi repudiandae dolorum, ex necessitatibus iusto quo vitae maxime itaque ad accusamus. Vero eveniet quam ipsam nihil? Quibusdam!</li>
            </ul>
        </div>
    </div>
    <div class="card__side card__side--back">
        <div class="card__cta">
            <div class="card__price-box">
                <p class="card__price-value">Back Side</p>
            </div>
        </div>
    </div>
</div>

CSS Code

Both front/back card size will be children of card class. Since I use absolute position for the children classes we need to have relative position in the parent. The most important thing is perspective. As you can see in the video, we need perspective property to give flipping visual effect. I chose 150rem because a smaller number gives more dramatic flipping.

.card {
  // FUNCTIONALITY

  // perspective has to be in parent
  perspective: 150rem;
  -moz-perspective: 150rem;
  position: relative;
  height: 50rem;

  &__side {
    height: 50rem;
    transition: all .8s ease;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;

    // hides the back part of the element
    backface-visibility: hidden;

    border-radius: 3px;
    overflow: hidden;
    box-shadow: 0 1.5rem 4rem rgba($color-black, .15);

    &--front {
      background-color: $color-white;
    }

    &--back {
      transform: rotateY(180deg);
      background-image: linear-gradient(
          to right bottom, 
          $color-secondary-light, 
          $color-secondary-dark);
    }
  }

  // when hover, I want .card__side--front to transform
  &:hover &__side--front {
    transform: rotateY(-180deg);
  }

  &:hover &__side--back { 
    transform: rotateY(0);
  }

  // FRONT SIDE STYLING
  &__picture {
    background-size: cover;
    height: 23rem;
    background-blend-mode: screen;
    -webkit-clip-path: polygon(0 0, 100% 0, 100% 85%, 0 100%);
    clip-path: polygon(0 0, 100% 0, 100% 85%, 0 100%);

    background-image: linear-gradient(to right bottom, $color-secondary-light, $color-secondary-dark),
      url(../img/nat-5.jpg);
  }

  &__heading {
    font-size: 2.8rem;
    font-weight: 300;
    text-transform: uppercase;
    text-align: right;
    color: $color-white;
    position: absolute;
    top: 12rem;
    right: 2rem;
    width: 75%;
  }

  &__heading-span {
    padding: 1rem 1.5rem;
    -webkit-box-decoration-break: clone;
    box-decoration-break: clone;
    
    background-image: linear-gradient(
        to right bottom, 
        rgba($color-secondary-light, .85), 
        rgba($color-secondary-dark, .85));
  }

  &__details {
    padding: 3rem;

    ul {
      list-style: none;
      width: 80%;
      margin: 0 auto;

      li {
        text-align: center;
        font-size: 1.5rem;
        padding: 1rem;

        &:not(:last-child) {
          border-bottom: 1px solid $color-grey-light-2;
        }
      }
    }
  }
}

This is a pretty long code and let’s take a look at each class.

CSS – card__side

This class represents a class of both front/back side. Let’s take a look at closer look.

  &__side {
    height: 50rem;
    transition: all .8s ease;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;

    // hides the back part of the element
    backface-visibility: hidden;

    border-radius: 3px;
    overflow: hidden;
    box-shadow: 0 1.5rem 4rem rgba($color-black, .15);

    &--front {
      background-color: $color-white;
    }

    &--back {
      transform: rotateY(180deg);
      background-image: linear-gradient(
        to right bottom, 
        $color-secondary-light, 
        $color-secondary-dark);
    }
  }

// when hover, I want .card__side--front to transform
  &:hover &__side--front {
    transform: rotateY(-180deg);
  }

  &:hover &__side--back { 
    transform: rotateY(0);
  }

Since we have two sides and they need to be in the same position to flip, I used position absolute – top:0, left: 0. This is why I used position:relative in the parent card class.

Note that I put rotateY(180deg) on backside because they need to stay on 180 degree flipped while the mouse hovers over the component.

Note that on hover state I also specified &__side–front/back to transform the card whenever the mouse hover the card.

CSS – card__picture

// FRONT SIDE STYLING
  &__picture {
    background-size: cover;
    height: 23rem;
    background-blend-mode: screen;
    -webkit-clip-path: polygon(0 0, 100% 0, 100% 85%, 0 100%);
    clip-path: polygon(0 0, 100% 0, 100% 85%, 0 100%);

    background-image: linear-gradient(to right bottom, $color-secondary-light, $color-secondary-dark),
      url(../img/nat-5.jpg);
  }

It is not just an ordinary picture. It is actually blended to linear-gradient color I specified. The property for the blend is background-blend-mode. There are multiple blend mode you can explorer but I used screen here. I also used clip-path to clip the image to make it look nicer.

CSS – card__heading

  &__heading {
    font-size: 2.8rem;
    font-weight: 300;
    text-transform: uppercase;
    text-align: right;
    color: $color-white;
    position: absolute;
    top: 12rem;
    right: 2rem;
    width: 75%;
  }

  &__heading-span {
    padding: 1rem 1.5rem;
    -webkit-box-decoration-break: clone;
    box-decoration-break: clone;
    
    background-image: linear-gradient(
        to right bottom, 
        rgba($color-secondary-light, .85), 
        rgba($color-secondary-dark, .85));
  }

Heading is on top of the image. I used absolute position again in order to manually place the heading on the image.
I am going to skip explanation about. details as it’s pretty simple.

Now we have a nice looking and working flipping card component!

Leave a Reply

Your email address will not be published. Required fields are marked *