Today I wanted to try and recreate a super cool dribbble shot from Dede Dwiyansyah I came across.
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.
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>
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');
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;
}
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;
}
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;
}
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;
}
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);
}
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;
}
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;
}
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%;
}
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;
}
Remember we had the Visa SVG logo, we put that in the right bottom corner.
.card svg {
bottom: 30px;
position: absolute;
right: 30px;
}
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);
}
}
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.
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
Top comments (27)
One suggestion would be to wrap the entire backdrop-filter in @supports to avoid browser read failures.
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 🤷
I think nesting increases readability.
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.I've seen that one, but it won't really fix it for the browser, it will just not have the whole effect then?
great helper tool - glassmorphism.com
Minor nitpick: The slider on that tool says "transparency", but turning it up makes it less transparent, so it should be labelled "opacity" instead.
Oh nice, haven't seen that one around!
I'm on Firefox 84 and the blur isn't there at all.
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
about:config
search for backdrop-filter and toggle to true
Oh thanks for mentioning this I see!
Let me see what I missed 👀
I wish
backdrop-filter
was more widely supported. It's such a nice effect for image lightboxes, semi-transparent menu bars, etc. etc. etc.Yeah exactly, but browser support goes quick these days so hopefully soon it will be a default to use one :)
That blur is beautiful
Thanks it's really nice, hopefully, all browsers will quickly support it
Cool and impressive!!
Thank you Timothy, glad you like it 🤟
Nice animation though
Thanks! Just a pity I had to put in the delay on the blue one
Try a negative animation-delay.
Legend! Totally forgot those were valid!
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!
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.
Hermoso 😍
Cool tip. Thank you for sharing
Thank you Phong, glad you liked it ✌️