DEV Community

Cover image for CSS Frosted glass credit card
Chris Bongers
Chris Bongers

Posted on • Originally published at daily-dev-tips.com

CSS Frosted glass credit card

Today I wanted to try and recreate a super cool dribbble shot from Dede Dwiyansyah I came across.

Dribbble frosted glass credit card

It's actually a Figma tutorial on how to create the frosted credit card effect. I decided to try and recreate this amazing shot in HTML! (With an own twist)

So time to give it my own take on CSS.

I knew it was possible to do this effect, but normally people leverage a background image filter blur, which in this case wouldn't work with the balls behind it.

So I decided to do some research, and this is my end result.

CSS Glass credit card effect

I'll be guiding you through how to make this in CSS.

HTML Structure

Let's start by defining the HTML structure for this project.

<div class="holder">
  <div class="card">
    <div class="card__text">
      8293 3412 5976 1254
      <br />
      <small>12/24</small>
    </div>
    <svg>Insert Visa logo here</svg>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

As you can see I'm using a holder div, we need this div for the two orbiting balls.

Then we have the card, which contains another container for the text, and at the end, an SVG for the visa logo.

Note: The full SVG visa logo can be found on the Codepen.

Now it's time to start the fun bit, the CSS.

CSS Frosted blurry glass effect

I'm going to be guiding you through all the little pieces we need to re-create this cool CSS frosted glass effect.

First, we need to use a font that resembles a credit card font.
I found the Inconsolata font on Google fonts works pretty well.

@import url('https://fonts.googleapis.com/css2?family=Inconsolata&display=swap');
Enter fullscreen mode Exit fullscreen mode

With this line, we import the font directly from Google fonts.

Next, we add a small reset to get rid of the default margins and paddings.

* {
  margin: 0;
  padding: 0;
}
Enter fullscreen mode Exit fullscreen mode

Now let's style the body.
In the dribbble shot, we saw the person used a gradient background, I decided to give it a background image.

body {
  background: url('https://images.pexels.com/photos/1655166/pexels-photo-1655166.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260')
    no-repeat center center;
  background-size: cover;
  display: grid;
  font-family: 'Inconsolata', monospace;
  min-height: 100vh;
  place-items: center;
}
Enter fullscreen mode Exit fullscreen mode

I'm also using the CSS grid center method to get the card centered on our page.
In this spot, we are also loading our fonts.

As mentioned we are using the holder to place our two orbiting balls in.
We will be using pseudo-elements to create these balls, so our holder will need to be a relative element.

.holder {
  position: relative;
}
Enter fullscreen mode Exit fullscreen mode

Now let's create the balls, the orange one will be created using the before pseudo element and the blue one with the after pseudo element.

They share some similarities, in size and roundness so let's write that with a double selector.

.holder:before,
.holder:after {
  animation: orbit 5s linear infinite;
  border-radius: 50%;
  box-shadow: 0 0 1rem 0 rgba(0, 0, 0, 0.2);
  content: '';
  height: 150px;
  position: absolute;
  width: 150px;
}
Enter fullscreen mode Exit fullscreen mode

This creates a round ball because of the 50% border-radius.
We also add an animation called orbit. We'll create the animation in a bit.

Now for the orange ball, we need to create a radial gradient.

.holder:before {
  background: #ffe897;
  background: -moz-radial-gradient(top right, #ffe897, #f98a05);
  background: radial-gradient(to bottom left, #ffe897, #f98a05);
  background: -webkit-radial-gradient(top right, #ffe897, #f98a05);
}
Enter fullscreen mode Exit fullscreen mode

I used css-gradient.com to generate the gradient.

Then for the blue one, we also place a radial gradient and offset it to the right side.
This one also needs an animation delay, else they'll be doing the exact same thing.

.holder:after {
  animation-delay: 2.5s;
  background: #e0e793;
  background: -moz-radial-gradient(bottom right, #e0e793, #6dd0f1);
  background: radial-gradient(to top left, #e0e793, #6dd0f1);
  background: -webkit-radial-gradient(bottom right, #e0e793, #6dd0f1);
  right: 0;
  top: 0;
  z-index: -1;
}
Enter fullscreen mode Exit fullscreen mode

Then it's time to add our card.

The card itself has a fixed size and a small box-shadow to make it pop a bit more:

.card {
  border: 1px solid #fff;
  border-radius: 15px;
  box-shadow: 0 0 1rem 0 rgba(0, 0, 0, 0.2);
  font-size: 2rem;
  height: 220px;
  overflow: hidden;
  position: relative;
  width: 370px;
}
Enter fullscreen mode Exit fullscreen mode

Then for the magic part, the blur effect we use another :before pseudo element.

.card:before {
  background-color: rgba(255, 255, 255, 0.3);
  backdrop-filter: blur(10px) saturate(100%) contrast(45%) brightness(130%);
  content: '';
  height: 100%;
  position: absolute;
  width: 100%;
}
Enter fullscreen mode Exit fullscreen mode

The whole magic blur effect comes from the backdrop-filter this gives it the blurry look.
We also use a background color with an opacity of 30% using the rgba spectrum.

For the text inside we only need to offset it a bit and make sure it's on top of everything.

.card__text {
  color: #6f7886;
  margin-left: 30px;
  margin-top: 100px;
  position: relative;
  z-index: 2;
}
Enter fullscreen mode Exit fullscreen mode

Remember we had the Visa SVG logo, we put that in the right bottom corner.

.card svg {
  bottom: 30px;
  position: absolute;
  right: 30px;
}
Enter fullscreen mode Exit fullscreen mode

Before we talked about the orbit animation, this animation will make the two balls orbit around the card, in a circular motion.

@keyframes orbit {
  from {
    transform: rotate(0deg) translateX(100px) rotate(0deg);
  }
  to {
    transform: rotate(360deg) translateX(100px) rotate(-360deg);
  }
}
Enter fullscreen mode Exit fullscreen mode

This specific animation uses a two-step animation transforming the elements to rotate from 0 to 360 degrees (a full circle).
It also offsets the translateX axis to make it move.

The full result of this can be seen on this Codepen.

Browser Support

This method relies heavily on the backdrop-filter which has quite decent support.

It can be safely used in all modern browsers, you can get some more support by leveraging all the prefixes for it.

CSS backdrop-filter support

Thank you for reading, and let's connect!

Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter

Discussion (28)

Collapse
oovictorfranco profile image
Victor Franco • Edited on

One suggestion would be to wrap the entire backdrop-filter in @supports to avoid browser read failures.

@supports ((-webkit-backdrop-filter: blur(10px) saturate(100%) contrast(45%) brightness(130%)) or (backdrop-filter: blur(10px) saturate(100%) contrast(45%) brightness(130%))) {
  .card {
    &:before {
      background-color: rgba(255, 255, 255, 0.3);
      backdrop-filter: blur(10px) saturate(100%) contrast(45%) brightness(130%);
      content: '';
      height: 100%;
      position: absolute;
      width: 100%;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode
Collapse
darkwiiplayer profile image
DarkWiiPlayer
  .card {
    &:before {
Enter fullscreen mode Exit fullscreen mode

Is there any reason for nesting that? It seems weird as the original code wasn't nested and this literally does nothing other than decrease readability 🤷

Collapse
johnylab profile image
João Ferreira

I think nesting increases readability.

Collapse
swagwik profile image
Sattwik Sahu

Your suggestion is in Sass syntax, for anyone who's getting confused why there's nesting in it. Sass is actually like a much better version of CSS, just that you can do a lot more with it.

Collapse
dailydevtips1 profile image
Chris Bongers Author

I've seen that one, but it won't really fix it for the browser, it will just not have the whole effect then?

Collapse
madza profile image
Madza

great helper tool - glassmorphism.com

Collapse
darkwiiplayer profile image
DarkWiiPlayer

Minor nitpick: The slider on that tool says "transparency", but turning it up makes it less transparent, so it should be labelled "opacity" instead.

Collapse
dailydevtips1 profile image
Chris Bongers Author

Oh nice, haven't seen that one around!

Collapse
fuzzylogic profile image
Lazar

I'm on Firefox 84 and the blur isn't there at all.

Collapse
dailydevtips1 profile image
Chris Bongers Author

So for Firefox although it states it's supported the user needs to enable the flag.
By default, it's turned off

In firefox, you could open: about:config
And search for: backdrop -> Turn this value to true and restart firefox

In that case, it will work.
I expected it too work out of the box, going to update the browser support note

Collapse
yusafs94 profile image
YusafS94

about:config

search for backdrop-filter and toggle to true

Collapse
dailydevtips1 profile image
Chris Bongers Author

Oh thanks for mentioning this I see!
Let me see what I missed 👀

Collapse
darkwiiplayer profile image
DarkWiiPlayer

I wish backdrop-filter was more widely supported. It's such a nice effect for image lightboxes, semi-transparent menu bars, etc. etc. etc.

Collapse
dailydevtips1 profile image
Chris Bongers Author

Yeah exactly, but browser support goes quick these days so hopefully soon it will be a default to use one :)

Collapse
waylonwalker profile image
Waylon Walker

That blur is beautiful

Collapse
dailydevtips1 profile image
Chris Bongers Author

Thanks it's really nice, hopefully, all browsers will quickly support it

Collapse
timhuang profile image
Timothy Huang

Cool and impressive!!

Collapse
dailydevtips1 profile image
Chris Bongers Author

Thank you Timothy, glad you like it 🤟

Collapse
ridoansaleh profile image
Ridoan

Nice animation though

Collapse
dailydevtips1 profile image
Chris Bongers Author

Thanks! Just a pity I had to put in the delay on the blue one

Collapse
mattschuette profile image
Matt Schuette

Try a negative animation-delay.

Thread Thread
dailydevtips1 profile image
Chris Bongers Author

Legend! Totally forgot those were valid!

Collapse
ash_bergs profile image
Ash

Really enjoyed this post - learning CSS is my favorite coding hobby, and I learned a lot from this post. I'll be using bits and pieces of this in the future!

Collapse
dailydevtips1 profile image
Chris Bongers Author

Awesome, glad you're picking up little things.
I think that's the whole idea just knowing about them and once you need them you're going to be like; Oh yeah that was a cool thing.

Collapse
ikurosaki profile image
ikurosaki

Hermoso 😍

Collapse
phongduong profile image
Phong Duong

Cool tip. Thank you for sharing

Collapse
dailydevtips1 profile image
Chris Bongers Author

Thank you Phong, glad you liked it ✌️