Image-carousel Web Component in Vanilla JavaScript

Image-carousel Web Component in Vanilla JavaScript

Web Components:

Every developer loves components why? they are reusable and easy to maintain having web components which are encapsulated with there own CSS and JavaScript allows us to avoid conflicts between different parts of the page.

But what if you are looking to not use any frameworks and just work with Vanilla JavaScript, I myself works with pure vanilla JavaScript as it always tempts to use the new frameworks. if you can create a custom elements which are encapsulated with there own styling and functionality using web components in JavaScript isn't that nice.

Let Create a Web Component and learn on the fly after all who are we ? we are coder!!! and what do we do ?? We copy paste

lets Create a Image carousel component why? don't we think this is something that is being used in any website that we land so why don't we try and create a simple Image carousel web component which is reusable and also encapsulated with its own styling and functionality, this carousel changes images every after 2 secs.

To begin with lets create our good old HTML boiler plate.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script type="module" src="app.js"></script>
</head>
<body>
  <image-carousel></image-carousel>
</body>
</html>

<image-carousel></image-carousel> this HTMLElement which you see in the body element is our new custom HTMLELement. In order to create that create a app.js in the project folder and also create a new folder in your project and name it as Components this is where you will create your components.

In Components folders I'm gonna create a file caller Carousel.js and here we will be creating our carousel web component.In order to create we need to do something like this.

export default class Carousel extends HTMLElement {
  constructor() {
    super();

    this.attachShadow({ mode: "open" });
}

customElements.define('image-carousel', Carousel);

Now this create a new custom HTMLElement which can be used inside the DOM. If you look at the code you can notice that we are initiating a shadowDOM to this HTMLElement.

If you are not aware of shadowDOM you can check out this line , normally shadowDOM allows hidden DOM trees to be attached to elements in the regular DOM tree this shadow DOM tree starts with a shadow root, underneath which you can attach any element, in the same way as the normal DOM. this allows us to encapsulate JavaScript or CSS within the shadowDOM making it a unique and not to conflict with the rest of the code in our solution.

Now Lets create our template, we can target the shadowRoot innerHTML and define our styling and our template.

export default class Carousel extends HTMLElement {
  constructor() {
    super();

    this.attachShadow({ mode: "open" });
    this.shadowRoot.innerHTML = `
        <style>
            .carousel{
                display: flex;
                overflow: hidden;
                width: 300px;
                height: 200px;
            }
            .carousel-images{
                display: flex;
                transition: transform 0.5s ease-in-out;
            }

            .carousel-image{
                width: 100%;
                height: 100%;
                object-fit: cover;
            }
        </style>
        <div class="carousel">
            <div class="carousel-images">
            </div>
        </div>
        `;
}

customElements.define('image-carousel', Carousel);

This attaches the our styling and our template to the shadowRoot but there is nothing inside the template.

let add these Images array under the template and state of the images and our started function

this.images = [
      "https://images.unsplash.com/photo-1490730141103-6cac27aaab94?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
      "https://images.unsplash.com/photo-1536782376847-5c9d14d97cc0?q=80&w=1776&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
      "https://images.unsplash.com/photo-1538991383142-36c4edeaffde?q=80&w=2071&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
    ];

this.currentIndex = 0;

this.startInterval();

In Web Components you can use The connectedCallback lifecycle method it is called when the Carousel element is added to the DOM. This method iterates over the array of image URLs and creates an img element for each one. The img element is then added to the Carousel's images container.

connectedCallback() {
    this.images.forEach((imagePath) => {
      const image = document.createElement("img");
      image.src = imagePath;
      image.classList.add("carousel-image");
      this.shadowRoot.querySelector(".carousel-images").appendChild(image);
    });
  }

The startInterval method creates an interval that calls the nextImage method every 2 seconds. This is what makes the Carousel automatically change slides.

startInterval() {
    this.intervalId = setInterval(() => {
      this.nextImage();
    }, 2000);
  }

The nextImage method is responsible for changing the current image to the next one in the series. It does this by moving the current image to the end of the images container and updating the currentIndex. The translateX CSS property is used to shift the images container horizontally, revealing the next image.

nextImage() {
    const currentImage = this.shadowRoot.querySelector(
      ".carousel-image:first-child"
    );
    const imagesContainer = this.shadowRoot.querySelector(".carousel-images");
    this.currentIndex = (this.currentIndex + 1) % this.images.length;
    if (this.images[this.currentIndex].complete) {
      imagesContainer.style.transform = `translateX(-${
        this.images[this.currentImage].offsetWidth * this.currentIndex
      }px)`;
    }
    console.log(imagesContainer);
    console.log(currentImage);
    imagesContainer.appendChild(currentImage);
  }

Here is the entire code, you can get the entire picture on how to create a web component in Vanilla JavaScript. this can be imported to app.js

class Carousel extends HTMLElement {
  constructor() {
    super();

    this.attachShadow({ mode: "open" });
    this.shadowRoot.innerHTML = `
        <style>
            .carousel{
                display: flex;
                overflow: hidden;
                width: 300px;
                height: 200px;
            }
            .carousel-images{
                display: flex;
                transition: transform 0.5s ease-in-out;
            }

            .carousel-image{
                width: 100%;
                height: 100%;
                object-fit: cover;
            }
        </style>
        <div class="carousel">
            <div class="carousel-images">

            </div>
        </div>
        `;

    this.images = [
      "https://images.unsplash.com/photo-1490730141103-6cac27aaab94?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
      "https://images.unsplash.com/photo-1536782376847-5c9d14d97cc0?q=80&w=1776&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
      "https://images.unsplash.com/photo-1538991383142-36c4edeaffde?q=80&w=2071&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
    ];

    this.currentIndex = 0;

    this.startInterval();
  }

  connectedCallback() {
    this.images.forEach((imagePath) => {
      const image = document.createElement("img");
      image.src = imagePath;
      image.classList.add("carousel-image");
      this.shadowRoot.querySelector(".carousel-images").appendChild(image);
    });
  }

  startInterval() {
    this.intervalId = setInterval(() => {
      this.nextImage();
    }, 2000);
  }

  nextImage() {
    const currentImage = this.shadowRoot.querySelector(
      ".carousel-image:first-child"
    );
    const imagesContainer = this.shadowRoot.querySelector(".carousel-images");
    this.currentIndex = (this.currentIndex + 1) % this.images.length;
    if (this.images[this.currentIndex].complete) {
      imagesContainer.style.transform = `translateX(-${
        this.images[this.currentImage].offsetWidth * this.currentIndex
      }px)`;
    }
    console.log(imagesContainer);
    console.log(currentImage);
    imagesContainer.appendChild(currentImage);
  }
}
customElements.define('image-carousel', Carousel);

Reference:

Here are some of the links and YT videos which I watched to learn, you can also learn in-depth about web components here:

Conclusion:

In conclusion, web components are a powerful tool for creating modern, maintainable, and accessible web applications. By understanding their basic concepts and utilizing the features they offer, you can enhance your development process and create robust web applications that are easy to use and maintain.