Search code examples
javascripthtmlcssmix-blend-mode

CSS mix-blend-mode + JS


So I have a custom js cursor ( which follows the mouse cursor with a delay ) which has a background color of #000 and mix-blend-mode set to difference. My body background color and text is set to #fff. Now, I have a p tag with the text "HELLO" which I want to be visible just the words "H" and "O", so I created a span which color's is set to #000. When I hover over the P tag, because of the mix-blend-mode, I can see the "ELL" words as I wanted, but the words "H" and "O" get " invisible ". How can I make them be visible when the cursor gets over it? ( just the part of each word which is being hovered by the cursor, not the entire word, IF the cursor doesn't cover the entire word )

Is there any solution? I tryed to change the color of the "H" and "O" on mouseenter/mouseleave but it doesn't work as expected.

const cursor = document.querySelector('.cursor')
const wuc = document.querySelectorAll('.wuc')
document.addEventListener('mousemove', e => {
    cursor.setAttribute('style', 'top: ' + e.clientY+'px; left: '+e.clientX+'px;')
})


wuc.forEach((wuc) => {
    wuc.addEventListener('mouseenter', () => {
        wuc.style.color = '#fff'
    })
    wuc.addEventListener('mouseleave', () => {
        wuc.style.color = '#000'
    })
})
body {
    background-color: #fff;
    color: #fff;
}

.cursor {
    width: 5vw;
    height: 5vw;
    transform: translate(-2.5vw, -2.5vw);
    position: fixed;
    transition-duration: 200ms;
    transition-timing-function: ease-out;
    background-color: #000;
    border-radius: 50%;
    mix-blend-mode: difference;
}

p {
    margin-left: 30vw;
    margin-top: 40vh;
}
.wuc {
    color: #000;
}
 <div class="cursor"></div>
    <p class="container">
       <span class="wuc">H</span>ELL<span class="wuc">O</span>
    </p>


Solution

  • I would color the text using a radial-gradient that follow the same position of your custom cursor

    const cursor = document.querySelector('.cursor')
    document.addEventListener('mousemove', e => {
      cursor.setAttribute('style', 'top: ' + e.clientY + 'px; left: ' + e.clientX + 'px;');
      document.body.setAttribute('style', '--x: ' + e.clientX + 'px;--y:' + e.clientY + 'px;');
    })
    body {
      background-color: #fff;
      color: #fff;
    }
    
    .cursor {
      width: 5vw;
      height: 5vw;
      transform: translate(-2.5vw, -2.5vw);
      position: fixed;
      transition-duration: 200ms;
      transition-timing-function: ease-out;
      background-color: #000;
      border-radius: 50%;
      mix-blend-mode: difference;
    }
    
    p {
      margin-left: 30vw;
      margin-top: 40vh;
    }
    
    .wuc {
      background: 
        radial-gradient(farthest-side, #fff 99.5%, #000 100%) calc(var(--x,0px) - 2.5vw) calc(var(--y,0px) - 2.5vw)/5vw 5vw fixed no-repeat,
        #000;
      -webkit-background-clip:text;
      background-clip:text;
      -webkit-text-fill-color: transparent;
      color:transparent;
      
    }
    <div class="cursor"></div>
    <p class="container">
      <span class="wuc">H</span>ELL<span class="wuc">O</span>
    </p>