DEV Community

Sarah Chima
Sarah Chima

Posted on

Image Popup on hover

Image Popup on hover

Recently, I had the task of making an image popup on hover. This gif above describes what I mean. I did not know how to do it but after some minutes of googling, I found a technique that makes it quite easy to implement and uses no JavaScript. This technique is placing two images side by side, the thumbnail image(smaller image) and a larger image which will appear when you hover over the thumbnail image. Let's do this

First Step:

We will be placing the two images side by side, the thumbnail image and the larger image as seen in the block of code below. So in your HTML file, add the following code and remember to properly link your image files.



<main>
  <ul>
    <li>
      <img src="img/thumbnail1.jpg" alt="adventure" >
      <span class="large">
          <img src="img/large1.jpg" class="large-image" alt="adventure" >
      </span>
    </li>
    <li>
      <img src="img/thumbnail2.jpg"" alt="cat" >
      <span class="large">
         <img src="img/large2.jpg" class="large-image" alt="cat" >
      </span>
    </li>
    <li>
        <img src="img/large3.jpg" alt="adventure" >
        <span class="large">
          <img src="img/large3.jpg" class="large-image" alt="adventure" >
        </span>
    </li>
  </ul>
</main>



Enter fullscreen mode Exit fullscreen mode

Since we are using an unordered list, we will style the ul and li in our CSS to remove the list style. Also, we make all the list items to appear inline and the image to appear styled. To your CSS file linked to the HTML code add the following:



    ul {
      display: flex;
    }

    li {
      list-style-type: none;
      padding: 10px;
      position: relative;
    }


Enter fullscreen mode Exit fullscreen mode

Now, this is how our page should look.

Image of work so far

Second Step

Next, we will visually hide the larger image using absolute positioning. We will use the class we add to the span that the larger images were placed in.



.large {
  position: absolute;
  left: -9999px;
}


Enter fullscreen mode Exit fullscreen mode

Now, only the smaller images will be left.

Image of work so far
Let us add some styles to make the large images pop up when you hover over the smaller images.



li:hover .large {
  left: 20px;
  top: -150px;
}


Enter fullscreen mode Exit fullscreen mode

And that is all. When you hover over the small images, the large images appear.

We can decide to do more by adding a box-shadow to the images and even text under for each image. I decided to add a shadow and give the large images a border radius.



.large-image {
  border-radius: 4px;
   box-shadow: 1px 1px 3px 3px rgba(127, 127, 127, 0.15);;
}


Enter fullscreen mode Exit fullscreen mode

So we are done. Have you ever done something similar? How did you do it? I will love to know.

Top comments (11)

Collapse
 
moopet profile image
Ben Sinclair • Edited

I have a suggestion to improve what you've coded - if you ditch the thumbnail images and instead resize the large images in the browser you'll save the extra weight of the thumbnails (since you're always downloading the larger image anyway) and use fewer HTTP requests:

<li>
  <img src="img/large1.jpg" alt="adventure" >
  <span class="large">
    <img src="img/large1.jpg" class="large-image" alt="adventure" >
  </span>
</li>
li > img {
  max-width: 40px;
}

What's the benefit here of not using Javascript?

If you're concerned about accessibility then you've swapped one problem for another - you have to modify the HTML to serve twice the number of images (i.e. it's not "pure" CSS) and will have to find a way of hiding those images and their alt attributes from screen readers, etc.

Collapse
 
sarah_chima profile image
Sarah Chima

Sounds like a great suggestion. So instead of requesting for two images, we use just one. This reduces the number of requests made. Thanks for the suggestion.

Collapse
 
ayrtonvwf profile image
Ayrton Fidelis

Nice article!

We could implement some lazy-loading by putting the large image as the background of an element that appears only when we hover the thumbnail.

Here's an example that demonstrate how lazy-loading would work:

<style>
 img:hover + .big {
  background-image: url('https://via.placeholder.com/300x300');
  width: 300px;
  height: 300px;
 }
</style>
<img src="https://via.placeholder.com/100x100">
<div class="big"></div>

Inspecting the network requests, we can see that the large image is just fetched when we hover the thumbnail.

Of course, we'd have to work a little harder with accessibility.

Collapse
 
stevensonmt profile image
stevensonmt

I like Ben Sinclair's suggestion more, but I was going to recommend modifying the display attribute rather than position to achieve a similar effect. I'm not sure it matters that much, but I would expect that to be a little more efficient on first render.

Collapse
 
stevensonmt profile image
stevensonmt

BTW, here's an example my daughter and I put together last year for her to learn about HTML and CSS, which is similar to what you've done but uses transitions and the display property instead of position. We'll work on font choice next year ;)
Repo: github.com/stevensonmt/pheniestem
Site: stevensonmt.github.io/pheniestem/s...

Collapse
 
jeroka profile image
Esteban Rocha

Very good! Love CSS only approaches when possible, BTW! also you could also apply some opacity and transition to that, to create a smooth change.

Collapse
 
sarah_chima profile image
Sarah Chima

That sounds like a great idea! I'll try that.

Collapse
 
david_j_eddy profile image
David J Eddy

Nice Sarah! #backintheday This would have been lines and lines of js logic...then seperate js logic for every browser vendor. Amazing how things have changed...for the better :)

Collapse
 
sarah_chima profile image
Sarah Chima

Wow!!! That must have been tedious.

Collapse
 
andy profile image
Andy Zhao (he/him)

Awesome! Love that it's pure CSS!

Collapse
 
ezizeay profile image
Ezizeay

what about several small hyperlinked images Popup on hover an image?