Re-Creating The Pop-Out Hover Effect With Modern CSS (Part 2)
The last time we met, I demonstrated how newer CSS features — particularly trigonometric functions — can be leveraged to accomplish a “pop-out” hover effect. This is what we made together:
Even the rotation is possible with clip-path polygon()
:
We can define the shape with three parameters:
- The number of spikes (we’ll call this
N
); - The radius of the big circle, illustrated in green (we’ll call this
R
); - The radius of the small circle illustrated in blue (this will be
R - d
).
For the sake of simplicity, I will define d
as a percentage of R
— R - (R * p)
— where p
is a number in the range [0 1]
. So, in the end, we are left with three variables, N
, R
, and p
.
If you look closely at the shape, you can see it is a series of triangular shapes that are cut out of a large circular shape. That is exactly how we are going to tackle this challenge. We can create triangles with conic-gradient
and then cut them out of the circle with the mask-composite
property. Getting a circle is pretty easy using border-radius: 50%
.
The number of conic gradients is equal to the number of triangles in the pattern. Each gradient can use nearly the same configuration, where the difference between them is how they are rotated. That means the gradient’s code will look something like this:
conic-gradient(from -1*angle at {position}, #000 2*angle, #0000 0);
Thankfully, the position we calculated in the last article is similar enough to the point that we can rely on it here as well:
50% + (50% * (1 - p)) * cos(360deg * i/N)
50% + (50% * (1 - p)) * sin(360deg * i/N)
Again, N
is the number of triangles, and p
controls the radius of the small circle. R
is equal to 50%
, so the position can also be expressed like this:
R + (R * (1 - p)) * cos(360deg * i/N)
R + (R * (1 - p)) * sin(360deg * i/N)
We need to resort to some geometry to determine the value of angle
. I will skip the boring math for the sake of brevity, but please feel free to leave a comment if you’re interested in the formula, and I will be glad to give you more details.
angle = atan(sin(180deg/N)/(p - 1 + cos(180deg/N)))
Now, we need to loop through all of that as many times as there are triangles in the pattern. So, we will do what we did in the last article and switch from vanilla CSS to Sass so we can take advantage of Sass loops.
The following snippet selects the one element in the HTML,
, and loops through the conic gradients for as many triangles we set ($n: 9
). The output of that loop is saved as another variable, $m
, that is applied to the CSS mask
.
$n: 9; /* number of spikes */
img {
--r: 160px; /* radius */
--p: 0.25; /* percent */
--angle: atan(sin(180deg/#{$n}) / (var(--p) - 1 + cos(180deg/#{$n})));
width: calc(2 * var(--r));
aspect-ratio: 1;
border-radius: 50%;
$m: ();
@for $i from 0 through ($n - 1) {
$m: append($m,
conic-gradient(
from calc(90deg + 360deg * #{$i/$n} - var(--angle)) at
calc(50% + (50% * (1 - var(--p))) v cos(360deg * #{$i/$n}))
calc(50% + (50% * (1 - var(--p))) * sin(360deg * #{$i/$n})),
#000 calc(2*var(--angle)), #0000 0),
comma
);
}
mask: $m;
}
Here’s the result of all that work:
Next, we add the scale effect to the image’s :hover
state:
img {
--f: 1.2; /* the scale factor */
/* etc */
}
img:hover {
scale: var(--f);
}
To make sure both starburst shapes have identical sizes (in the non-hover and hover states), --i
needs a formula based on the scale factor:
img {
--f: 1.2; /* the scale factor */
/* etc */
}
img:hover {
--i: calc(var(--r) * (1 - var(--p)) * (var(--f) - 1) / var(--f));
scale: var(--f);
}
And, now, we are finally finished.
See the Pen Fancy Pop Out hover effect! by Temani Afif.
Another Example
Let’s try another fancy effect where the avatar is hidden, and on hover, it slides from the bottom to “pop out” while, at the same time, we update the starburst shape.
See the Pen Fancy Pop Out Reveal hover effect! by Temani Afif.
Cool, right? We are still using only one
element in the markup, but this time, I introduced the sliding effect. This will be your homework! I will let you dissect the code to understand what I have changed.
Hint: A CSS Tip where I am using the sliding effect.
Wrapping Up
I hope you enjoy having a little extra practice on the techniques we used in the previous article to create this “pop-out” hover effect. If it feels like I went a little faster this time around, it’s because I did. Rather than spending time explaining the same concepts and techniques, I was more concerned with demonstrating them in a slightly different context. So, we learned a few new ideas for working with gradients in CSS masks and background images!
In spite of the complexity of everything we covered, there is nothing that requires you to understand everything at once or even right away. Take the time to go through this and the previous article step-by-step until you grasp the parts that are toughest for you to grok. In all honesty, you will probably never find yourself in a situation where you need to use all these tricks together. This was a pretty niche exercise. But it provides us with an excuse to individually inspect the techniques that can help you solve some complex problems in CSS without resorting to scripting or extra HTML.
As for the math and the formulas, you don’t need to accurately understand them. The goal is to demonstrate that we can be as accurate as we want when it comes to calculating values and still develop something that is incredibly maintainable with only a few variables. Without trigonometric functions and calc()
in CSS, we would be obliged to manually set all of the values once we need to update something, which would be incredibly tedious.
I’ll close this little series with a last demo. Enjoy!
See the Pen Pop out hover effect featuring Kevin and Alvaro by Temani Afif.