In the design world, masking is a popular technique to achieve unique design effects, as a designer I have used it many times, but I have used CSS masks on web pages very rarely, I think the reason I don’t use CSS masks is because of browser support, they are only partially supported in blink browsers (Chrome and Edge), while they are fully supported in Safari and Firefox.


The good news is that CSS masking will be part of Interop 2023, which means we should expect cross-browser support (yay!!!) .


In this post, I’ll cover what CSS masking is, how it works, and output some use cases and examples that incorporate it.

 Let’s get started.

 What is a mask?


Simply put, a mask works by partially hiding an element without erasing it.

 Refer to the images below:


We have an image and a mask, and in a design application like Photoshop, we can insert the image inside a gray shape, which creates a masked image.


It works by hiding certain parts of the image instead of erasing it (they are still there, just hidden).


This is the core concept of masking, using a shape to show and hide a part of an element, and we can further explore more unique masking content.

 For example, we can create a gradient mask like the one shown below.


In a gradient, there are filled and transparent pixels; the filled part is part of the visible area of the element and the transparent part is the hidden part.


In Photoshop, we can add a layer mask to a group of layers and the contents of the group will be masked. It works by using the Brush tool to hide part of the group to achieve the mask.


The masked content is not erased, it is hidden (note the group item).


Well, all of the above is on the theoretical side, in the next article I will cover CSS masking, how it works and some use cases and examples.

 How to use masks in CSS

 There are several ways to mask elements in CSS:

  •   mask causality
  •   clip-path causality
  • SVG <mask>


mask The main difference between the clip-path property and the mask property is that the former is used for images and gradients, while the latter is used for paths; the focus of this article will be on the property.


In CSS, we have the mask shorthand property, similar to the background property, yes, you read that right. That’s why I think it’s easy to remember the syntax because it’s exactly the same as the background attribute, but with a handful of other properties.


Instead of listing all the CSS masking properties, I’ll add a step-by-step example of the masking feature so you can visually spot the difference.

 The CSS background is shown below:

.card__thumb {
    background-image: url('hero-cool.png');
}

 The CSS mask is shown below:

.card__thumb {
    mask-image: url('hero-cool.png');
}


Pretty cool, right? This makes understanding and mastering CSS masks much easier.

 Now, let’s redo the original example with CSS.

 First, I need to export the shape as a png image.

 Suppose I want to apply a mask to that image.

<img src="ahmad-shadeed-web-directions.jpg" alt="" />
img {
    mask-image: url("shape.png");
}


Can you predict the result? By default, the mask will be duplicated and its size will be equal to the mask image itself, as shown below:


To recover, we need to set mask-repeat to no-repeat , just like the CSS background image.

img {
    mask-image: url("shape.png");
    mask-repeat: no-repeat;
}


Great! Note that the mask is located in the upper left corner, and it can be changed via mask-position Note again that the syntax is identical to the CSS background image configuration!

img {
    mask-image: url("shape.png");
    mask-repeat: no-repeat;
    mask-position: center;
}


In addition to the position, we can also change the mask size, which is useful for responding to the size of an element using a masked image.

img {
    mask-image: url("shape.png");
    mask-repeat: no-repeat;
    mask-position: center;
    mask-size: 60%;
}


There are also some mask properties, but I don’t want to discourage you from learning with them now; I’ll cover them later with real-world use cases.

 Masking with CSS Gradients


CSS masking is not just about using images, we can also utilize gradients to create powerful and useful masking effects.


I’ll show some useful use cases later, but for now, I want to focus on the basics of how gradients work with masks.


In the following example, mask-image consists of a CSS linear gradient from all black to transparent.

img {
    mask-image: linear-gradient(#000, transparent);
}

 According to MDN:


By default, this means that the alpha channel of the masked image will be multiplied by the alpha channel of the element, which can be controlled using the mask-mode attribute.


This means that you can use any color except black and the mask will still work because the default mask mode is set to alpha (I’ll cover this in more detail later).

img {
    mask-image: linear-gradient(red, transparent);
}


Again, the idea of a mask is that transparent pixels will be hidden, and the following is a simplified example of a gradient with a hard color stop:

img {
    mask-image: linear-gradient(#000 50%, transparent 0);
}


Too cool! Now that the core masking concept is clear (I hope), let’s explore some real-world use cases for CSS masking.

 Practical use cases and examples

 Fade Image


An interesting use for using masks is to make the image fade out and blend with the background underneath it.

 Consider the following image:

css-masking-use-case-fade-image-light.png


At first glance, you might want to add a gradient that is the same color as the background. Like this:

.hero__thumb:after {
    position: absolute;
    inset: 0;
    background: linear-gradient(to top, #f1f1f1, transparent)
}


While this may work, it fails when the main background color changes, noting that the home banner stutters:


Using CSS masks, we can mask the homepage banner to work with any background color.

.hero__thumb {
    mask-image: linear-gradient(#000, transparent);
}


That’s it! The fade transition effect is now real and does not fail when changing the background of the main page, see the example below:

 Mask text content: Example 1


When we want to display long text but there is not enough space to display it fully, the solution is to fade the text at the beginning and the end, and then the text will animate in either direction to show the rest of the content.

 Consider the following image:


Once again, the hack with the gradient doesn’t work because the background underneath the content is changed, which can be a solid color or an image.


To implement it in CSS, we need to add a gradient mask to fade the content at the beginning and end.


I like the idea of doing this in a CSS gradient and seeing the result, then applying it as a mask, which helps visualize the gradient before using it as a mask.

.c-card__footer {
    background-image: linear-gradient(90deg, transparent, #000 15%, #000 85%, transparent 100%);
}

 With the above, we can apply it as a mask.

.c-card__footer {
    mask-image: linear-gradient(90deg, transparent, #000 15%, #000 85%, transparent 100%);
}


Still not perfect? We can fine-tune the gradient values until the result is perfect.

 Mask text content: Example 2


This is the same as the previous example, but applied vertically, which I’ve seen in live Instagram videos.

 Consider the following image:


Notice the content being flushed out from the top? This small place can have feed comments, actions and other content. Using CSS masks is perfect for this.

 First, let’s look at the gradient.

 In CSS, it might look like this:

.whatever-the-class-name {
    mask-image: linear-gradient(to bottom, transparent, #000);
}

 Mask List


I came across this really cool example when I was working on CSS masking, and the idea is that we have a series of features, courses, or whatever, and we want to fade the text to make the user more curious about what’s in it.

 Consider the following example:


You can see a list on the left, fading in at the very bottom, using a CSS mask is perfect for this operation as it blends in with the background underneath, whether it’s an image or a dark background.

 Let’s take a look at the Mask Gradient to understand how it works.

 In CSS, it looks like this:

.list {
    mask-image: linear-gradient(to bottom, #000, transparent 95%);
}

 Interesting image effects


With CSS masks and gradients, the possibilities for creating visual effects are endless. This is a simple example of how we can create visual effects for images.

 Here’s a quick design I created for this demo.


The image effect you see consists of 5 linear gradients, and by adding a different gradient position to each gradient, we can get a similar effect.

 Let’s look at the gradient in more detail:

.thumb {
    mask-image: linear-gradient(to bottom, #000, #000),
    linear-gradient(to bottom, #000, #000),
    linear-gradient(to bottom, #000, #000),
    linear-gradient(to bottom, #000, #000),
    linear-gradient(to bottom, #000, #000);
    mask-size: 18% 70%;
    mask-position: 0 100%, 25% 25%, 50% 50%, 75% 0, 100% 50%;
    mask-repeat: no-repeat;
}

 Visually, the mask is shown below:


To create a fade effect on the mask of each rectangle, we need to update each gradient and include the “transparent” keyword.

.thumb {
    mask-image: linear-gradient(to bottom, transparent, #000),
    linear-gradient(to bottom, #000, transparent),
    linear-gradient(to bottom, transparent, #000),
    linear-gradient(to bottom, #000, transparent),
    linear-gradient(to bottom, transparent, #000);
    mask-size: 18% 70%;
    mask-position: 0 100%, 25% 25%, 50% 50%, 75% 0, 100% 50%;
    mask-repeat: no-repeat;
}


We can also animate the mask size or position on hover.


It’s powerful, and imagine combining it with scroll-based animation and things could get out of hand (but in a good way).

 Rounded corner tabs


I’m thinking of trying a CSS mask for a UI effect called Rounded Tabs.


The idea is that we want to round the sides of the element in a way that blends with the border-radius of the element.


In this blog post, Chris Coyier explains a technique implemented using multiple pseudo-elements, the more dynamic solution being the use of CSS masks.

 First, let’s take a closer look at the shape I’m trying to achieve.


The shape consists of a square and a circle, and all we need is their intersection.


How can this be done? We can perform composting operations on them using multiple layers of masks and the mask-composite attribute.

 First, we need to create an element to hold the mask.

.nav-item.active:before {
    content: "";
    position: absolute;
    left: 100%;
    bottom: 0;
    width: 24px;
    height: 24px;
    background-color: var(--active-bg);
}


In this space, we need to draw a circle and a square to be combined, and luckily we can do that by mixing linear and radial gradients.

.nav-item.active:before {
    content: "";
    position: absolute;
    left: 100%;
    bottom: 0;
    width: 24px;
    height: 24px;
    background-color: var(--active-bg);
    background-image: linear-gradient(to top, #000, #000),
    radial-gradient(circle 15px at center, #000 80%, transparent 81%);
    background-size: 12px 12px, 100%;
    background-position: bottom left, center;
    background-repeat: no-repeat, repeat;
}

 Note the following:

  •  I added 12px 12px as the size for the square.
  •  The square is located in the lower left corner.
  •  Square shapes do not need to be repeated.


The above is just to visually illustrate the effect of the two gradients, the next step is to implement them! In CSS masks, we can use the mask-composite property to combine two shapes.

.nav-item.active:before {
    content: "";
    position: absolute;
    left: 100%;
    bottom: 0;
    width: 24px;
    height: 24px;
    background-color: var(--active-bg);
    mask-image: linear-gradient(to top, red, red),
    radial-gradient(circle 15px at center, green 80%, transparent 81%);
    mask-size: 12px 12px, 100%;
    mask-position: bottom left, center;
    mask-repeat: no-repeat, repeat;
    mask-composite: subtract;
}


This is the CSS right side of the above shape. For the other one, we just need to change mask-position to flip it.

.nav-item.active:after {
    mask-position: bottom right, center;
}

 Multiple Avatar Cropping


In my article on skeletonization effects, I explored different ways to create skeletons using CSS.

 One example is perfect for CSS masks.


With CSS masks, we can use radial gradients to achieve this effect.

.avatar {
    -webkit-mask-image: radial-gradient(ellipse 54px 135px at 11px center, #0000 30px, #000 0);
}


I highly recommend reading this article as there are many detailed examples like this one.


When I started learning about CSS masking, there were limited resources and more importantly, very few practical use cases that we could use in our daily workflow. I hope this article gives you an idea of where you can use CSS masks in your next project.


By the way, I haven’t delved into properties like mask-mode because, to be honest, I haven’t found a problem to solve with them (until now). I’ll update this post when I have a more convincing example of using such attributes.

 More resources


If you want to improve your skills in more CSS masking examples, then you must check out the following:


  • Gorgeous hover effect for your avatar by Temani Afif

  • Mask Compositing: Quick Start Course by Ana Tudor

  • Speech bubbles using only CSS by Temani Afif

  • Cool Gradient Border Hover Effect by Temani Afif

 Thank you for reading.

By lzz

Leave a Reply

Your email address will not be published. Required fields are marked *