Search code examples
javascriptcssbordergradient

How can I make a dynamic border with gradient that changes based on mouse position


I'm wondering if the background-image property can be edited in real time via JavaScript, what I'm trying to do has a similar concept to the following question: How to change the color of the background based on mouse position (specific colors)

But instead of editing the background, I'm editing the border, giving it 100% opacity only in the corner where the cursor is.

The CSS method I tried to get the gradient rounded border is as follows: https://gist.github.com/stereokai/36dc0095b9d24ce93b045e2ddc60d7a0

On JavaScript, the method I did was as follows (using jQuery 3.7.1 to detect the mouse position within the element):

if(x <= middle_x && y <= middle_y)
{
    content.style.backgroundImage = "linear-gradient(#303030, #303030), radial-gradient(circle at top left, #8B686B, #00000000, #00000000);";
}
else if(x >= middle_x && y <= middle_y)
{
    content.style.backgroundImage = "linear-gradient(#303030, #303030), radial-gradient(circle at top right, #8B686B, #00000000, #00000000);";
}
else if(x <= middle_x && y >= middle_y)
{
    content.style.backgroundImage = "linear-gradient(#303030, #303030), radial-gradient(circle at bottom left, #8B686B, #00000000, #00000000);";
}
else if(x >= middle_x && y >= middle_y)
{
    content.style.backgroundImage = "linear-gradient(#303030, #303030), radial-gradient(circle at bottom right, #8B686B, #00000000, #00000000);";
}

(content is the div element that contains the border).

However, after testing, it seems that the algorithm had no effect, as the element's border remained static, even though the algorithm detected the position and corner corresponding to the cursor position.

So after this, I thought that background-image could not be edited in real-time.

Should I try another CSS method? Is this last thought wrong?


Solution

  • You don't need JavaScript for that. Place div elements inside the "box" and style the box when one of the child div elements is hovered. To make the child div elements fill up the box you can use CSS flex (or CSS grid if there should be more div elements placed in a grid).

    Using CSS :has() you can make the CSS selector target the box when one of its child elements is hovered.

    div.box {
      width: 300px;
      height: 80px;
      border: double 4px transparent;
      border-radius: 80px;
      background-image: linear-gradient(white, white), radial-gradient(circle at top left, red, blue);
      background-origin: border-box;
      background-clip: padding-box, border-box;
      display: flex;
      flex-direction: row;
    }
    
    div.box div {
      flex-grow: 1;
    }
    
    div.box:has(div:nth-child(1):hover) {
      background-image: linear-gradient(white, white), radial-gradient(circle at top left, orange, red, blue);
    }
    
    div.box:has(div:nth-child(2):hover) {
      background-image: linear-gradient(white, white), radial-gradient(circle at top left, green, orange, red, blue);
    }
    
    div.box:has(div:nth-child(3):hover) {
      background-image: linear-gradient(white, white), radial-gradient(circle at top left, silver, green, orange, red, blue);
    }
    
    div.box:has(div:nth-child(4):hover) {
      background-image: linear-gradient(white, white), radial-gradient(circle at top left, purple, silver, green, orange);
    }
    <div class="box">
      <div></div>
      <div></div>
      <div></div>
      <div></div>
    </div>