Author: | trandrew96 |
---|---|
Views Total: | 4,566 views |
Official Page: | Go to website |
Last Update: | April 9, 2021 |
License: | MIT |
Preview:

Description:
A Netflix-inspired infinite carousel slider written in vanilla JavaScript.
More Features:
- Touch-enabled.
- Navigation arrows.
- Smooth hover effect.
See Also:
How to use it:
1. Load the needed Font Awesome iconic font in the document.
<script src="https://kit.fontawesome.com/a0043d9bc2.js" crossorigin="anonymous"></script>
2. Build the HTML structure for the carousel slider.
<div class="container"> <button type="button" id="moveLeft" class="btn-nav"> ᐊ </button> <div class="container-indicators"> <div class="indicator active" data-index=0></div> <div class="indicator" data-index=1></div> <div class="indicator" data-index=2></div> </div> <div class="slider" id="mySlider"> <div class="movie" id="movie0"> <img src="movie1.jpg" alt="" srcset="" /> <div class="description"> <div class="description__buttons-container"> <div class="description__button"><i class="fas fa-play"></i></div> <div class="description__button"><i class="fas fa-plus"></i></div> <div class="description__button"><i class="fas fa-thumbs-up"></i></div> <div class="description__button"><i class="fas fa-thumbs-down"></i></div> <div class="description__button"><i class="fas fa-chevron-down"></i></div> </div> <div class="description__text-container"> <span class="description__match">97% Match</span> <span class="description__rating">TV-14</span> <span class="description__length">2h 11m</span> <br><br> <span>Explosive</span> <span>·</span> <span>Exciting</span> <span>·</span> <span>Family</span> </div> </div> </div> </div> <button type="button" id="moveRight" class="btn-nav"> ᐅ </button> </div>
3. The necessary CSS/CSS3 styles.
:root { --movie-width: 15.5vw; --movie-height: 200px; --arrow-width: 50px; --slider-py: 200px; } @media only screen and (max-width: 1000px) { :root { --movie-width: 25vw; } } /* * * THE SLIDER CONTAINER * *********************************/ .slider { width: 100%; overflow-x: scroll; overflow-y: visible; white-space: nowrap; position: relative; padding-top: var(--slider-py); padding-bottom: var(--slider-py); } /* * * SLIDER INDICATORS * *********************************/ .container-indicators { width: 100px; position: absolute; right: 0; top: calc(var(--slider-py) - 60px); visibility: hidden; } .indicator { width: 15px; height: 2px; background-color: grey; display: inline-block; } .indicator.active { background-color: white; } /* * * MOVIE ELEMENTS! * *********************************/ .movie { width: var(--movie-width); height: var(--movie-height); display: inline-block; position: relative; color: white; padding: 0 2px; font-size: 0.8rem; transition: all 0.8s ease-in-out; } .movie:nth-of-type(1) { margin-left: var(--arrow-width); } .movie:hover { transform: scale(1.3); z-index: 2; } .movie img { object-fit: cover; height: 100%; width: 100%; border-radius: 10px; } .description { position: absolute; display: none; z-index: 9999; background-color: #272727; width: var(--movie-width); margin-top: -10px; padding: 10px 0; border-bottom-left-radius: 10px; border-bottom-right-radius: 10px; } /* Make description visible when movie is hovered */ .movie:hover > .description { display: block; } .movie:hover > img { border-bottom-left-radius: 0; border-bottom-right-radius: 0; } .description__buttons-container { display: flex; flex-direction: row; padding: 10px; } .description__text-container { padding: 10px; } .description__match { color: green; } .description__rating { outline: 1px solid white; padding: 0 3px; margin: 0 5px; } .description__button { display: flex; align-items: center; justify-content: center; width: 20px; height: 20px; border: 2px solid white; text-align: center; font-size: 8px; margin-right: 5px; border-radius: 100%; } .description__button:hover { border-color: grey; color: grey; cursor: pointer; } .description__button:nth-of-type(5) { margin-left: auto; margin-right: 0; } /* * * BUTTONS * *********************************/ .btn-nav { width: var(--arrow-width); height: var(--movie-height); border-radius: 5px; position: absolute; bottom: 0; background-color: rgba(0, 0, 0, 0.3); outline: none; border: none; color: white; top: var(--slider-py); z-index: 5; visibility: hidden; } #moveLeft { left: 0; } #moveRight { right: 0; } .container:hover .btn-nav, .container:hover .container-indicators { visibility: visible; }
4. The JavaScript to enable the carousel slider.
const slider = document.querySelector(".slider"); const btnLeft = document.getElementById("moveLeft"); const btnRight = document.getElementById("moveRight"); const indicators = document.querySelectorAll(".indicator"); let baseSliderWidth = slider.offsetWidth; let activeIndex = 0; // the current page on the slider let movies = [ { src: "movie1.jpg", }, { src: "movie2.jpg", }, { src: "movie3.jpg", }, // ... ]; // Fill the slider with all the movies in the "movies" array function populateSlider() { movies.forEach((image) => { // Clone the initial movie thats included in the html, then replace the image with a different one const newMovie = document.getElementById("movie0"); let clone = newMovie.cloneNode(true); let img = clone.querySelector("img"); img.src = image.src; slider.insertBefore(clone, slider.childNodes[slider.childNodes.length - 1]); }); } populateSlider(); populateSlider(); // delete the initial movie in the html const initialMovie = document.getElementById("movie0"); initialMovie.remove(); // Update the indicators that show which page we're currently on function updateIndicators(index) { indicators.forEach((indicator) => { indicator.classList.remove("active"); }); let newActiveIndicator = indicators[index]; newActiveIndicator.classList.add("active"); } // Scroll Left button btnLeft.addEventListener("click", (e) => { let movieWidth = document.querySelector(".movie").getBoundingClientRect() .width; let scrollDistance = movieWidth * 6; // Scroll the length of 6 movies. TODO: make work for mobile because (4 movies/page instead of 6) slider.scrollBy({ top: 0, left: -scrollDistance, behavior: "smooth", }); activeIndex = (activeIndex - 1) % 3; console.log(activeIndex); updateIndicators(activeIndex); }); // Scroll Right button btnRight.addEventListener("click", (e) => { let movieWidth = document.querySelector(".movie").getBoundingClientRect() .width; let scrollDistance = movieWidth * 6; // Scroll the length of 6 movies. TODO: make work for mobile because (4 movies/page instead of 6) console.log(`movieWidth = ${movieWidth}`); console.log(`scrolling right ${scrollDistance}`); // if we're on the last page if (activeIndex == 2) { // duplicate all the items in the slider (this is how we make 'looping' slider) populateSlider(); slider.scrollBy({ top: 0, left: +scrollDistance, behavior: "smooth", }); activeIndex = 0; updateIndicators(activeIndex); } else { slider.scrollBy({ top: 0, left: +scrollDistance, behavior: "smooth", }); activeIndex = (activeIndex + 1) % 3; console.log(activeIndex); updateIndicators(activeIndex); } });
Hi,
a very nice slider! I want to use it in my online movie database. But I have not enough know-how in javascript. How I can change the description nodes of the “movie0” Element (expanding the array is not the problem)? Shoud I use a other element type for that?
An other problem is, that I need to embed the whole slider in a div instead of an document. I get not the right positions of the nav buttons and the font type is not displayed.
I have no idea…
Sincerly,
Ulli