I came across the question: how do I make part of a div transparent and other parts blurred? The final result is this

Further, can also achieve arbitrary shape hollowing effect

Where the mouse passes is clearly visible, the rest is blurry.

May not start at the beginning, don’t worry, you can start from a simple, similar effect, step by step try, have a look.

First, the effect of ordinary translucent

For example, usually encountered in the development of more may be a translucent effect, a bit similar to the searchlight (the place outside the mouse is a translucent mask, it will look a little darker). As follows:

Let’s start with this effect. Suppose we have a layout like this:

<div class="wrap" id="img">
    <img class="prew" src="https://tva1.sinaimg.cn/large/008i3skNgy1gubr2sbyqdj60xa0m6tey02.jpg">
</div>
Copy the code

So how do you draw a hollow circle? Here’s a way to do it

It’s very simple. All you need is a big enough projection, and here’s how it works

This can be drawn with the pseudo-element ::before for a more concise structure. In code

.wrap::before{
  content:' ';
  position: absolute;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%); /* Default center */
  box-shadow: 0 0 0 999vw rgba(0.0.0.5); /* Enough projection */
}
Copy the code

You can get something like this

2. Pass the mouse position with CSS variables

As a rule of thumb, you might change the style attribute of an element directly in JS, something like this

img.addEventListener('mousemove'.(ev) = > {
    img.style.left = '... ';
    img.style.top = '... ';
})
Copy the code

However, such interaction and business logic are mixed together, which is not conducive to later maintenance. In fact, we only need the coordinates of the mouse, CSS can also completely follow the effect.

Use CSS variables here, and you’ll be fine! Assuming the mouse coordinates are [–x,–y](range [0, 1]), then the coordinates of the mask can be calculated using CALC

.wrap::before{
  left: calc(var(--x) * 100%);
  top: calc(var(--y) * 100%);
}
Copy the code

Then the mouse coordinates can be obtained using JS to calculate, also easier, as follows

img.addEventListener('mousemove'.(ev) = > {
    img.style.setProperty('--x', ev.offsetX / ev.target.offsetWidth);
    img.style.setProperty('--y', ev.offsetY / ev.target.offsetHeight);
})
Copy the code

In this way, the hollow out effect of translucent effect is completed

Context backdrop backdrop backdrop backdrop shadow (codepen.io)

Third, gradient can also achieve translucent effect

In addition to the shadow extension method described above, CSS radial gradient can also achieve this effect

Draw a gradient from transparent to translucent as follows

.wrap::before{
    content: ' ';
    position: absolute;
    width: 100%;
    height: 100%;
    left: 0;
    top: 0;
    background: radial-gradient( circle at center, transparent 50px.rgba(0.0.0.5) 51px);
}
Copy the code

You can get something like this

Then, map the mouse coordinates to it. This is where you can see the benefits of CSS variables. You don’t need to change the JS, just change the position of the gradient center in the CSS

.wrap::before{
  background: radial-gradient( circle at calc(var(--x) * 100% )  calc(var(--y) * 100% ), transparent 50px.rgba(0.0.0.5) 51px);
}
Copy the code

Fourth, the effect of background blur attempt

The CSS has a property specifically for the background (the area behind the element) : backdrop-filter. Use the same way as filter!

backdrop-filter: blur(10px);
Copy the code

Here is a schematic effect in MDN

Backdrop – filter area behind the content of the current element is fuzzy, want to see the effect, need the element itself translucent or fully transparent; A filter obfuscates the current element itself. If you are interested, you can check out this article: CSS Backdrop backdrop Filter and Apple iOS Ground-glass effect.

Note that this blurring has nothing to do with the semi-transparency of the background, even if the elements themselves are transparent. For example, here is the effect after removing the background, the whole block is blurred

What if we applied the above example directly?

1. Shadow implementation

Add backdrop backdrop filter in the first example above

.wrap::before{
  content:' ';
  position: absolute;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%); /* Default center */
  box-shadow: 0 0 0 999vw rgba(0.0.0.5); /* Enough projection */
  backdrop-filter: blur(5px)}Copy the code

The result is as follows

You can see that the circular area is blurred, which is exactly the opposite of what you want. In fact, it is easy to understand, only the circular area is the real structure, the outside is all shadow, so the final scope of action is only the circular part

2. Gradual implementation

Now in the second example add backdrop bath-filter

.wrap::before{
    content: ' ';
    position: absolute;
    width: 100%;
    height: 100%;
    left: 0;
    top: 0;
    background: radial-gradient( circle at calc(var(--x) * 100% )  calc(var(--y) * 100% ), transparent 50px.rgba(0.0.0.5) 51px);
  	backdrop-filter: blur(5px)}Copy the code

Results the following

It’s all blurred out, except outside the circle. Due to the size of ::before occupying the entire container, the entire back is blurred, and the rounded exterior is dark due to the effect of translucent gradients.

In short, it still cannot meet our needs, and new solutions need to be sought.

5. CSS MASK hollow out

Instead of blurring the circular area, it’s more like hollowing out the area. Just like a whole piece of frosted glass before, and then through the CSS MASK made a round hole, so that through the round hole to see the back must be clear.

You can modify the second example slightly by drawing a transparent circle with a radial gradient, and the rest of the circle is a solid color mask layer, as shown below

In code

.wrap::before{
    content: ' ';
    position: absolute;
    width: 100%;
    height: 100%;
    left: 0;
    top: 0;
    -webkit-mask: radial-gradient( circle at calc(var(--x, .5) * 100% )  calc(var(--y, .5) * 100% ), transparent 50px.# 000 51px);
  	background: rgba(0.0.0.3);
  	backdrop-filter: blur(5px)}Copy the code

This has achieved the effect of the beginning of the article

Setup setup setup setup setup setup setup setup setup setup setup setup setup setup setup setup setup setup setup setup setup setup setup setup setup setup setup setup setup setup setup setup setup setup setup setup setup setup setup

6, CSS MASK COMPOSITE to achieve a richer hollowing effect

In addition to using radial gradient to draw the MASK layer, you can also do this by using CSS MASK COMPOSITE. Standard key values are as follows (Supported by Firefox) :

/* Keyword values */
mask-composite: add; /* Overlay (default) */
mask-composite: subtract; /* subtract, exclude the upper region */
mask-composite: intersect; /* intersects, only shows the overlap */
mask-composite: exclude; / *, display only * / don't overlap
Copy the code

What does mask composition mean? It’s analogous to shape composition in Photoshop, almost one-to-one correspondence

– Webkit-mask-composite = webkit-mask-composite = webkit-mask-composite

-webkit-mask-composite: clear; /* Clear, do not show any masks */
-webkit-mask-composite: copy; /* Display only the upper mask, not the lower mask */
-webkit-mask-composite: source-over; 
-webkit-mask-composite: source-in; /* display only overlaps */
-webkit-mask-composite: source-out; /* Only the top mask is displayed. */ is not displayed when overlapped
-webkit-mask-composite: source-atop;
-webkit-mask-composite: destination-over;
-webkit-mask-composite: destination-in; /* display only overlaps */
-webkit-mask-composite: destination-out;/* Display only the lower mask, overlap areas do not display */
-webkit-mask-composite: destination-atop;
-webkit-mask-composite: xor; /* display only overlapped areas */
Copy the code

Do you look confused? Here made a corresponding effect diagram, if not too skilled, when using know that there is such a function, and then on the line

Back here, you can draw a full background and a circular background, and then punch a hole through mask-composite: exclude

.wrap::before{
    content: ' ';
    position: absolute;
    width: 100%;
    height: 100%;
    left: 0;
    top: 0;
    -webkit-mask: url("data:image/svg+xml,%3Csvg width='50' height='50' viewBox='0 0 50 50' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='25' cy='25' r='25' fill='%23C4C4C4'/%3E%3C/svg%3E"), linear-gradient(red, red);
  	-webkit-mask-size: 50px.100%;
  	-webkit-mask-repeat: no-repeat;
  	-webkit-mask-position: calc(var(--x, .5) * 100% + var(--x, .5) * 100px - 50px )  calc(var(--y, .5) * 100% + var(--y, .5) * 100px - 50px ), 0;
  	-webkit-mask-composite: xor;   /* Display only non-overlapping areas, chorem, Safari support */
  	mask-composite: exclude; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  	background: rgba(0.0.0.3);
  	backdrop-filter: blur(5px)}Copy the code

Pay attention to the calculation in -webkit-mask-position, which can also achieve this effect

Sindba-mask-composite (codepen.io) bad-mask-composite (codepen.io)

As you may have noticed, the circles in the above example were drawn in SVG with mask composition, which seems a bit more verbose. In fact, it’s a more versatile solution that opens up endless possibilities. For example, I need a star ⭐️ hollow out effect, very simple, first through a drawing software to draw a

Then escape this SVG code. Here I recommend using Zhang Xinxu’s SVG online compression and merging tool

I’ll just substitute that for the example I just did

.wrap::before{
    content: ' ';
    position: absolute;
    width: 100%;
    height: 100%;
    left: 0;
    top: 0;
    -webkit-mask: url("data:image/svg+xml,%3Csvg width='96' height='91' viewBox='0 0 96 91' fill='none' XMLNS = 'http://www.w3.org/2000/svg' % 3 e % 3 cpath d = '34.55 h36.327 M48 0 l11. 226 l - 48 L77.39 90.45 69.098 21.352 29.39 18.61 90.451 29.851 29.9.447 34.5h36.327l48 0z' Fill ='%23C4C4C4'/%3E%3C/ SVG %3E"), linear-gradient(red, red);
  	-webkit-mask-size: 50px.100%;
  	-webkit-mask-repeat: no-repeat;
  	-webkit-mask-position: calc(var(--x, .5) * 100% + var(--x, .5) * 100px - 50px )  calc(var(--y, .5) * 100% + var(--y, .5) * 100px - 50px ), 0;
  	-webkit-mask-composite: xor;   /* Display only non-overlapping areas, chorem, Safari support */
  	mask-composite: exclude; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  	background: rgba(0.0.0.3);
  	backdrop-filter: blur(5px)}Copy the code

The stars hollow out effect is as follows

Setup setup backdrop backdrop backdrop backdrop backdrop backdrop (codepen.io)

Another example is a heart-shaped ❤, which works like this

Backdrop backdrop backdrop backdrop backdrop (codepen.io)

Only think, can not do

Vii. Summary and explanation

The above has realized a hollow out effect of mouse following, from simple to complex, from single to universal. Although it uses a little JS, it is only the role of “tool man”, and the interactive logic is all completed by CSS. Here is a summary:

  1. A large enough shadow is a trick to achieve a circular hollowing effect
  2. CSS gradient can also easily draw a circular hollow background
  3. CSS variables make it easy to use mouse position to achieve the desired effect
  4. The sindset-filter can be imagined as the function of frosted glass
  5. The CSS Mask can be used to drill holes in frosted glass to achieve hollow effect
  6. With the mask composition feature and SVG, you can hollow out any shape

CSS MASK is still very powerful, it is necessary to learn more. Finally, if you think it’s good and helpful, please like, bookmark and retweet ❤❤❤