In a earlier article, we explored fancy hover results for photographs that contain shines, rotations, and 3D views. We’re going to proceed enjoying with photographs, however this time, we’re making animations that reveal photographs on hover. Particularly, we’ll find out about CSS masks and the way they can be utilized to cowl parts of a picture which can be revealed when the cursor hovers over the picture.
Right here is the HTML we’ll use for our work:
<img src=”” alt=””>
Sure, that’s proper, just one picture tag. The problem I wish to tackle with every new CSS challenge is: Let CSS do the entire work with out further markup.
As we go, you could discover minor variations between the code I share within the article and what’s used contained in the demos. The code all through the article displays the CSS specification. However since browser assist is inconsistent with among the options we’re utilizing, I embrace prefixed properties for broader assist.
Instance 1: Circle Reveal
On this first one, a picture sits in a sq. container that’s wiped away on hover to disclose the picture.
So, we’ve two photographs, every with a gradient background that’s revealed with a contact of padding. We might have added a <div> — or even perhaps a <determine> — to the markup to create a real container, however that goes towards the problem of letting CSS do the entire work.
Whereas we have been capable of work across the want for further markup, we now must ask ourselves: How can we cover the picture with out affecting the gradient background? What we want is to cover the picture however proceed to point out the padded space round it. Enter CSS masks.
It’s not terribly difficult to use a masks to a component, however it’s a bit trickier on this context. The “trick” is to chain two masks layers collectively and be extra specific about the place the masks are utilized:
img {
/* and many others. */
masks:
linear-gradient(#000 0 0) padding-box,
linear-gradient(#000 0 0) content-box;
}
Now we’ve two masks “sources”:
content-box: one that’s restricted to the picture’s content material,
padding-box: one which covers the entire picture space, together with the padded space.
We’d like two layers as a result of then we are able to mix them with the CSS mask-composite property. We have now other ways to mix masks layers with mask-composite, considered one of which is to “exclude” the realm the place the 2 masks overlap one another.
img {
/* and many others. */
masks:
linear-gradient(#000 0 0) padding-box,
linear-gradient(#000 0 0) content-box;
mask-composite: exclude;
}
It will make solely the gradient seen (the padded space), as you possibly can see under.
See the Pen Overview of the exclude composition by Temani Afif.
Discover that we are able to take away the padding-box from the code since, by default, a gradient covers the entire space, and that is what we want.
Are there different methods we might do that with out mask-composite? There are lots of methods to cover the content material field whereas displaying solely the padded space. Right here is one method utilizing a conic-gradient because the masks:
masks:
conic-gradient(from 90deg at 10px 10px, #0000 25%, #000 0)
0 0 / calc(100% – 10px) calc(100% – 10px);
/* 10px is the worth of padding */
See the Pen Border-only utilizing conic-gradient by Temani Afif.
There are others, in fact, however I believe you get the concept. The method you select is completely as much as you. I personally suppose that utilizing mask-composite is greatest because it doesn’t require us to know the padding worth prematurely or change it in multiple place. Plus, it’s likelihood to apply utilizing mask-composite.
Now, let’s exchange the second gradient (the one overlaying solely the content material space) with a radial-gradient. We would like a circle swipe for the hover transition, in spite of everything.
img {
masks:
linear-gradient(#000 0 0),
radial-gradient(#000 70%,#0000 71%) content-box;
mask-composite: exclude;
}
See the Pen Including the radial-gradient by Temani Afif.
See that? The exclude masks composite creates a gap within the picture. Let’s play with the dimensions and place of that cutout and see what is occurring. Particularly, I’m going to chop the dimensions in half and place the circle within the middle of the picture:
masks:
linear-gradient(#000 0 0),
radial-gradient(#000 70%,#0000 71%) content-box
middle / 50% 50% no-repeat;
mask-composite: exclude;
See the Pen Updating the radial-gradient dimension and place by Temani Afif.
I wager you possibly can already see the place that is going. We alter the dimensions of the radial-gradient to both cover the picture (improve) or reveal the picture (lower). To completely cover the picture, we have to scale the masks as much as such an extent that the circle covers up the picture. Meaning we want one thing larger than 100%. I did some boring math and located that 141% is the exact quantity, however you may wing it with a spherical quantity for those who’d like.
That provides us our ultimate CSS for the impact:
padding: 10px; /* management the thickness of the gradient “border” */
background: repeating-linear-gradient(45deg, #FF6B6B 0 10px, #4ECDC4 0 20px);
masks:
linear-gradient(#000 0 0),
radial-gradient(#000 70%, #0000 71%) content-box
50% / var(–_s, 150% 150%) no-repeat;
mask-composite: exclude;
transition: .5s;
}
img:hover {
–_s: 0% 0%;
}
A number of minor particulars:
We begin with a dimension equal to 150% 150% to initially cover the picture. I’m taking the extra step of making use of the dimensions as a CSS variable (–_s) with the total dimension (150% 150%) as a fallback worth. This fashion, all we have to do is replace the variable on hover.
Add a hover state that decreases the dimensions to zero in order that the picture is totally revealed.
Apply a slight transition of .5s to easy out the hover impact.
Right here’s the ultimate demo yet another time:
See the Pen Hover reveal animation utilizing masks by Temani Afif.
We simply created a pleasant reveal animation with just a few strains of CSS — and no extra markup! We didn’t even have to resort to pseudo-elements. And that is merely one strategy to configure issues. For instance, we might play with the masks’s place to create a slick variation of the impact:
See the Pen One other variation of the round reveal animation by Temani Afif.
I’m a giant fan of placing an concept on the market and pushing it ahead with extra experiments. Fork the demo and let me know what attention-grabbing issues you may make out of it!
Instance 2: Diagonal Reveal
Let’s improve the problem and attempt to create a hover impact that wants three gradients as an alternative of two.
See the Pen Hover reveal animation utilizing masks II by Temani Afif.
Do not have a look at the code simply but. Let’s attempt to create it step-by-step, beginning with a less complicated impact that follows the identical sample we created within the first instance. The distinction is that we’re swapping the radial-gradient with a linear-gradient:
padding: 10px; /* management the thickness of the gradient “border” */
background: repeating-linear-gradient(45deg, #FF6B6B 0 10px, #4ECDC4 0 20px);
masks:
linear-gradient(#000 0 0),
linear-gradient(135deg, #000 50%, #0000 0) content-box
0% 0% / 200% 200% no-repeat;
mask-composite: exclude;
transition: .5s;
}
img:hover {
mask-position: 100% 100%;
}
You’ll discover that the opposite minor distinction between this CSS and the primary instance is that the dimensions of the masks is the same as 200% 200%. Additionally, this time, the masks’s place is up to date on hover as an alternative of its dimension, going from 0% 0% (top-left) to 100% 100% (bottom-right) to create a swiping impact.
See the Pen Diagonal reveal animation utilizing masks by Temani Afif.
We are able to change the swipe path merely by reversing the linear gradient angle from 135deg to -45deg, then updating the place to 0% 0% on hover as an alternative of 100% 100%:
padding: 10px; /* management the thickness of the gradient “border” */
background: repeating-linear-gradient(45deg, #FF6B6B 0 10px, #4ECDC4 0 20px);
masks:
linear-gradient(#000 0 0),
linear-gradient(-45deg, #000 50%, #0000 0) content-box
100% 100% / 200% 200% no-repeat;
mask-composite: exclude;
transition: .5s;
}
img:hover {
mask-position: 0% 0%;
}
See the Pen Diagonal reveal animation utilizing masks by Temani Afif.
Another factor: I outlined solely one mask-position worth on hover, however we’ve two gradients. For those who’re questioning how that works, the masks’s place applies to the primary gradient, however since a gradient occupies the total space it’s utilized to, it can’t be moved with proportion values. Meaning we are able to safely outline just one worth for each gradients, and it’ll have an effect on solely the second gradient. I clarify this concept way more totally in this Stack Overflow reply. The reply discusses background-position, however the identical logic applies to mask-position.
Subsequent, I’d wish to attempt to mix the final two results we created. Examine the demo under to know how I need the mix to work:
See the Pen Mixture of two diagonal reveal by Temani Afif.
This time, each gradients begin on the middle (50% 50%). The primary gradient hides the top-left a part of the picture, whereas the second gradient hides the bottom-right a part of it. On hover, each gradients slide in the wrong way to disclose the total picture.
For those who’re like me, you’re in all probability considering: Add all of the gradients collectively, and we’re accomplished. Sure, that’s the most intuitive answer, and it could appear like this:
padding: 10px; /* management the thickness of the gradient “border” */
background: repeating-linear-gradient(45deg, #FF6B6B 0 10px, #4ECDC4 0 20px);
masks:
linear-gradient(#000 0 0),
linear-gradient(135deg, #000 50%, #0000 0) content-box
50% 50% / 200% 200% no-repeat,
linear-gradient(-45deg, #000 50%, #0000 0) content-box
50% 50 / 200% 200% no-repeat;
mask-composite: exclude;
transition: .5s;
cursor: pointer;
}
img:hover {
mask-position: 0% 0%, 100% 100%;
}
See the Pen Combining each results by Temani Afif.
This method sort of works, however we’ve a small visible glitch. Discover how an odd diagonal line is seen as a result of nature of gradients and points with anti-aliasing. We are able to attempt to repair this by growing the share barely to 50.5% as an alternative of fifty%:
See the Pen Making an attempt to repair the anti-aliasing difficulty by Temani Afif.
Yikes, that makes it even worse. You’re in all probability questioning if I ought to lower the share as an alternative of accelerating it. Attempt it, and the identical factor occurs.
The repair is to replace the mask-composite property. For those who recall, we’re already utilizing the exclude worth. As an alternative of declaring exclude alone, we have to additionally apply the add worth to ensure the underside layers (the swiping gradients) aren’t excluded from one another however are as an alternative added collectively:
img {
masks:
/* 1st layer */
linear-gradient(#000 0 0),
/* 2nd layer */
linear-gradient(135deg, #000 50.5%, #0000 0) content-box
50% 50% / 200% 200% no-repeat,
/* third layer */
linear-gradient(-45deg, #000 50.5%, #0000 0) content-box
50% 50% / 200% 200% no-repeat;
mask-composite: exclude, add;
}
Now, the second and third layers will use the add composition to create an intermediate layer that might be excluded from the primary one. In different phrases, we should exclude all of the layers from the primary one.
I do know mask-composite is a convoluted idea. I extremely advocate you learn Ana Tudor’s crash course on masks composition for a deeper and extra thorough rationalization of how the mask-composite property works with a number of layers.
This fixes the road difficulty in our hover impact:
See the Pen Diagonal reveal animation utilizing masks by Temani Afif.
Another small element you will have noticed: we’ve outlined three gradients within the code however solely two mask-position values on the hover state:
img:hover {
mask-position: 0% 0%, 100% 100%;
}
The primary worth (0% 0%) is utilized to the primary gradient layer; it will not transfer because it did earlier than. The second worth (100% 100%) is utilized to the second gradient layer. In the meantime, the third gradient layer makes use of the primary worth! When fewer values are declared on mask-position than the variety of masks layers, the sequence of comma-separated values repeats till the entire masks layers are accounted for.
On this case, the sequence repeats circles again to the primary worth (0% 0%) to make sure the third masks layer takes a price. So, actually, the code above is a extra succinct equal to scripting this:
img:hover {
mask-position: 0% 0%, 100% 100%, 0% 0%;
}
Right here is the ultimate demo once more with each variations. You will notice that the second instance makes use of the identical code with minor updates.
See the Pen Hover reveal animation utilizing masks II by Temani Afif.
Instance 3: Zig-Zag Reveal
I’ve yet another instance for you, this time revealing the picture with zig-zag edges sliding aside, type of like enamel chomping on the picture.
See the Pen Hover reveal animation utilizing masks III by Temani Afif.
Whereas this will likely appear like a extra advanced hover impact than the final two we lined, it nonetheless makes use of the identical underlying CSS sample we’ve used all alongside. In truth, I’m not even going to dive into the code as I need you to reverse-engineer it utilizing what you now learn about utilizing CSS gradients as masks and mixing masks layers with mask-composite.
I gained’t provide the reply, however I’ll share an article I wrote that demonstrates how I created the zig-zag form. And since I’m feeling beneficiant, I’ll hyperlink up this on-line border generator as one other useful resource.
Wrapping Up
I hope you loved this little experiment with CSS masks and gradients! Gradients might be complicated, however mixing them with masks is nothing wanting difficult. However after spending the time it takes to take a look at three examples in items, we are able to clearly see how gradients can be utilized as masks in addition to how we are able to mix them to “draw” seen areas.
As soon as we’ve an concept of how that works, it’s superb that every one we have to do to get the impact is replace both the masks’s place or dimension on the aspect’s hover state. And the truth that we are able to accomplish all of this with a single HTML aspect reveals simply how highly effective CSS is.
We noticed how the identical normal CSS sample might be tweaked to generate numerous variations of the identical impact. I believed I’d finish this text with just a few extra examples so that you can play with.
See the Pen Hover reveal animation utilizing masks IV by Temani Afif.
See the Pen Hover reveal animation utilizing masks V by Temani Afif.
See the Pen Hover reveal animation utilizing masks VI by Temani Afif.
Additional Studying on Smashing Journal
“CSS And Accessibility: Inclusion By Person Selection,” Carie Fisher
“Gradients, Mix Modes, And A Actually Cool Hover Impact,” Preethi Sam
“A Few Fascinating Methods To Use CSS Shadows For Extra Than Depth,” Preethi Sam
“Falling For Oklch: A Love Story Of Colour Areas, Gamuts, And CSS,” Geoff Graham
Subscribe to MarketingSolution.
Receive web development discounts & web design tutorials.
Now! Lets GROW Together!