skip to Main Content

I am trying to make an effect where, when I hover over an image, that part of the image where my cursor is becomes blurred.

I’ve tried multiple methods to approach this problem, such as using SVGs (Code for what I’m currently trying is provided below), as well as just a normal div with a blur backdrop-filter. However, they all lead to the same problem in which the border of the blurring element is sharp, so it ends up looking like the image provided. Instead, I want the blur effect to look like it slowly merges into the image. How can I achieve that effect? Also, I am a beginner at web development, so I would appreciate answers which explain everything in baby steps. Thanks a lotThe output of previously tried solutions

 <!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Blurred Circle Effect</title>
  <link rel="stylesheet" href="styles.css">
  <style>
    .container {
  position: relative;
  width: 100%;
  height: 100vh;
  background-image: url('https://via.placeholder.com/400');
  background-size: cover;
}

.container::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-image: inherit;
  background-size: inherit;
  filter: blur(10px);
  clip-path: circle(20% at center); /* Adjust the circle size */
  pointer-events: none; /* Prevent interaction with the pseudo-element */
}

  </style>
</head>
<body>

  <div class="container"></div>

</body>
</html>

2

Answers


  1. How about this, stack the images on top of each other, blur the one one top, that way the colors are similar.

    Depending on the size you want to display the images, you will have to tweak the blur values, sizes, etc to get the desired result.

    Keep in mind that if you do this as a way to prevent users from using the image before they buy it for example, this is not a safe way to prevent that.

    html, body {
        margin: 0;
    }
    
    img {
        position: absolute;
        height: 100%;
        width: 100%;
        object-fit: cover;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
    }
     
    #image2 {
        width: 60%;
        height: auto;
        filter: blur(40px);
    }
    <div id="container">
        <img id='image1' src="https://images.pexels.com/photos/301920/pexels-photo-301920.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1">
        <img id='image2' src="https://images.pexels.com/photos/301920/pexels-photo-301920.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1">
    </div>

    EDIT

    You said that you want to blur the image on mouse hover, so I added that, as pointed out by @DBS in the comments there might be a way to do it with masking, I know you want a smooth transition but this is as close as I got.

    const img1 = document.querySelector('#image1')
    const img = document.querySelector('#image2')
    
    
    function trackMouse(e) {
        const x = e.x - img.clientWidth / 2
        const y = e.y - img.clientHeight / 2
        img.style.top = y + "px"
        img.style.left = x + "px"
        img.style.objectPosition = `${(e.x / img1.clientWidth ) * 100}% ${(e.y / img1.clientHeight ) * 100}% `
    }
    
    window.addEventListener('mousemove', trackMouse)
    html, body {
        margin: 0;
    }
    
    #container {
        overflow: hidden;
        display: flex;
        position: relative;
        height: 500px;
        width: 700px;
    }
    
    img {
        height: 500px;
        width: 700px;
        position: absolute;
    }
     
    #image2 {
            filter: blur(15px);
            border-radius: 50%;
            opacity: 1;
            height: calc(500px / 1.5);
            width: calc(500px / 1.5); 
            object-fit: none;
            z-index: 1;
        }
    <div id="container">
        <img id='image1' src="https://images.pexels.com/photos/301920/pexels-photo-301920.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1">
    
        <img id='image2' src="https://images.pexels.com/photos/301920/pexels-photo-301920.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1">
    
    
    </div>

    Photo from pexels.com

    Login or Signup to reply.
  2. IMPORTANT NOTE: this answer is heavily based on @DBS comment and @RDU answer. I add this for completeness on the specific effect that I think you want (bc it would be too long of a comment), but this is RDUs approach with some adaptations, so please consider voting them first.

    As RDU explained, this is achieved stacking two identical images, then blurring and masking the one on top so only a small circle portion of this is shown. As DBS explained in his comment, by sizing both of them the same, it can seem as only one spot is blurred.

    To achieve the mouse move effect you want you simply need to add an event listener that modifies the mask’s center point (and remove the mask from the style sheet so it can be overriden.

    Also to centralize the events on the background, you need to use pointer-events: none on the filter overlay to prevent it catching the events because it will be on top of the other image

    Finally, to show the blurred area only when the mouse is inside the image, we use filter.style.display = "none"; and filter.style.display = "block"; to hide and show the element on mouseleave and mouseenter respectively

    Full working example below:

    const background = document.getElementById("background");
    
    background.addEventListener("mousemove", function(e) {
      const filter = document.getElementById("filter");
    
      filter.style.maskImage = `radial-gradient(circle at ${e.offsetX}px ${e.offsetY}px, #000 0%, #000 10%, transparent 30%, transparent 100%)`;
    
    });
    
    background.addEventListener("mouseenter", function(e) {
      const filter = document.getElementById("filter");
      filter.style.display = "block";
    });
    
    background.addEventListener("mouseleave", function(e) {
      const filter = document.getElementById("filter");
      filter.style.display = "none";
    });
    
    document.addEventListener('DOMContentLoaded', function() {
      filter.style.display = "none";
    });
    #filter,
    #background {
      position: absolute;
      top: 0;
      left: 0;
      width: auto;
      height: 400px;
    }
    
    #filter {
      pointer-events: none;
      filter: blur(10px);
    }
    <img id="background" src="https://placecats.com/400/400" />
    <img id="filter" src="https://placecats.com/400/400" />
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search