Invert text color on mouse hover
Here is an idea using clip-path
. The trick is to duplicate the text to have two layers above each other with different text color then I reveal the top one using the clip-path
that I adjust with the move of the mouse.
var h =document.querySelector('h1');
var p= h.getBoundingClientRect();
var c= document.querySelector('.cursor');
document.body.onmousemove = function(e) {
/*Adjust the cursor position*/
c.style.left=e.clientX+'px';
c.style.top=e.clientY+'px';
/*Adjust the clip-path*/
h.style.setProperty('--x',(e.clientX-p.top)+'px');
h.style.setProperty('--y',(e.clientY-p.left)+'px');
}
body {
cursor:none;
}
h1 {
color: #000;
display:inline-block;
margin:50px;
text-align: center;
position:relative;
}
h1:before {
position:absolute;
content:attr(data-text);
color:#fff;
background:#000;
clip-path: circle(20px at var(--x,-100%) var(--y,-100%));
}
.cursor {
position:fixed;
width:40px;
height:40px;
background:#000;
border-radius:50%;
top:0;
left:0;
transform:translate(-50%,-50%);
z-index:-2;
}
<h1 data-text="WORK">WORK</h1>
<span class="cursor"></span>
Here is Another idea using radial-gradient
and without duplicating the text that can work with multiple elements at the same time:
document.body.onmousemove = function(e) {
document.documentElement.style.setProperty('--x',(e.clientX)+'px');
document.documentElement.style.setProperty('--y',(e.clientY)+'px');
}
body {
cursor:none;
}
.mask {
background:
radial-gradient(circle 20px
at var(--x,0) var(--y,0),
#fff 99%,black 100%)
fixed;
background-clip: text;
-webkit-background-clip: text;
color:transparent;
-webkit-text-fill-color: transparent;
}
html::before {
content:"";
position:fixed;
width:40px;
height:40px;
background:#000;
border-radius:50%;
top:var(--y,0);
left:var(--x,0);
transform:translate(-50%,-50%);
z-index:-2;
}
<h1 class="mask">WORK</h1>
<p class="mask">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis risus sapien. Maecenas dui orci, blandit et commodo eget, egestas quis odio. Donec eu tortor turpis. Aliquam convallis et nisi ut varius. Proin sapien erat, auctor in efficitur vel, efficitur sit amet justo. In pretium iaculis tempus. Vivamus congue</p>
<p class="mask">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis risus sapien. Maecenas dui orci, blandit et commodo eget, egestas quis odio. Donec eu tortor turpis. Aliquam convallis et nisi ut varius. Proin sapien erat, auctor in efficitur vel, efficitur sit amet justo. In pretium iaculis tempus. Vivamus congue</p>
Related question with similar ideas: Stacking circles produces a black bar on border radius
Made a solution using mix-blend-mode: difference;
for the .cursor
.
The advantage is - we don't need to add any classes or javascript to all elements that we are hovering with our circle-mouse over.
The disadvantage is - this solution less stable due to mix-blend-mode
is a bit raw technology. It requires to set height
in body
and html
, and strict background-color
for body
.
The part with .cursor
CSS and JavaScript - I partly borrowed form the solution of @Temani Afif. Thank you and hope you don't mind, because it's pointless to try to write it better. But i added +window.scrollX
and +window.scrollY
for correct .cursor
work while scrolling.
More about mix-blend-mode
you cay read here https://caniuse.com/#search=mix-blend-mode and https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
document.body.onmousemove = function(e) {
document.documentElement.style.setProperty('--x', (e.clientX+window.scrollX) + 'px');
document.documentElement.style.setProperty('--y', (e.clientY+window.scrollY) + 'px');
}
html {
height: 100%; /* requires for stable body height */
}
body {
min-height: 100%; /* requires for 'mix-blend-mode' */
cursor: none;
color: #000;
background-color: #fff; /* requires for 'mix-blend-mode' */
}
.cursor {
position: absolute;
width: 40px;
height: 40px;
background: #fff;
border-radius: 50%;
top: var(--y, 0);
left: var(--x, 0);
transform: translate(-50%, -50%);
z-index: 2;
mix-blend-mode: difference;
}
<h1>WORK</h1>
<span class="cursor"></span>