7 days of unlimited WordPress themes, plugins & graphics - for free!* Unlimited asset downloads! Start 7-Day Free Trial
  1. Web Design
  2. HTML

How to Make Multi-Preview Thumbnails With JavaScript Mouse Events

Scroll to top
Read Time: 5 mins

In this tutorial we’ll have some fun with JavaScript mouse events by building something useful and interesting: thumbnails which, when hovered over, display a selection of different ebooks.

Here’s the demo that we’re going to build (move the mouse around over each thumbnail):

Each thumbnail displays the corresponding ebooks hidden underneath, depending on the cursor position. It’s an ideal way of giving a sneak preview of what’s available (in this case in the Envato Tuts+ ebook library).

As we build this we’ll be using CSS Grid Layout and the JavaScript mousemove event, amongst other things.

1. The HTML Markup

The markup we’ll use is pretty straightforward; a plain unordered list with some equally-sized images inside each of the list items (cards). 

2. The CSS

Now, with regards to the CSS styles, two things are important:

  • We define the unordered list as a grid container and give the list items width: 25%.  Instead of CSS grid, you could use flexbox or your preferred layout method.
  • We visually hide and absolutely position all images inside the list items, apart from the first one.

The CSS rules we apply to our demo are shown below:

With a couple of other reset styles (removing the bullets from the unordered list, giving the body a background color etc.) we end up with this:

3. The JavaScript

Let’s add the following two lines so that when all page assets are ready, the init function is executed. We’ll also trigger it every time the browser window is resized.

Inside this function, a number of things happen; first we loop through the cards.

Loop the Child Images

Next, for each card we retrieve the number of child images without taking into account the first image. 

Note: first image is visible by default and not absolutely positioned. 

If there’s at least one child image, we do the following things:

  • Calculate the width of the card (the width of the first image) and...
  • ...split the card into equal parts by dividing its width with the number of child images.

To better understand this, let’s assume that our first card is 235px wide. This card contains four images (remember we ignore the first image), so the division 235px/4 will give us 58.75px. So what is the role of this number? Well, it creates our ranges, so upon card hover, we track the mouse X position, check its range, and finally display the appropriate image.

For our simple example, here are the generated ranges:

Mouse X Position Image to Show
0<X≤58.75px 1st
58.75px<X≤117.5px 2nd
117.5px<X≤176.25px 3rd
176.25px<X≤235px 4th

Please note the “Image to Show” column shows the image that should appear from the pool of the four child images (once again we exclude the first visible image).

Now that we know the requirements, let’s translate them into code. Still inside the loop we listen for the mousemove event.

When this event fires, we perform the following actions:

  1. Get the X coordinate of the mouse pointer relative to the “hovered” card and not relative to the browser window.
  2. Remove the is-visible class from all card images.
  3. Display the appropriate image depending on the mouse position (see previous table for an example). 

Part of the code that implements the aforementioned behavior is as follows:

As you can see, there are two custom functions. Firstly, the removeIsVisibleClass function which is responsible for removing the is-visible class from the corresponding image. Secondly, the more general addClass function which is responsible for adding the is-visible class to the target image. 

Here’s their signature:

So far, we’ve seen what happens every time we hover over a card. Let’s now discuss the opposite scenario. In other words, what should happen if we stop hovering over a card. In this case the first initial image should be displayed:

4. Browser Support

Our demo should work well in most of the desktop browsers. A few notes though:

  • The demo makes use of CSS Grid and the foreach loop which aren’t supported by all browsers. There are alternative solutions for both cases if you prefer to use a fallback.
  • The demo works similarly on all screens/devices and isn’t optimized for small screens/touch devices. For our simple demo that's fine, but in a real project you might want to restrict this implementation to larger screens only (or non-touch devices).

Finally, as usual, we use Babel to compile the ES6 code down to ES5.


In this tutorial, we managed to build an interesting hover effect by taking advantage of JavaScript mouse events. Hopefully you’ve been inspired enough to build something amazing. 

To take things further, I encourage you to build a reusable function that will handle the repetitive code inside the switch statement. Post a comment if you take the challenge on!

Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Web Design tutorials. Never miss out on learning about the next big thing.
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.