3

Hi this is a bit of an odd question, I've seen similar effects to whats I'm going for but not exactly the same not sure if what I want to do is possible. I want to have two divs stacked with the contents of the div below revealed only in a specific area (around the cursor), is there a way to make only part of a div transparent? Or is there any other way to achieve this effect?

enter image description here

3
  • do they have same parent div? Commented Dec 2, 2021 at 9:41
  • 1
    I don't believe it is achievable as in your drawing. If it is possible at all, I rather imagine doing the opposite: putting the green div on top, and then show only what's around the cursor and masking the rest. But for this kind of advanced effects (masking) you'll probably need a <canvas> in some way. This being said, this question is off-topic for Stackoverflow :) Commented Dec 2, 2021 at 9:42
  • You could also have the bottom div to be copied over the top div. So three layers. The reveal layer, the "top" layer and the bottom. You then reveal the real top layer but it looks like it is at the bottom. The flashlight effect for revealing content I'm not familiar with, but probably not a CSS only effect if I had to guess. Commented Dec 2, 2021 at 9:47

1 Answer 1

9

Instead of having the element you want to show in the background you can put it in front and only show part of it via a clip-path;

For the coordinates I use CSS variables though you could also overwrite the style directly.

// Get element from the DOM const container = document.querySelector('.container'); // Apply event listener container.addEventListener('mousemove', updateCoords, false); function updateCoords(event) { // Get X and Y coordinates const { offsetX, offsetY } = event; // Update coordinates container.style.setProperty('--x', offsetX + 'px'); container.style.setProperty('--y', offsetY + 'px'); }
.container { border: 1px solid #000; width: 300px; height: 300px; } /* Show child when hovering the container */ .container:hover .child { display: block; } .child { clip-path: ellipse(30px 30px at var(--x) var(--y)); display: none; }
<div class="container"> <img class="child" src="//picsum.photos/300" width="300" height="300" /> </div>

You can use requestAnimationFrame to make the circle move more smoothly

// Get element from the DOM const container = document.querySelector('.container'); // Apply event listener container.addEventListener('mousemove', updateCoords, false); function updateCoords(event) { // Get X and Y coordinates const { offsetX, offsetY } = event; // Update coordinates requestAnimationFrame(() => { container.style.setProperty('--x', offsetX + 'px'); container.style.setProperty('--y', offsetY + 'px'); }); }
.container { border: 1px solid #000; width: 300px; height: 300px; } /* Show child when hovering the container */ .container:hover .child { display: block; } .child { clip-path: ellipse(30px 30px at var(--x) var(--y)); display: none; }
<div class="container"> <img class="child" src="//picsum.photos/300" width="300" height="300" /> </div>

Example with text

// Get element from the DOM const container = document.querySelector('.container'); // Apply event listener container.addEventListener('mousemove', updateCoords, false); function updateCoords(event) { // Get X and Y coordinates const {offsetX, offsetY} = event; // Update coordinates requestAnimationFrame(() => { container.style.setProperty('--x', offsetX + 'px'); container.style.setProperty('--y', offsetY + 'px'); }); }
.container { min-height: 100vh; min-width: 100vh; overflow: hidden; } .container:hover .code { display: flex; } .display, .code { position: absolute; display: flex; align-items: center; justify-content: center; width: 100vw; height: 100vh; background-color: rgb(49, 49, 49); color: rgb(240, 191, 29); pointer-events: none; } .code { clip-path: ellipse(100px 100px at var(--x) var(--y)); display: none; background-color: rgb(3, 3, 3); color: rgb(101, 253, 101); }
<div class="container"> <div class="display"> <h1>Header</h1> </div> <div class="code"> <h3>&lt;h1&gt;Header&lt;/h1&gt;</h3> </div> </div>

Sign up to request clarification or add additional context in comments.

3 Comments

Hi thanks this is almost exactly what I was after, I'm using this effect to show text not images and it works perfectly until the mouse goes over the text, it sends the circle to the top of the screen, I'm sorta stumped on why this may be happening any ideas?
@jacquesrockell yes this is because the event bubbles. Meaning once you hover the text it will read coordinates from the heading not the container. One easy solution is to add pointer-events: none; to your content. See update snippet.
The effect is working great, ty

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.