How to create Disney plus clone with pure HTML, CSS, JS
Tags: html, css, javascript, webdev
Published: 2021-08-15 10:14:28

Hello, Today we'll see, how we can easily create a disney plus UI clone using HTML, CSS and JS only. No other library. We'll also see how we can make an endless slider effect. Which took me 2-3 hrs to code.

Our clone is very similar to the original disney plus website. It is only one page(homepage) website. It has navbar and search box with cool click effect same as disney+ and it also has a slider or carousel with infinity or endless effect. Which was very hard for me to make at first. And after that we also have movie cards. With awesome card hover effect. And we have much more.

To see demo or you want full coding tutorial video with explanation. You can watch the tutorial below.

#Video Tutorial

{% youtube ZeY9RicS2js %}

> I appreciate if you can support me by subscribing my youtube channel. 

So, without wasting more time let's see how to code this.

#Code

Before we start writing our code. Although it's not a Node app but we should see it folder structure at least to with.

![Frame 7](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/43mi53jv6t5akp4m34cp.png)
 

[Download Template](https://github.com/kunaal438/disney-plus-clone)

You can see we have a file named `data.js`. This file contain our movie slider data. You can see below.

```JS
let movies = [
    {
        name: 'falcon and the winter soldier',
        des: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Velit porro et veniam excepturi, eaque voluptatem impedit nulla laboriosam facilis ut laboriosam libero!',
        image: 'images/slider 2.PNG'
    },
    {
        name: 'loki',
        des: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Velit porro et veniam excepturi, eaque voluptatem impedit nulla laboriosam facilis ut laboriosam libero!',
        image: 'images/slider 1.PNG'
    },
    {
        name: 'wanda vision',
        des: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Velit porro et veniam excepturi, eaque voluptatem impedit nulla laboriosam facilis ut laboriosam libero!',
        image: 'images/slider 3.PNG'
    },
/// and so on
]
```
If you see the starting data. You'll notice that our `slide-1` is on second number on the list. Why is that. That is because. Our slider will have 3 slides at a time and we want the active slide to be in center. Which means when we first start with slide data. our active slide or first slide will be in middle. I hope this make sense. If not then watch it video tutorial for more better understanding.

Now let's code the webpage.

###Webpage.

Start with `index.html`. Write basic HTML structure and link CSS and JS files. Make sure you add `data.js` file before `app.js`. So that we can access the data in `app.js` file.

Now first create Navbar.
```HTML
<nav class="navbar">
    <img src="images/logo.png" class="brand-logo" alt="">
    <ul class="nav-links">
        <li class="nav-items"><a href="#">TV</a></li>
        <li class="nav-items"><a href="#">movies</a></li>
        <li class="nav-items"><a href="#">sports</a></li>
        <li class="nav-items"><a href="#">premium</a></li>
    </ul>

    <div class="right-container">
        <input type="text" class="search-box" placeholder="search">
        <button class="sub-btn">subscribe</button>
        <a href="#" class="login-link">login</a>
    </div>
</nav>
```
```CSS
*{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body{
    width: 100%;
    background: #0c111b;
    position: relative;
    font-family: roboto, sans-serif;
}

.navbar{
    width: 100%;
    height: 80px;
    position: fixed;
    top: 0;
    left: 0;
    padding: 0 4%;
    background: #0c111b;
    z-index: 9;
    display: flex;
    align-items: center;
}

.brand-logo{
    height: 70px;
}

.nav-links{
    margin-top: 10px;
    display: flex;
    list-style:none;
}

.nav-items a{
    text-decoration: none;
    margin-left: 20px;
    text-transform: capitalize;
    color: #fff;
    opacity: 0.9;
}

.right-container{
    display: block;
    margin-left: auto;
}

.search-box{
    border: none;
    border-bottom: 1px solid #aaa;
    background: transparent;
    outline: none;
    height: 30px;
    color:#fff;
    width: 250px;
    text-transform: capitalize;
    font-size: 16px;
    font-weight: 500;
    transition: .5s;
}

.search-box:focus{
    width: 400px;
    border-color: #1f80e0;
}

.sub-btn{
    background: #1f80e0;
    height: 30px;
    padding: 0 20px;
    color: #fff;
    border-radius: 5px;
    border: none;
    outline: none;
    text-transform: uppercase;
    font-weight: 700;
    font-size: 12px;
    margin: 0 10px;
}

.login-link{
    color: #fff;
    opacity: 0.9;
    text-transform: uppercase;
    font-size: 15px;
    font-weight: 700;
    text-decoration: none;
}
```
######Output
![Capture](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ssx01cj78btv6z5ixeca.PNG)

Now let's make slider. We'll create these slides with JS but for styling purpose just create one for now in HTML.

```HTML
div class="carousel-container">
    <div class="carousel">
        <div class="slider">
            <div class="slide-content">
                <h1 class="movie-title">loki</h1>
                <p class="movie-des">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Suscipit saepe eius ratione nostrum mollitia explicabo quae nam pariatur. Sint, odit?</p>
            </div>
            <img src="images/slider 1.PNG" alt="">
        </div>
    </div>
</div>
``` 
```CSS
.carousel-container{
    position: relative;
    width: 100%;
    height: 450px;
    padding: 20px 0;
    overflow-x: hidden;
    margin-top: 80px;
}

.carousel{
    display: flex;
    width: 92%;
    height: 100%;
    position: relative;
    margin: auto;
}

.slider{
    flex: 0 0 auto;
    margin-right: 30px;
    position: relative;
    background: rgba(0, 0, 0,0.5);
    border-radius: 5px;
    width: 100%;
    height: 100%;
    left: 0;
    transition: 1s;
    overflow: hidden;
}

.slider img{
    width: 70%;
    min-height: 100%;
    object-fit: cover;
    display: block;
    margin-left: auto;
}

.slide-content{
    position: absolute;
    width: 50%;
    height: 100%;
    z-index: 2;
    background: linear-gradient(to right, #030b17 80%, #0c111b00);
    color: #fff;
}

.movie-title{
    padding-left: 50px;
    text-transform: capitalize;
    margin-top: 80px;
}

.movie-des{
    width: 80%;
    line-height: 30px;
    padding-left: 50px;
    margin-top: 30px;
    opacity: 0.8;
}
```
######Output
![Capture2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i61exbw1vitv17v63kiv.PNG)
YOu can comment the slide now. As we are done styling it.
And create this slider working. [Watch this](https://youtu.be/ZeY9RicS2js?t=846) to understand the working concept of this slider.

Inside `app.js` . Select our Carousel element and create an empty array to store all slides.

```JS
const carousel = document.querySelector('.carousel');
let sliders = [];

let slideIndex = 0; // to track current slide index.
```
Now create a function `createSlide` for creating a slide.

```JS
const createSlide = () => {
    if(slideIndex >= movies.length){
        slideIndex = 0;
    }

    // creating DOM element
    let slide = document.createElement('div');
    let imgElement = document.createElement('img');
    let content = document.createElement('div');
    let h1 = document.createElement('h1');
    let p = document.createElement('p');
}
```
In this function. In the start we are increasing or setting our next `slideIndex` with some if/else condition. And after that we are creating DOM element that we need for our slide. These all elements are exactly same as we had in our `index.html`.

After creating all these elements. Append/attach these elements to one another to form the HTML strucuture.

```JS
{
    // attaching all elements
    imgElement.appendChild(document.createTextNode(''));
    h1.appendChild(document.createTextNode(movies[slideIndex].name));
    p.appendChild(document.createTextNode(movies[slideIndex].des));
    content.appendChild(h1);
    content.appendChild(p);
    slide.appendChild(content);
    slide.appendChild(imgElement);
    carousel.appendChild(slide);
}
```
> this code is inside `createSlide` function.

After done appending elements to each other. Now set their class names and set image's source.

```JS
{
    // setting up image
    imgElement.src = movies[slideIndex].image;
    slideIndex++;

    // setting elements classname
    slide.className = 'slider';
    content.className = 'slide-content';
    h1.className = 'movie-title';
    p.className = 'movie-des';

    sliders.push(slide);
}
```
And last remember to push the `slide` inside `sliders` array.

We are done creating sliders. But our slider won't work why because we have to shift our first slide to the left. For that add this at the end of the function.

```JS
{
    if(sliders.length){
        sliders[0].style.marginLeft = `calc(-${100 * (sliders.length - 2)}% - ${30 * (sliders.length - 2)}px)`;
    }
}
```
And now if you create slides. You'll see our slider works or not.
```JS
for(let i = 0; i < 3; i++){
    createSlide();
}

setInterval(() => {
    createSlide();
}, 3000);
```
We are done with Sliders. Now create video cards.
```HTML
<div class="video-card-container">
    <div class="video-card">
        <img src="images/disney.PNG" class="video-card-image" alt="">
        <video src="videos/disney.mp4" mute loop class="card-video"></video>
    </div>
    <div class="video-card">
        <img src="images/pixar.PNG" class="video-card-image" alt="">
        <video src="videos/pixar.mp4" mute loop class="card-video"></video>
    </div>
    <div class="video-card">
        <img src="images/marvel.PNG" class="video-card-image" alt="">
        <video src="videos/marvel.mp4" mute loop class="card-video"></video>
    </div>
    <div class="video-card">
        <img src="images/star-wars.PNG" class="video-card-image" alt="">
        <video src="videos/star-war.mp4" mute loop class="card-video"></video>
    </div>
    <div class="video-card">
        <img src="images/geographic.PNG" class="video-card-image" alt="">
        <video src="videos/geographic.mp4" mute loop class="card-video"></video>
    </div>
</div>
```
```CSS
.video-card-container{
    position: relative;
    width: 92%;
    margin: auto;
    height: 10vw;
    display: flex;
    margin-bottom: 20px;
    justify-content: space-between;
}

.video-card{
    position: relative;
    min-width: calc(100%/5 - 10px);
    width: calc(100%/5 - 10px);
    height: 100%;
    border-radius: 5px;
    overflow: hidden;
    background: #030b17;
}

.video-card-image,
.card-video{
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.card-video{
    position: absolute;
}

.video-card:hover .video-card-image{
    display: none;
}
```
######Output
![Capture3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9fb8tsay4r4ayi27lytk.PNG)
And to make video play on hover card. Code this.
```JS
/// video cards

const videoCards = [...document.querySelectorAll('.video-card')];

videoCards.forEach(item => {
    item.addEventListener('mouseover', () => {
        let video = item.children[1];
        video.play();
    })
    item.addEventListener('mouseleave', () => {
        let video = item.children[1];
        video.pause();
    })
})
``` 
>This effect will only work if user click on your site first. If use did not click on your page first then the video will not play because of the google chrome policy.

And the last thing. Let's create cards.

```HTML
    <h1 class="title">recommended for you</h1>
    <div class="movies-list">
        <button class="pre-btn"><img src="images/pre.png" alt=""></button>
        <button class="nxt-btn"><img src="images/nxt.png" alt=""></button>
        <div class="card-container">
            <div class="card">
                <img src="images/poster 1.png" class="card-img" alt="">
                <div class="card-body">
                    <h2 class="name">movie name</h2>
                    <h6 class="des">Lorem ipsum dolor sit amet consectetur.</h6>
                    <button class="watchlist-btn">add to watchlist</button>
                </div>
            </div> 
            ...20+ more cards
        </div>
   </div>
.. repeat this whole block 3-4 times with different card content
```

```CSS
.title{
    color: #fff;
    opacity: 0.9;
    padding-left: 4%;
    text-transform: capitalize;
    font-size: 22px;
    font-weight: 500;
}

.movies-list{
    width: 100%;
    height: 220px;
    position: relative;
    margin: 10px 0 20px;
}

.card-container{
    position: relative;
    width: 92%;
    padding-left: 10px;
    height: 220px;
    display: flex;
    margin: 0 auto;
    align-items: center;
    overflow-x: auto;
    overflow-y: visible;
    scroll-behavior: smooth;
}

.card-container::-webkit-scrollbar{
    display: none;
}

.card{
    position: relative;
    min-width: 150px;
    width: 150px;
    height: 200px;
    border-radius: 5px;
    overflow: hidden;
    margin-right: 10px;
    transition: .5s;
}

.card-img{
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.card:hover{
    transform: scale(1.1);
}

.card:hover .card-body{
    opacity: 1;
}

.card-body{
    opacity: 0;
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
    z-index: 2;
    background: linear-gradient(to bottom, rgba(4, 8, 15, 0), #192133 90%);
    padding: 10px;
    transition: 0.5s;
}

.name{
    color: #fff;
    font-size: 15px;
    font-weight: 500;
    text-transform: capitalize;
    margin-top: 60%;
}

.des{
    color: #fff;
    opacity: 0.8;
    margin: 5px 0;
    font-weight: 500;
    font-size: 12px;
}

.watchlist-btn{
    position: relative;
    width: 100%;
    text-transform: capitalize;
    background: none;
    border: none;
    font-weight: 500;
    text-align: right;
    color: rgba(255, 255, 255, 0.5);
    margin: 5px 0;
    cursor: pointer;
    padding: 10px 5px;
    border-radius: 5px;
}

.watchlist-btn::before{
    content: '';
    position: absolute;
    top: 0;
    left: -5px;
    height: 35px;
    width: 35px;
    background-image: url(images/add.png);
    background-size: cover;
    transform: scale(0.4);
}

.watchlist-btn:hover{
    color: #fff;
    background: rgba(255, 255, 255, 0.1);
}

.pre-btn,
.nxt-btn{
    position: absolute;
    top: 0;
    width: 5%;
    height: 100%;
    z-index: 2;
    border: none;
    cursor: pointer;
    outline: none;
}

.pre-btn{
    left: 0;
    background: linear-gradient(to right, #0c111b 0%, #0c111b00);
}

.nxt-btn{
    right: 0;
    background: linear-gradient(to left, #0c111b 0%, #0c111b00);
}

.pre-btn img,
.nxt-btn img{
    width: 15px;
    height: 20px;
    opacity: 0;
}

.pre-btn:hover img,
.nxt-btn:hover img{
    opacity: 1;
}
```
######Output
![Capture4](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t3rmpa04nlskxt3g4g2a.PNG)

We are almost done. The last thing we have to do is make this card slider working. For that open `app.js` again.
```JS
// card sliders

let cardContainers = [...document.querySelectorAll('.card-container')];
let preBtns = [...document.querySelectorAll('.pre-btn')];
let nxtBtns = [...document.querySelectorAll('.nxt-btn')];

cardContainers.forEach((item, i) => {
    let containerDimensions = item.getBoundingClientRect();
    let containerWidth = containerDimensions.width;

    nxtBtns[i].addEventListener('click', () => {
        item.scrollLeft += containerWidth - 200;
    })

    preBtns[i].addEventListener('click', () => {
        item.scrollLeft -= containerWidth + 200;
    })
})
```
And we are done.

So, that's it. I hope you understood each and everything. If you have doubt or I missed something let me know in the comments.

#Articles you may find Useful

1. [Infinte CSS loader](https://dev.to/kunaal438/quick-css-make-infinity-loading-animation-for-your-next-website-187k)
2. [Best CSS Effect](https://dev.to/kunaal438/css-the-best-css-effects-of-all-time-most-underrated-web-ux-2chj)
3. [Wave Button Hover Effect](https://dev.to/kunaal438/create-awesome-wavy-button-hover-effect-pure-css-wavy-design-1722)
4. [Youtube API - Youtube Clone](https://dev.to/kunaal438/create-working-youtube-clone-with-search-box-youtube-api-2a6e)
5. [TMDB - Netflix Clone](https://dev.to/kunaal438/how-to-create-netflix-clone-netflix-clone-with-hmtl-css-js-989)

I really appreciate if you can subscribe my youtube channel. I create awesome web contents.

<a href="https://www.youtube.com/c/modern_web?sub_confirmation=1"><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jeitpawvax07cx7r9yoa.png"></a>

Thanks For reading.