How to make a 3D Image Slider Cube - Using HTML, CSS, and Vanilla JS

In this article, I will show you how to make a 3D Image Slider Cube. It's a really common component that you've probably seen on a lot of websites.

We'll take a step-by-step approach to create a 3D Image Slider Cube in this article, to make it as beginner-friendly as possible.

Prerequisites for this project:

This article requires a basic understanding of HTML, CSS, and a little bit of Javascript. I'll explain the project in a manner that makes it easy to follow even for complete beginners with a basic understanding of the listed technologies.

Project Goal:

This short video is our end project after completion. We will create a 3d image slider cube, and two navigation buttons to slide our cube -- previous & next buttons.

Step 1: HTML structure

Create the boilerplate HTML and connect it with CSS and Javascript files.

Once done, let's look at the body element of our webpage. Here, we will create a structure for our image slider cube.

<div class="wrapper">
   <div class="container">
      <div class="image-cube">
      </div>
   </div>
</div>

Here, we have created three div elements -- a component wrapper, a container, and an image cube.

CSS:
* {
    padding: 0;
    margin: 0;
    box-sizing: border-box;
}

body {
    background-color: #9cd2d8;
}

.wrapper {
    border: 1px solid #ffffff;
    height: 300px;
    width: 300px;
    position: absolute;
    margin: auto;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
}

.container {
    height: 100%;
    width: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    perspective: 800px;
    perspective-origin: 50%;
}

.image-cube {
    width: 300px;
    height: 300px;
    transform-style: preserve-3d;
    position: relative;
    transition: 2s;
}

In the CSS file, the wrapper is positioned absolute, which means its position is set relative to its parent element i.e. body for this case. We centered the wrapper using margin: auto. Read more about "position in CSS".

The container element has a flex display and is taking all the space of its parent element. Container element has perspective: 800px and perspective-origin: 50%.

The perspective attribute in CSS defines the distance of z-index = 0 plane from the user, hence adds perspective for the 3D-positioned element.

Greater perspective value means farther the z-index=0 plane from the user (or screen) and smaller the value means the z-index=0 plane is much closer. Lesser perspective values really enhance the 3D object as it causes large transformation. Read more about perspective in CSS.

The perspective-origin specifies the vanishing point in CSS, which gives us the line of sight and the respective position of the viewer.

The image-cube div contains transform-style: preserve-3d which creates a 3D figure where all the child elements of the object will now become the faces of the 3d object. However, currently, they are stacked over one another, and we have to configure the style of each face.

There is also a transition: 2s attribute in the image cube which slows the transition and takes 2s for every sliding operation.

Step 2: Add images to the slider

Next, we add images to the cube and configure the style of all the faces to make it a cube. We know, that in a cube all the faces are at 90 degrees with each other. Thus, we will also configure the child elements of the image-cube (i.e. faces) to be at 90 degrees with each other.

<div class="front">
            <img src="https://images.unsplash.com/photo-1635353019337-d37813892542?crop=entropy&cs=srgb&fm=jpg&ixid=MnwxNDU4OXwwfDF8cmFuZG9tfHx8fHx8fHx8MTYzNjQwNDg3NQ&ixlib=rb-1.2.1&q=85" />
         </div>
         <div class="right">
            <img src="https://images.unsplash.com/photo-1635320623348-bb1f46428927?crop=entropy&cs=srgb&fm=jpg&ixid=MnwxNDU4OXwwfDF8cmFuZG9tfHx8fHx8fHx8MTYzNjQwNDg3NQ&ixlib=rb-1.2.1&q=85" />
         </div>
         <div class="back">
            <img src="https://images.unsplash.com/photo-1635355811454-d2371b64dfe8?crop=entropy&cs=srgb&fm=jpg&ixid=MnwxNDU4OXwwfDF8cmFuZG9tfHx8fHx8fHx8MTYzNjQwNDg3NQ&ixlib=rb-1.2.1&q=85" />
         </div>
         <div class="left">
            <img src="https://images.unsplash.com/photo-1635261155180-77111688b0cf?crop=entropy&cs=srgb&fm=jpg&ixid=MnwxNDU4OXwwfDF8cmFuZG9tfHx8fHx8fHx8MTYzNjQwNTEyMA&ixlib=rb-1.2.1&q=85" />
         </div>

Step3: Styling the image cube to create a 3D cube

.image-cube {
    width: 300px;
    height: 300px;
    transform-style: preserve-3d;
    position: relative;
    transition: 2s;
}

.image-cube div {
    height: 300px;
    width: 300px;
    position: absolute;
}

img {
    width: 100%;
    height: 100%;
    transform: translateZ(0);
}

.front {
    transform: translateZ(150px);
}

.right {
    transform: rotateY(-270deg) translateX(150px);
    transform-origin: 100% 0;
}

.back {
    transform: translateZ(-150px) rotateY(180deg);
}

.left {
    transform: rotateY(270deg) translateX(-150px);
    transform-origin: 0 50%;
}

All the child div elements of the image cube will have position: absolute, hence they remain positioned relative to the image cube.

All image elements have transform: translateZ(0) that sets them at z-index = 0, which is the centre of the cube.

We translate the front face from z=0 to z=150 (positive z value means the object is closer to the screen). On the opposite, the back face has a z-value = -150 which translates it away from the screen. Meanwhile, the mid-point of the distance between the front image and back image lies on z-value = 0.

Moreover, the back image is rotated by 180 degrees to make it similar to a cube in the real world.

Transform right face and rotate it across Y-axis by -270deg and translate on X-axis by 150px right of its original position. On the opposite, we have left face of the cube having transform: rotateY(270deg) translate(-150px) this rotates the face by 270deg and translate 150px towards left on the x-axis.

Step 4: Buttons to slide images

Add buttons components inside the wrapper after the container.

<div class="btns">
   <button id="prev">
   <i class="fas fa-arrow-left">Prev</i>
   </button>
   <button id="next">
   <i class="fas fa-arrow-right">Next</i>
   </button>
</div>
CSS for buttons:
.btns {
    margin-top: 80px;
    display: flex;
    justify-content: space-between;
}

.btns button {
    background-color: transparent;
    color: #ffffff;
    border: 3px solid #ffffff;
    background: #0a3342;
    padding: 8px 40px;
    border-radius: 20px;
    font-size: 20px;
    cursor: pointer;
}

This is just basic HTML and CSS where we are creating and styling previous-button and next-button.

Step 5: Adding sliding function to the buttons

First, we assign the HTML element to the variables in our javascript file.

let cube = document.querySelector(".image-cube");

let btnNext = document.getElementById("next");

let btnPrev = document.getElementById("prev");

Then create variable pos = 0, which specifies the angle of rotation of the whole image cube. Here pos = 0, which means that under normal conditions this slider will be at zero degrees angle.

Finally, add event listeners for button clicks — where, next button rotates the cube by -90 degrees and the previous button rotates the cube by 90 degrees.

let pos = 0;


btnNext.addEventListener("click", () => {

    pos -= 90;

    cube.style.transform = `rotateY(${pos}deg)`;

});

btnPrev.addEventListener("click", () => {

    pos += 90;

    cube.style.transform = `rotateY(${pos}deg)`;

});

Similarly, for the previous button, we increase the pos by 90 for every click. And rotate the cube by 90deg on the Y-axis.

Add any image you like to the cube and you have the 3d image slider cube ready to use.