DEV Community

Cover image for Windows 10 grid hover effect using HTML, CSS, and vanilla JS

Windows 10 grid hover effect using HTML, CSS, and vanilla JS

Jash Gopani on April 24, 2021

Table of Contents Introduction Observations Getting Started The Crux Finding nearby elements to cursor How to Calculate nearby point...
Collapse
 
webreflection profile image
Andrea Giammarchi

interesting article, thanks, and just few quick notes:

nearBy.splice(0, nearBy.length)
could just be
nearBy.splice(0)

element.className
could rather be
element.classList.contains('win-btn')

last, but not least, it's not clear why some event is directly attached, and some is added via proper method ... anyway, thanks for the write up and the code 👋

Collapse
 
jashgopani profile image
Jash Gopani

Thanks, @webreflection for the splice suggestion. I will use that 😁.
I have almost completed the 3rd article of this series and I have already used the classList property there since I wanted to show both the approaches to the readers.

Coming to your query about direct event vs methods, the DOM element does not have a property called onmousemove . That's why I had to use addEventListener method for that particular event.

For reference, I have done console.dir() of a DOM element to check the same

console.dir

I Hope this helps 😉

Collapse
 
webreflection profile image
Andrea Giammarchi • Edited

'onmousemove' in HTMLElement.prototype in true, and every event should be added via addEventListener to avoid conflicts with other possible events.

b.onmouseleave should be b.addEventListener('mouseleave', ...) and the other too, or you can use handleEvent with an object right away.

As summary, this is how I would've written that:

const winBtn = {
  handleEvent(e) {
    this[`on${e.type}`](e);
  },
  onmouseleave({currentTarget}) {
    Object.assign(currentTarget.style, {
      background: "black",
      borderImage: null
    });
    currentTarget.border = "1px solid transparent";
  },
  onmouseenter() {
    clearNearBy();
  },
  onmousemove({currentTarget, clientX, clientY}) {
    currentTarget.border = "1px solid transparent";
    const {left, top} = currentTarget.getBoundingClientRect();
    const x = clientX - left; //x position within the element.
    const y = clientY - top; //y position within the element.
    Object.assign(currentTarget.style, {
      background:  `radial-gradient(circle at ${x}px ${y}px , rgba(255,255,255,0.25),rgba(255,255,255,0) )`,
      borderImage: `radial-gradient(20% 65% at ${x}px ${y}px ,rgba(255,255,255,0.7),rgba(255,255,255,0.7),rgba(255,255,255,0.1) ) 9 / 2px / 0px stretch `
    });
  }
};

document.querySelectorAll(".win-btn").forEach((b) => {
  for (const type of ['mouseleave', 'mouseenter', 'mousemove'])
    b.addEventListener(type, winBtn);
});
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
jashgopani profile image
Jash Gopani

Nice ✨

Thread Thread
 
webreflection profile image
Andrea Giammarchi

if you look closer, you also have one object as listener, with 4 methods, instead of N x 3 functions per each .win-btn on the page ... it's both a RAM and a CPU win ;-)

Thread Thread
 
jashgopani profile image
Jash Gopani • Edited

Do you always prefer this syntax over normal syntax? Since you have a ton of experience in JS, I would like to know what more improvisations can be made 😬. Please give your feedback on part 3 also

Thread Thread
 
webreflection profile image
Andrea Giammarchi

not sure this answers your question: webreflection.medium.com/dom-handl... 👋

Collapse
 
namanvyas profile image
Naman vyas

wonderful jash 👍

Collapse
 
jashgopani profile image
Jash Gopani

Thankyou😇

Collapse
 
jagritgoyal profile image
JagritGoyal • Edited

Hi,
first of all thank you so much for making the code for this effect and the detailed explanation of the code.
I want to apply the same effect in my project but have to do some modifications, one of which is that i want to add an image also with the text in each grid item but after doing that the affect is not working properly.

The problem is that if i hover over any grid item that contains the image, there are some points at which the hover effect doesnt work.
I dont know what is the problem or what to change in code to make it work properly.
Please help!!!

Problem 1:

Image description

Problem 2:

Image description

Collapse
 
jashgopani profile image
Jash Gopani

Hey Jagrit, Thanks for the feedback. I had also encountered same problem sometime after publishing these articles. The solution I used is that to use a div as the win-grid-item on top of our actual grid item.
If you are trying to implement it in react then you can try the component that I have published on npm - npmjs.com/package/react-win-grid

Collapse
 
jagritgoyal profile image
JagritGoyal

What is the win-grid-item?
Can you please give a detailed solution to this?

Thread Thread
 
jashgopani profile image
Jash Gopani

My bad, by win-grid-item, I meant any item inside the win-grid class. These are just the component names that I used for my npm package.

Here is the idea in simpler terms:
Originally, the items that we have in our grid are primitive elements and not composite i.e. they don't have any child elements inside them. So the logic that I have given in the article tries to change the background of the button.

Now, when we have composite elements in our win-grid class, like having a div and inside that having other elements, we want to show the gradient on top of that composite item. So what you can do in this case is that place a transparent div element on top of each composite item in your grid.

A simple analogy would be that the grid is a collection of boxes, and each box has some items in it. You want the spotlight to highlight the edges of the boxes and the top of the boxes. So what you do is that you cover each box with a transparent lid and now write your code to apply the spotlight effects on the edges and surface of lid and apply a blending mode so that it will look like the effect is applied to whole box and not just the lid.

You can have a look at these two files where I have done the same thing for my react component
Github link

You can refer to the ".hoverlay" class here. It is analogous to the transparent lid. If you are not very familiar with react then the whole code might confuse you but the idea is the same that I've explained above.

Let me know if you have any further questions.

Collapse
 
professor9833 profile image
Professor9833

Great explanation!

Collapse
 
jashgopani profile image
Jash Gopani

Thankyou professor 🤓

Collapse
 
mihirgandhi profile image
Mihir Gandhi

Waah Gopani Ji Waah! XD
Thanks for explaining every aspect of the code, including why you didn't use map() or forEach(). Great post!

Collapse
 
jashgopani profile image
Jash Gopani

Thankyou Gandhi Ji 🙌

Collapse
 
amoldalwai profile image
amoldalwai

Great logic and explanation ..never thought that such a simple ui would be that difficult to make.

Collapse
 
jashgopani profile image
Jash Gopani

Less is more 😂

Collapse
 
arnavgu25774294 profile image
Arnav Gupta

A great descriptive article. Very well written and the memes in the middle provided a good laugh and made me enjoy the article a bit more.

Collapse
 
jashgopani profile image
Jash Gopani

Thanks a lot🤟