Show only the portion of the image where the cursor is currently hovering

Information in advance:
You can check out the current code or view the live demo (hover image functionality not included) at .

The concept:
I would like to have it so that when I hover my cursor (displayed as a black circle) over the image, only the specific part of the image that the cursor is hovering over is shown, rather than the entire image.

The issue:
Where should I begin? I've come across some CodePens that utilize Z-Index for this effect. However, my attempts have not been fruitful so far. Any example website showcasing similar functionality would be greatly helpful.


For clearer understanding, here are two additional example images.

https://i.sstatic.net/MTE7p.png

In the first image, the smaller circle / cursor (black / turquoise circle) hovers over the circular text but does not intersect the actual image yet, hence it remains hidden.


https://i.sstatic.net/AAzAV.png
In the second image, the cursor is positioned slightly above the image, revealing that specific part of the image.

Answer №1

One way to create a 'hole' in an element using CSS is by utilizing the mask property.

To achieve this effect, you can set the background of a div as the image that should be partially revealed, and then overlay it with an after pseudo-element. This pseudo-element should have the front image as its background, masked with a radial gradient positioned based on the mouse's coordinates.

Here's an example where a colored image is overlaid with a grayscale one:

window.onload = function() {
		  const div = document.querySelector('.hole');
		  let isIn = false;
		  div.addEventListener('mouseover', function() {
		    isIn = true;
		  });
		  div.addEventListener('mouseout', function() {
		    isIn = false;
		  });
		  div.addEventListener('mousemove', function() {
		    if (isIn) {
		      div.style.setProperty('--x', event.clientX + 'px');
		      div.style.setProperty('--y', event.clientY + 'px');
		    }
		  });
		}
.hole {
		  background-image: url(https://picsum.photos/id/1016/1024/768);
		  background-size: cover;
		  --x: 200px;
		  --y: 150px;
		  width: 100vw;
		  height: 100vh;
		  position: relative;
		}

		.hole::after {
		  content: '';
		  width: 100%;
		  height: 100%;
		  position: absolute;
		  top: 0;
		  left: 0;
		  background-image: url(https://picsum.photos/id/1016/1024/768?grayscale);
		  background-size: cover;
		  z-index: 1;
		  -webkit-mask-repeat: no-repeat no-repeat;
		  mask-repeat: no-repeat no-repeat;
		  -webkit-mask-image: radial-gradient(200px at var(--x) var(--y), transparent 95%, black 100%);
		  mask-image: radial-gradient(200px at var(--x) var(--y), transparent 95%, black 100%);
		}
<div class="hole"></div>

Answer №2

To display the front image under the mouse cursor, you can utilize the CSS property clip-path along with a mousemove event listener. Make sure to reset the clip-path when the mouse leaves the element.

Here's a basic example incorporating an invert filter on the overlay image using CSS. You could enhance this by implementing event delegation for managing multiple overlays and more complex interactions.


const overlay = document.querySelector('.overlay');

overlay.addEventListener('mousemove', e => {
  const { height, width } = e.currentTarget.getBoundingClientRect();
  
  const x = e.offsetX;
  const y = e.offsetY;
  
  const xPercent = Math.round((x / width) * 100);
  const yPercent = Math.round((y / height) * 100);

  e.currentTarget.style.clipPath = `circle(18% at ${xPercent}% ${yPercent}%)`;
});

overlay.addEventListener('mouseleave', e => {
  e.currentTarget.style.clipPath = null; 
});

.container {
  position: relative;
}

.container img {
  width: 200px;
  height: 200px;
  position: absolute;
  top: 0;
  left: 0;
}

.overlay {
  filter: invert(var(--value, 100%));
  clip-path: circle(0 at 49% 45%);
}
<div class='container'>
  <img src='https://source.unsplash.com/random' />    
  <img src='https://source.unsplash.com/random' class='overlay'/>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Find the current elapsed time using Wavesurfer in real time

I am currently utilizing the waveSurfer library created by katspaugh for playing audio files. In order to display 'elapsed time / total time', I have written code in the following manner: waveSurfer.on('play', function() { $scope.g ...

Looking for a straightforward way to incorporate a "Read more" and "Show Less" functionality into a Wordpress site using Javascript?

As a last resort, I am seeking a quick and simple fix. I have been experimenting with Javascript to implement a 'Read more...' & '... Read Less' feature on six different sections of a single page. The goal is to display only the fi ...

exploring the contrast of css versus javascript selectors

Could you please explain the contrast between div#name and #name? Is there a significant difference when using class or id to position an element? Thank you for your help. ...

Reusing Form HTML Elements Based on Conditions

Here's a scenario where depending on the value of the $mode variable, either 'page' or 'popup' will be returned by a conditional. This choice will determine which HTML markup is displayed. Both scenarios contain a form element wit ...

Embarking on the journey of launching an Angular application on AWS CloudFront

I have a Laravel PHP application that functions as an API accessed by an Angular single-page app. Currently, the Angular app is situated within the public folder, but I aim to separate it so I can deploy it through Amazon CloudFront. I came across this ar ...

Create a prototype class in NuxtJS Vue

What is the correct way to set a class to prototype in Vue NuxtJS? I have created a plugin Here is my nuxt.config.js file: plugins: [ { src: "~/plugins/global.js" }, ], The global.js file contains: import Vue from "vue"; import CustomStore from "dev ...

Is there a way to prevent a page from rendering until the necessary data is retrieved?

I am facing an issue where my page is attempting to render before the data is available. I have used async/await in my code, but I keep getting an error saying that the data is undefined. Interestingly, when I comment out the page elements and check the Re ...

Leveraging the power of Ajax and Javascript to handle and process conditional if/else statements

Hey there, I'm new around here so I hope I got this right. Currently, I'm diving into the Ajax for Dummies book after enjoying the PHP one years ago. However, I've hit a roadblock with my first real Ajax program. It took me ages to locate th ...

Issue with Angular 7: In a ReactiveForm, mat-select does not allow setting a default option without using ngModel

I have a Angular 7 app where I am implementing some reactive forms. The initialization of my reactive form looks like this: private initFormConfig() { return this.formBuilder.group({ modeTransfert: [''], modeChiffrement: [' ...

transfer properties to a dynamic sub element

I am currently working on a multi-step form project. I have successfully implemented the form so that each step displays the corresponding form dynamically. However, I am facing challenges in passing props to these components in order to preserve the state ...

Mobile device causing elements to resize unevenly

On my simple webpage, I have a combination of text and a table. Check out the HTML below: <body> <div id='stat'> <p class='subheading'>Stat of the Week: Average Final Standings</p> <p class='text&apo ...

Attempting to retrieve all elements... held within a parent object in JavaScript

Currently diving into JS, Jest testing, and React - quite the ride! { '1': { accountName: 'Dance Party', balance: 200, key: 1 }, '2': { accountName: 'Whiskey Party', balance: 69, key: 2 }, '3& ...

Prevent discrepancies between the outcome on the server and the client side

My website utilizes a combination of PHP and JavaScript for processing results - some server-side, some client-side. Solely relying on JavaScript can cause issues with search engine crawling, while using only PHP may not provide real-time responses accura ...

Inheritance of nested directives in Angular.js

Click here for a live example I'm trying to understand how 00B can be contained within 00A. Here is the code snippet: <div directive-one="['foo', 'bar']"> <directive-two /> </div> In this code, the directi ...

jQuery - accessing a different class within the object

Let me explain the scenario: I have a website that will delve into 4 different subjects. Initially, I have 4 divs each representing the title of those subjects. For instance, <div><p> Physics </p></div> <div><p> Chem ...

To restore the position of the chosen object in Three.js after clicking reset

I am facing an issue with resetting the position of my latest Object in three.js. Initially, my code consists of the following: function onDocumentMouseDown( event ) { event.preventDefault(); var vector = new THREE.Vector3( mouse ...

Encountering issues when attempting to create a service worker in a Vue.js application using Workbox's injectManifest feature

I'm attempting to utilize vue.js's capabilities for progressive web apps by creating a customized service worker using workbox. However, every time I try to build the app, I encounter the following error: AssertionError [ERR_ASSERTION]: swSrc mus ...

Struggling with defining the default value for a JavaScript array

One interesting feature on my website is a changing h1 heading that updates when the user clicks a button. However, I encountered an issue where, upon initial page load, the h1 appears empty and only populates with text after the button is clicked. I am ...

Is there a way to deactivate specific options within the "Select" component on Material-UI, similar to how it is done in the "Autocomplete" feature?

Is it possible to restrict certain options in the Select component similar to how it is done in the Autocomplete component? PS: The options are present in an array. <FormControl variant="outlined"> <InputLabel>States</Inp ...

An unexpected problem with text redirection that should not be happening

I am facing an issue with my HTML text field and post button on my website. Whenever I click the post button to make a post, it redirects to a separate PHP file called post.php which handles PHP and MySQL code for posting. However, I want to avoid this red ...