My face in close-up.

Richard Blechinger

Web developer, designer, caffeine addict

Making a 3D card fade in CSS

Modern browsers are amazing in what they can do with only CSS. Today we’re taking a whirlwind tour of 3D transforms to fade in a card component.

To give you an idea of what we’ll be building, here’s a CodePen with the fully finished effect. It’s delayed by 2 seconds, but if you missed it you can just press the rerun button on the CodePen window!

See the Pen 3D Card for my blog post by Richard Blechinger (@pretzelhands) on CodePen.

The HTML

Alright, now let’s get onto the code. I’ll be writing this in my usual style, so if you’re not familiar with BEM-oriented CSS you may want to read up on that first.

First up, you need some HTML, which should look somewhat like this:

<div class="card">
  <h3 class="card__title">This is a card</h3>
  <div class="card__content">
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
  </div>
</div>

The only thing that really matters here is .card - You can put literally anything you want in there, including images. In this case I chose to put in a title and some basic Lorem ipsum text.

You should end up with something that looks like this:

The unstyled card component

Now, that doesn’t look like a card at all, so let’s whip it into shape. For that purpose we can add some quick CSS to make it look more like an actual card:

Basic animation

Note that any of the following styles can be adjusted to your own liking, these are just decorative, not related to the actual function.

.card {
  max-width: 320px;
  padding: 20px;
  box-shadow: 0 1px 5px rgba(0, 0, 0, 0.5);
}

Nothing too crazy here, but it helps us make the card more card-like. I like giving them a max-width of 320px since that is the smallest common mobile phone resolution, so they’ll always fit snuggly on the screen, while keeping the flexibility high.

The box-shadow value is kind of my go to for a Material Design-esque shadow. My card now looks like this, which is a nice and recognizable card:

The basic card component

The CSS animation properties

Now it’s time to add the animation properties to the CSS of .card, let’s see how that goes works:

.card {
  ...;

  animation-name: fade-in;
  animation-duration: 2s;
  animation-fill-mode: forwards;
}

So theres a bunch of properties here. You can also use a shorthand syntax, but I prefer being explicit with animations. Let’s look what each property does.

animation-name

This is the name of your animation. You can use any CSS selector you’d like. I used fade-in as a straightforward option.

animation-duration

As the name says, this is how long the animation lasts. For an effect like this, I’d suggest 1-2 seconds, so users really notice what’s happening.

animation-fill-mode

This specifies how the animation properties will applied to the object. Setting it to forwards means that the animation retains the state of the last keyframe.

Say you animated a green background to red. By the end of the animation the background will remain red instead of jumping back to its original green state.

I recommend reading up on MDN about the other values.

The CSS keyframe animation

Here’s the part where it gets exciting: We’re going to define the basic animation in pure CSS. I will leave off any browser prefixes for the sake of readability, but I highly suggest you read up on browser support on caniuse.com

A lot of new-fangled code will follow and I’ll show it as a whole first, then we’ll discuss the details!

@keyframes fade-in {
  0% {
    opacity: 0;
    transform:
      perspective(500px)
      rotateX(-15deg)
      translateZ(50px);
  }

  100% {
    opacity: 1;
    transform: none;
  }
}

Whew, would you look at that. A whole bunch of interesting CSS. So let’s go through it bit by bit to get a proper overview of that. First off is the keyframe syntax:

@keyframes fade-in {
  ...
}

Any animation starts off with @keyframes <animation-name>. It’s important that you use the same name you used for the animation-name earlier! In my case, it’s just fade-in.

0% { ... } // or: from { ... }
100% { ... } // or: to { ... }

The percentage properties inside the keyframe define the animation state at a certain point in time. 0% is at the beginning and can also be written as from. 100% is the final state and can also be written as to.

The percentage is based on the animation-duration that you defined earlier. For example 50% of 2 seconds would be at the 1 second mark.

Note that there is no comma in between each keyframe; you just list them down one after the other.

0% {
  opacity: 0;
  transform:
    perspective(500px)
    rotateX(-15deg)
    translateZ(50px);
}

This is the initial state of the animation. Here we set the opacity of the card to 0, so as to make the card invisible. Then we apply a whole bunch of transformations, so let’s look at them one by one.

perspective

This is perhaps the most complicated and artsy of all the transformations. Essentially what it does is to take the vanishing point and set it further into the distance, which establishes a certain … well, perspective. You really have to fiddle with it for your own use case, but I found that a value between 300px and 500px usually works fine.

This is used because the rotation would look completely flat otherwise.

Read up more on MDN

rotateX

This property rotates the card along it’s X axis. The degrees are given in standard 360 degree fashion by writing a number followed by deg. The X axis for rotation is the one that goes lengthwise through the card.

We use this to rotate the card from a slightly tilted angle to a flat one.

Read up more on MDN

translateZ

This property moves the card closer to or farther away from the viewer. It uses a plain old pixel value. The Z axis can be thought of as the ‘layer axis’. The higher the value, the bigger the card becomes. The lower the value, the smaller the card.

We use this to move the card from a slightly heightened position down to the canvas.

Read up more on MDN

100% {
  opacity: 1;
  transform: none;
}

Now we are at the final state of the animation. This is really not that complicated. We set the opacity to 1, which makes the card fully opaque and remove all transformations which makes the card lie down flat on the page.

Thanks to animation-fill-mode, this is the state that will be held by the card once the animation is done.

All together now

Here comes the full code, which you could (theoretically) entirely copy-pase into your project and you’d be good to go!

<!-- The HTML for the card -->
<div class="card">
  <h3 class="card__title">This is a card</h3>
  <div class="card__content">
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
  </div>
</div>
// The SCSS

// Animation styles
@keyframes fade-in {
  0% {
    opacity: 0;
    transform:
      perspective(500px)
      rotateX(-15deg)
      translateZ(50px);
  }

  100% {
    opacity: 1;
    transform: none;
  }
}

// Card styles
.card {
  max-width: 320px;
  padding: 20px;
  box-shadow: 0 1px 5px rgba(0, 0, 0, 0.5);

  animation-name: fade-in;
  animation-duration: 2s;
  animation-fill-mode: forwards;
}

And finally we let’s look at the finished product again!

See the Pen 3D Card for my blog post by Richard Blechinger (@pretzelhands) on CodePen.

Oh shucksy-doodles, it is beautiful! I hope you enjoyed this little tutorial on how to do a 3D card fade effect. If you wish to see more of these tutorials and other web developments goodies and tips, you can follow me on Twitter or pledge to me on Patreon.

Alternatively you can also hire me below to work on your project. Then you don’t have to think about the code and just get an amazing product out of it!

All support is appreciated!