How to Smoothly Zoom Images In and Out in JavaScript

How to Smoothly Zoom Images In and Out in JavaScript

Building a carousel in vanilla JavaScript with zoom effects
Ferenc Almasi β€’ 2022 July 19 β€’ Read time 12 min read
Learn how you can build from scratch, and how to smoothly zoom images in and out in your JavaScript carousel.
  • twitter
  • facebook
JavaScript

Zooming in and out of images in JavaScript is a great way to save space, but still allow your users to view the full-sized image. In this tutorial, we are going to take a look at how you can zoom in and out on images in JavaScript. But to make this project more practical, we are going to do it as part of implementing a carousel. This project is also hosted on GitHub.

We are going to achieve this in vanilla JavaScript with some CSS animations, without any frameworks. Explaining the implementation of the carousel will take some time, so if you are looking for a short answer on how to zoom images in JavaScript, here it is.

In order to zoom images in and out in JavaScript, you need to either change the width and height properties of the img element, or you need to use transform: scale(). The easiest way to do this is to apply a class to the element with JavaScript. This can happen either on click or on hover.

Zoom images with JavaScript
We will look into both click and hover zoom effects below.

Set up the Project

First, we are going to need to set up the project, however. If you are only interested in the implementation part, you can grab the full source code from GitHub, or you can jump right to the point of interest using the links below:

For everyone else, you will need to set up a placeholder in your HTML for the carousel, and include a new script file as well as some styles. Here is the entire document that we are going to work with:

Copied to clipboard! Playground
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>🎠 Carousel in JavaScript</title>
        <link rel="stylesheet" href="./styles.css" />
    </head>
    <body>
        <div class="carousel"></div>
        <script src="./carousel.js"></script>
    </body>
</html>
index.html

That is all the HTML we need, the rest will be added with JavaScript. Create a carousel.js file next to your index.html if you haven't already, and create the following function:

Copied to clipboard! Playground
const createCarousel = config => { ... }

const images = [{
    src: 'path/to/image.png',
    alt: 'Alt tag for image'
}]

createCarousel({
    selector: '.carousel',
    trigger: 'click',
    images
})
carousel.js

To make this carousel a little bit more configurable, we will allow some configurations to be passed. Namely:

  • selector: A CSS selector that will be used by our createCarousel function to grab the right container.
  • trigger: Either click or hover to define how the carousel should be triggered.
  • images: An array of image objects, containing a src and an alt property. This way, you can create carousels from remote data sources.

To create the HTML for the carousel itself, add the following to your createCarousel function:

Copied to clipboard! Playground
const createCarousel = config => {
    const {
        selector,
        images,
        trigger
    } = config

    const even = images.length % 2 === 0
    const activeImageIndex = Math.floor(images.length / 2)
    const container = document.querySelector(selector)
    const html = `
        <ul${even ? ' class="even"' : ''}>
            ${images.map((image, index) => `
                <li${index === activeImageIndex ? ' class="active"' : ''}>
                    <img
                        data-target="img"
                        src="${image.src}"
                        alt="${image.alt}"
                    />
                </li$>
            `).join('')}
        </ul>
        <div class="arrows">
            <span class="left" data-target="left">⬅️</span>
            <span class="right" data-target="right">➑️</span>
        </div>
    `
    
    container.innerHTML = html
}
carousel.js

This may seem like a lot to take at first, but let's break it down. First, we want to grab everything from the configuration object. We can do this with destructuring. Then we have two variables, even and activeImageIndex which will be used by CSS.

even can be used to tell whether the number of images is even, in which case, we want to align the carousel accordingly to make the active image always appear in the center of the screen, while activeImageIndex will be used to grab the middle element from the images.

Adjusting carousel position based on number of images
Image will always be centered to the viewport if we adjust the carousel by half of the width of an image

We can use the remainder (modulo) operator to calculate if there are even number of images and to grab the image in the middle of the array, we can use its length, divided by two.

The rest is just building up the HTML with a template literal and assigning it to the innerHTML of the passed element, that we can grab with a querySelector.

Notice that we have data-target values on the elements. We will use these in JavaScript to grab the right DOM elements.

Looking to improve your skills? Check out our interactive course to master JavaScript from start to finish.
Master JavaScriptinfo Remove ads

Now that we have the necessary DOM elements for the carousel, we need to style it accordingly so it actually looks and behaves like a carousel. For the carousel container, we will need the following rules:

Copied to clipboard! Playground
.carousel {
    max-width: 2500px;
    width: 100%;
    overflow: hidden;
    padding: 150px 0;
}
styles.css
Your max-width may differ depending on your use-case

We need overflow: hidden to ensure the width of the carousel doesn't exceed 100% of the screen. Also, note that we added a quite large padding. We need this to avoid clipping. Without this, zoomed-in images would be clipped.

The padding ensures the zoom effect is not clipped

Optionally, we can also add an ::after element to create a fade-out effect for the furthest images from the center. This can be achieved with a radial gradient:

Copied to clipboard! Playground
.carousel::after {
    content: '';
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    background: radial-gradient(circle, rgba(17,12,17,0) 30%, rgba(17,12,17,1) 90%);
}
styles.css
You can use cssgradient.io to generate gradients

If you do so, make sure you include pointer-events: none to allow the images to receive click events. Otherwise, they will be masked out by the element. Moving forward, the list is displayed as a flex, centered on the screen. If you want to animate the zoom effects, this is where you also want to add a transition.

Copied to clipboard! Playground
.carousel ul {
    margin: 0;
    padding: 0;
    display: flex;
    list-style-type: none;
    justify-content: center;
    transition: transform .6s cubic-bezier(0.075, 0.82, 0.165, 1);
}

.carousel ul.even {
    transform: translateX(-250px);
}
styles.css
Make sure you remove the list style type

This is where we also want to adjust the carousel for an even number of images. Since each image will have a width of 500px, we want to use half of that for the adjustment. Lastly, we have the image. We will use a transform: scale for zooming the images in and out.

Copied to clipboard! Playground
/* For an initial zoomed-in effect */
.carousel ul li.active img {
    transform: scale(1.2);
}

/* For zooming even further on click */
.carousel ul li.active img.zoom {
    transform: scale(2);
}

/* For disabling click event on images that are not in the middle */
.carousel ul li:not(.active) img {
    pointer-events: none;
}

.carousel img {
    width: 500px;
    height: 250px;
    object-fit: cover;
    display: block;
    cursor: pointer;
    transition: transform .6s cubic-bezier(0.075, 0.82, 0.165, 1);
}
styles.css

Since the dimensions are fixed, you also want to add object-fit: cover to avoid distorting the aspect ratio of the images. If you want your zoom effects to be animated, this is where you need to add a transition again.


How to Zoom Image Onclick

Now that we have everything sorted for CSS, we can jump back into coding actual interactivity. First, let's have a look at how you can zoom images in JavaScript using a click event. We will need to add a click event listener on the carousel itself, and then we can toggle a zoom class that will add a transform property on the image:

Copied to clipboard! Playground
let transform = even ? -250 : 0
let index = activeImageIndex

container.addEventListener('click', event => {
    const target = event.target
    const carousel = container.querySelector('ul')
    const activeElement = container.querySelector('.active')

    switch (target.dataset.target) {
        case 'img':
            if (trigger !== 'hover') {
                target.classList.toggle('zoom')
            } 
        break
        case 'left':
            if (index !== 0) {
                index--
                transform += 500
                carousel.style.transform = `translateX(${transform}px)`

                activeElement.classList.remove('active')
                activeElement.previousElementSibling.classList.add('active')
            }
        break
        case 'right':
            if (index !== images.length - 1) {
                index++
                transform -= 500
                carousel.style.transform = `translateX(${transform}px)`

                activeElement.classList.remove('active')
                activeElement.nextElementSibling.classList.add('active')
            }
        break
    }
})
carousel.js
We can switch between click targets based on the data attribute

For the zoom effect itself, we only need the first case from the switch. This toggles the necessary class. The left and right case on the other hand handles the navigation.

We need to transform the entire carousel by the width of an image (500px) either to the left or right, and also switch the classes of the active image. Make sure you check if we are on the first or last image to prevent the user to navigate in one direction indefinitely. For these checks, we can store an index just above the event listener.

Notice that in case the number of images is even, we want the initial value of the transform variable to be -250px.


How to Zoom Image Onmouseover

For triggering zooms on mouse over, we need to add two more event listeners: mouseover for the hover in, and mouseout for the hover-out events:

Copied to clipboard! Playground
if (trigger === 'hover') {
    container.addEventListener('mouseover', event => {
        if (event.target.dataset.target === 'img') {
            event.target.classList.add('zoom')
        }
    })

    container.addEventListener('mouseout', event => {
        if (event.target.dataset.target === 'img') {
            event.target.classList.remove('zoom')
        }
    })
}
carousel.js
Make sure you check if the event is received by the image

This does the same thing as the click event listener. Either add (on hover) or removes the zoom class (on blur).

Zooming images in and out in JavaScript

Summary

Congratulations, you have just finished creating your very first carousel in JavaScript with zoom-in and out functionality! As mentioned in the beginning, the full source code is available on GitHub.

Want to take this one step further? Here are some ideas on how to make this carousel more configurable:

  • Introduce infinite scrolling
  • Allow navigation with swipes and the keyboard
  • Display dots instead of arrows
  • Allow links to be placed on the images

Are you looking for more JavaScript projects? Check out the article below to find 100 JavaScript project ideas. Thank you for reading through, happy coding! πŸŽ 

100 JavaScript Project Ideas
  • twitter
  • facebook
JavaScript
Did you find this page helpful?
πŸ“š More Webtips
Mentoring

Rocket Launch Your Career

Speed up your learning progress with our mentorship program. Join as a mentee to unlock the full potential of Webtips and get a personalized learning experience by experts to master the following frontend technologies:

Courses

Recommended

This site uses cookies We use cookies to understand visitors and create a better experience for you. By clicking on "Accept", you accept its use. To find out more, please see our privacy policy.