Search code examples
cssbackground-blend-mode

CSS background blend mode black mask


Using css background-blend-mode I'm trying setup a mask where the first background image white parts apply a black color mask on the last one.

Here is a code sample showing where I'm stuck: https://codepen.io/BackNight/pen/YzQgyjo

.container {
  background-color: black;
  width: 200px;
  height: 200px;
  background-image: url('data:image/svg+xml,%3Csvg width="100" height="100" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg"%3E%3Cg fill="%23fff" fill-opacity="1" fill-rule="evenodd"%3E%3Cpath d="M0 40L40 0H20L0 20M40 40V20L20 40"/%3E%3C/g%3E%3C/svg%3E'), radial-gradient(closest-side, #1499ff calc(100% - 1px), transparent);
  background-size: auto, 75px 75px;
  background-repeat: no-repeat;
  background-position: right bottom, right 40px bottom;
  background-blend-mode: difference;
}

I can only get an orange color with a "difference" mode and I just need it to be black instead:

enter image description here

To give you an example of the final result I want:

enter image description here


Solution

  • What you can do is instead of relying on blending mode, which gives you very little control over the color, is to actually overlay your .container with a pseudo element that has the SVG in an alternative color palette that you want (in this case, a background of #1499ff and a fill of #000000.

    Then, you can use clip-path to hide the rest of the overlay, and use CSS properties to control the position of the overlay (if needed). See example below:

    // Optional JS to demonstrate an interactable mask
    document.querySelector('.container').addEventListener('mousemove', (e) => {
      e.target.style.setProperty('--circleX', `${e.clientX}px`);
      e.target.style.setProperty('--circleY', `${e.clientY}px`);
    });
    .container {
      background-color: black;
      width: 200px;
      height: 200px;
      background-image: url('data:image/svg+xml,%3Csvg width="100" height="100" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg"%3E%3Cg fill="%23fff" fill-opacity="1" fill-rule="evenodd"%3E%3Cpath d="M0 40L40 0H20L0 20M40 40V20L20 40"/%3E%3C/g%3E%3C/svg%3E');
      position: relative;
    }
    
    .container,
    .container::after {
      background-size: auto;
      background-repeat: no-repeat;
      background-position: right bottom;
    }
    
    .container::after {
      position: absolute;
      cursor: pointer;
      content: '';
      inset: 0;
      background-color: #1499ff;
      background-image: url('data:image/svg+xml,%3Csvg width="100" height="100" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg"%3E%3Cg fill="%23000" fill-opacity="1" fill-rule="evenodd"%3E%3Cpath d="M0 40L40 0H20L0 20M40 40V20L20 40"/%3E%3C/g%3E%3C/svg%3E');
      clip-path: circle(50px at var(--circleX, 50%) var(--circleY, 50%));
    }
    <div class="container">
    </div>