0

I've come across an issue of trying to fade the edges of the background image of a div so that it looks like it's blending with the background image of the full site (so the background image applied to the body).

body{
    background-image: url('some url here') !important;
    background-repeat: no-repeat;
    background-attachment: fixed;
    background-position: 100%;
    background-size: 1150px;
  }
  #blendElement{
    background: url('some other url here');
    background-attachment: fixed;
    background-repeat: no-repeat;
    background-size: 100%;
  }
<head>
</head>

<body>
 <div>
   <div id="blendElement"> This should have edges blending to the main (body's) background image behind it.
   </div>
 </div>
</body>

If you've ever used PowerPoint and tried an image effect called soft edges, that's exactly what I'm trying to do here. The only related "answer" I was able to find was for solid body background colors by using box-shadow with inset:

box-shadow: 25px 25px 50px 0 (color matching background color) inset;

But since the body has a background image and not a solid color, there's no way to make it look like it's blending in. And obviously using a transparent color in box shadow just shows the div background image as it normally would look.

Could someone help me out with this? (And I can't edit the div image to give it transparent fading edges, so it'll have to be directly done with CSS or JS)

shaedrich
  • 5,457
  • 3
  • 26
  • 42
Nirabhra
  • 71
  • 1
  • 12

3 Answers3

5

You can use the mask-* CSS properties to achieve the effect.

The following example produce a 10px long fading edge.

.body {
  display: grid;
  width: 200px;
  height: 200px;
  /* replace with the image you like here */
  background-image: repeating-linear-gradient(-45deg,
      yellow,
      yellow 20px,
      black 20px,
      black 40px);
}

.content {
  margin: 25px;
  /* replace with the image you like here */
  background-image: linear-gradient(to top, blue 0%, blue 100%);
  
  /* for webkit-based browsers */
  -webkit-mask-image:
    linear-gradient(to top, black 0%, black 100%),
    linear-gradient(to top, transparent 0%, black 100%),
    linear-gradient(to right, transparent 0%, black 100%),
    linear-gradient(to bottom, transparent 0%, black 100%),
    linear-gradient(to left, transparent 0%, black 100%);
  -webkit-mask-position:
    center,
    top,
    right,
    bottom,
    left;
  -webkit-mask-size:
    100% 100%,
    100% 10px,
    10px 100%,
    100% 10px,
    10px 100%;
  -webkit-mask-repeat:
    no-repeat,
    no-repeat,
    no-repeat,
    no-repeat,
    no-repeat;
   -webkit-mask-composite:
    source-out,
    source-over,
    source-over,
    source-over;
    
   /* for browsers which have implemented the official spec */
  mask-image:
    linear-gradient(to top, black 0%, black 100%),
    linear-gradient(to top, transparent 0%, black 100%),
    linear-gradient(to right, transparent 0%, black 100%),
    linear-gradient(to bottom, transparent 0%, black 100%),
    linear-gradient(to left, transparent 0%, black 100%);
  mask-position:
    center,
    top,
    right,
    bottom,
    left;
  mask-size:
    100% 100%,
    100% 10px,
    10px 100%,
    100% 10px,
    10px 100%;
  mask-repeat:
    no-repeat,
    no-repeat,
    no-repeat,
    no-repeat,
    no-repeat;
  mask-composite:
    subtract,
    add,
    add,
    add;
}
<div class="body">
  <div class="content"></div>
</div>

How does it work and how to customize?

It works by compositing 5 sub-images together and use the composited image as the mask for the element.

Let's separate the images: (here I am using background-* property to simulate the effect of the composited images)

.body {
  display: grid;
  width: 200px;
  height: 200px;
  grid-template: 200px / repeat(2, 200px 20px) 200px;
}

span {
  place-self: center;
}

.content1 {
  margin: 25px;
  background-image:
    linear-gradient(to top, black 0%, black 100%);
  background-position:
    center;
  background-size:
    100% 100%;
  background-repeat:
    no-repeat;
}

.content2 {
  margin: 25px;
  background-image:
    linear-gradient(to top, transparent 0%, black 100%),
    linear-gradient(to right, transparent 0%, black 100%),
    linear-gradient(to bottom, transparent 0%, black 100%),
    linear-gradient(to left, transparent 0%, black 100%);
  background-position:
    top,
    right,
    bottom,
    left;
  background-size:
    100% 10px,
    10px 100%,
    100% 10px,
    10px 100%;
  background-repeat:
    no-repeat,
    no-repeat,
    no-repeat,
    no-repeat;
  background-blend-mode:
    normal,
    normal,
    normal;
}

.content3 {
  margin: 25px;
  background-color: black;
  -webkit-mask-image:
    linear-gradient(to top, black 0%, black 100%),
    linear-gradient(to top, transparent 0%, black 100%),
    linear-gradient(to right, transparent 0%, black 100%),
    linear-gradient(to bottom, transparent 0%, black 100%),
    linear-gradient(to left, transparent 0%, black 100%);
  -webkit-mask-position:
    center,
    top,
    right,
    bottom,
    left;
  -webkit-mask-size:
    100% 100%,
    100% 10px,
    10px 100%,
    100% 10px,
    10px 100%;
  -webkit-mask-repeat:
    no-repeat,
    no-repeat,
    no-repeat,
    no-repeat,
    no-repeat;
   -webkit-mask-composite:
    source-out,
    source-over,
    source-over,
    source-over;
  mask-image:
    linear-gradient(to top, black 0%, black 100%),
    linear-gradient(to top, transparent 0%, black 100%),
    linear-gradient(to right, transparent 0%, black 100%),
    linear-gradient(to bottom, transparent 0%, black 100%),
    linear-gradient(to left, transparent 0%, black 100%);
  mask-position:
    center,
    top,
    right,
    bottom,
    left;
  mask-size:
    100% 100%,
    100% 10px,
    10px 100%,
    100% 10px,
    10px 100%;
  mask-repeat:
    no-repeat,
    no-repeat,
    no-repeat,
    no-repeat,
    no-repeat;
  mask-composite:
    subtract,
    add,
    add,
    add;
}
<div class="body">
  <div class="content1"></div>
  <span>-</span>
  <div class="content2"></div>
  <span>=</span>
  <div class="content3"></div>
</div>

The first image fills the entire box black.

The second image is a result of compositing the remaining 4 sub-images using the add operation. This image defines how the edge should fade. Note that the image is inverted, i.e. the outer edge is solid black while the inner edge is transparent.

The third image is created by subtracting the second image from the first image. The image is used as the mask.

When applying the mask, a black pixel means not fading the element pixel, a 50% transparency pixel means fading the element pixel by 50% and a 100% transparency pixel means fading the element pixel by 100% (not visible).

You can customize the effect by adjusting the the properties of the sub-images:

  • To control the length of the fading, adjust the sub-images' sizes via mask-size property
  • To have nonlinear fading, add more color stops to the linear-gradient() declaration
  • To not have complete fading on the edge, use a less transparent color for the color stops, e.g. rgba(0, 0, 0, 0.5)
Alvin Leung
  • 668
  • 1
  • 5
  • 10
  • Thanks a lot, can I also ask you how to modify the values such as the edge area that's blending, intensity of the blur, etc? (since I can't see any way to do that, it looks like this is the maximum blend or something, not sure...) – Nirabhra Jun 16 '21 at 03:31
  • 1
    I have updated my answer to show how it works and how to customize it. – Alvin Leung Jun 16 '21 at 04:56
0

You can use the background as gradient where the edges are rgba(0,0,0,0). This way it will smoothly blend with background. But this will not work for images. For images You will have to a div of background color and rgba(0,0,0,0) in gradient with color facing outward.

  • I'm not sure what exactly you mean by that, could you possibly give the example for the image through some code? – Nirabhra Jun 16 '21 at 03:09
0

Since you have a background image on the body of your website, then the easiest way to achieve your goal is to edit the div image itself using Photoshop or any Image Manipulation Tool and save it as PNG format to preserve the transparency of the fading effect.

mlvnbrj
  • 551
  • 4
  • 5