How to Create a Shimmer Effect Using HTML and CSS?
Learn how to create the 'shimmer' effect using HTML and CSS, commonly used as a UX pattern to represent loading.
16 mins •
What is the shimmer effect?
Let's start by witnessing the shimmer effect in real.
Here's a quick glimpse:
As complicated as it might seem to you, creating this effect is superbly simple. In fact, you might've already dissected into its individual bits and pieces by looking into the effect above.
The shimmer effect is implemented using a CSS linear gradient background paired with a CSS animation to move the background constantly.
That's it. Yes, literally just that!
So shall we get to the implementation? Let's go.
Dissecting the implementation
We'll start by creating a small rectangle <div>
:
<div></div>
div {
height: 150px;
width: 300px;
background-color: lightgray
}
You already know all of this, right?
Here's the output of this:
We'll be removing this light gray background color in no time below. For now, it's only to showcase the size of the <div>
.
Anyways, let's apply a gradient to the background of this <div>
.
CSS allows us to create two kinds of gradients: linear and radial.
Obviously, a radial gradient can't be used to replicate the shimmer effect, and it won't even look nice (what do you say?), which leaves us with the former choice — a linear gradient. And that's exactly how the shimmer effect is implemented.
But where to begin in this linear gradient?
Well, again as always, we strongly encourage you (yes you) to think about it and get your amazing brain power into it. You have a lot more potential in you than you can think of.
Assuming that you've done your thinking, let's now see it together how to implement this effect
Notice the white line in the shimmer effect which is the actual replication of the 'shimmer' (i.e. the shine). On the further ends away from this white line, the background color seems to be the same tints of gray. Hmm.
This means that the linear gradient should begin at some tint of gray and end at that same tint of gray, while having a white color in between (or if not white, still something considerably lighter than those grays in order to really shine through).
See, we're getting somewhere.
Let's go to our CSS and start spilling out whatever is coming to the mind.
Replicating the shimmer
So restating what we concluded above, we'll start with a gray tint, followed by a much lighter tint, followed by the same initial gray tint.
Let's use #eee
as the gray tint and #fafafa
as the lighter, shimmer tint.
Here's the setup of our linear gradient, using the linear-gradient()
function in CSS:
div {
height: 150px;
width: 300px;
background: linear-gradient(to right, #eee, #fafafa, #eee);
}
Notice that we've removed the background-color
style, now that background
is there.
Let's see what we get:
Nice, but the white shimmer is way too much scattered. Let's reduce its spread.
Remember how to do that in linear-gradient()
? We ought to set a percentage value after the color value to specify the position at which the color should begin.
Since we want our shimmer right in the center, we'll start off with specifying the position for the #fafafa
color (belonging to the shimmer):
div {
height: 150px;
width: 300px;
background: linear-gradient(to right, #eee, #fafafa 50%, #eee);
}
50%
means that #fafafa
would be concentrated right at the center of the background. So far, so good.
But just this won't produce any change because linear-gradient()
is already configured to evenly position all the colors in the background. We have to now set the positions of the first and last gray colors.
The positions of both these end points should be equi-distant from the center color.
That means that if, for example, the first gray color is at 20%
, then the last gray color should be at 80%
(both colors being at a distance of 30%
from the center). Similarly, if the starting gray color is at 45%
, the ending one should be at 55%
(with the same distance of 5%
).
We feel that 40%
and 60%
might be a good strike of balance, so let's do so and see the effect produced:
div {
height: 150px;
width: 300px;
background: linear-gradient(to right, #eee 40%, #fafafa 50%, #eee 60%);
}
Well, it looks very nice! Doesn't it?
Having ticked the first box of nicely reproducing the shimmer, let's now angle it.
Angling the shimmer
Typically, when implementing the shimmer effect, the shimmer is placed at an angle rather than being pitch straight.
Once again, angling the shimmer isn't any difficult at all — it's just one simple step.
That is, we only have to change the to right
keyword to -45deg
to specify the angle at which the gradient will proceed. But why -45deg
and not 45deg
?
Well, let's start by 45deg
, see why it won't work and then get back to -45deg
.
Here's the CSS for 45deg
:
div {
height: 150px;
width: 300px;
background: linear-gradient(45deg, #eee 40%, #fafafa 50%, #eee 60%);
}
And here's its output:
As can be seen, the shimmer runs from the top-left point to the bottom-right, looking like a backslash (\).
Usually, if we take a look out there, shimmers don't look this way. They are typically positioned like a forward slash (/).
Why is that so? Well, that's because when the shimmer moves from left to right, the one that looks like a backslash (\
) seems to start from the bottom and go upwards; that's something that doesn't look that nice. It's better to begin at the top and end at the bottom.
And that's achieved when the shimmer resembles a forward slash (/
)
Let's now turn to the -45deg
case, producing a shimmer akin to a forward slash (/):
div {
height: 150px;
width: 300px;
background: linear-gradient(-45deg, #eee 40%, #fafafa 50%, #eee 60%);
}
Yup, much better. So, we'll proceed with this.
The next step, now that we've completed our entire shimmer effect, is to add a pinch of animation to it. That's right, just a pinch of it.
But first we need to prepare certain things before we can finally bring in an animation.
Preparing the animation
Let's start by asking a naive question: What do you think will happen in the animation of our <div>
?
Well, the background gradient will move. "How?" you ask. Background gradients in CSS are treated as background images and thus all the properties that apply to background images, more or less, apply to background gradients as well.
In our case, since we want to move the background gradient horizontally, we'll be needing...you guessed it...the background-position-x
property.
But there's an additional thing to note.
When background-position is given a percentage value, for e.g. 100%
, the position of the background image (remember, a gradient is also an image) is determined relative to the absolute value of the following expression:
element width - image width (after resolution)
The issue is that when the background position is 100%
, which is the default, the expression above resolves to 0
since the width of the element equals the (final) width of the image. This means that any percentage value given to background-position-x
would resolve to 0
as well, thus rendering no movement.
The solution? Well, in our case, we should give double the size of the background image, i.e. using 200%
or maybe 300%
.
Let's try using 300%
:
div {
height: 150px;
width: 300px;
background: linear-gradient(-45deg, #eee 40%, #fafafa 50%, #eee 60%);
background-size: 300%;
}
Oops! That size got the shimmer to go out of initial view. We'll bring it to the desired position (whatever that is for our example) in a while; for now, let's see whether background-position-x
is working with percentage values.
Below we try a position of -100%
:
div {
height: 150px;
width: 300px;
background: linear-gradient(-45deg, #eee 40%, #fafafa 50%, #eee 60%);
background-size: 300%;
background-position-x: -100%
}
Yeah, so it's working.
Below we try another position, this time 40%
.
div {
height: 150px;
width: 300px;
background: linear-gradient(-45deg, #eee 40%, #fafafa 50%, #eee 60%);
background-size: 300%;
background-position-x: 40%
}
Fantastic.
Now, let's think about the position at which we should initially leave the gradient.
Well, the best configuration is for it to be positioned right before the top-left corner, to be ultimately brought in by movement via an animation over background-position-x
.
And the value 100%
will be sufficient for dealing with this:
div {
height: 150px;
width: 300px;
background: linear-gradient(-45deg, #eee 40%, #fafafa 50%, #eee 60%);
background-size: 300%;
background-position-x: 100%
}
This seems great.
Notice an important pattern here. As we increase the value of background-position-x
, the shimmer moves leftwards. Similarly, as we increas the value of background-position-x
, the shimmer moves rightwards.
We'll be leveraging this pattern in the next section where we finally consider our animation.
Adding the animation
To add the animation, we'll use the CSS animation
property.
Let's decide on the different aspects of the animation:
- Since the shimmer animation usually needs to run indefinitely while something is loading (which is what this effect is used for), we'll use an
infinite
animation count. - The time should be the time to complete one movement from the left to the right; let's go with
1s
. - The timing function could be
linear
to make the movement constant, without any kinds of accelerations (when usingease
, orease-in
, or other functions).
In the following code, we define an animation
using these aspects on our <div>
:
div {
height: 150px;
width: 300px;
background: linear-gradient(-45deg, #eee 40%, #fafafa 50%, #eee 60%);
background-size: 300%;
background-position-x: 100%
animation: shimmer 1s infinite linear;
}
Let's now define the keyframes for shimmer
.
Recall that we stated above that as we reduce the value of background-position-x
, the shimmer moves rightwards.
Because we want this very nature of movement, i.e. from left to right, in our effect, we'll be applying a value to background-position-x
in the to
keyframe that's less than 100%
(the initial value of the background-position-x
).
Precisely, we'll be using 0%
. This is because at that point the shimmer sits at the bottom-right corner of the element, completing one cycle of movement (from the left to the right).
This is accomplished below:
@keyframes shimmer {
to {
background-position-x: 0%
}
}
Let's see the output produced:
Oh! That looks stunning!
infinite
animation count for the example; we've instead used a count of 10
. So after 10 cycles, the animation would stop. In a real-world application, you'll however want infinite cycles because the underlying assets will eventually load and ultimately replace these shimmer effect loading indicators.And here we have our shimmer effect, created purely using HTML and CSS.
In the end
As you saw, producing the scintilating shimmer effect using just HTML and CSS was very easy. We just needed to have our basics right, and that's all.
You could tweak the effect in whatever way you like, but obviously keeping the main idea of the shimmer intact. You can change the end point colors of the gradient, or maybe make the shimmer more concentrated, or maybe even change the speed of its movement.
There's a lot to play around with in this effect.
And nothing is better than experimenting with some HTML and CSS in some free time. What do you say?