Найти тему

Карусель изображений на JavaScript

Оглавление

Оставляем для вас ниже готовый код для создания простой карусели с изображениями.

html

<div class="wrapper flex-center-all">

<div class="img-container">

<img src="https://plus.unsplash.com/premium_photo-1684992858411-3e3ddf37c4c9?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=880&q=80"

alt="jellyfish" class="visible" id="img-1">

<img src="https://images.unsplash.com/photo-1495012379376-194a416fcc5f?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=725&q=80"

alt="jellyfish" class="hidden" id="img-2">

<img src="https://images.unsplash.com/photo-1543007168-5fa9b3c5f5fb?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=688&q=80"

alt="jellyfish" class="hidden" id="img-3">

<img src="https://images.unsplash.com/photo-1540968221243-29f5d70540bf?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=627&q=80"

alt="jellyfish" class="hidden" id="img-4">

<img src="https://images.unsplash.com/photo-1601827196754-8a06c1891d35?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=687&q=80"

alt="jellyfish" class="hidden" id="img-5">

</div>

<div class="next-prev-btns">

<div class="prev-btn-container flex-center-all">

<button class="prev-btn flex-center-all">&#8249;</button>

</div>

<div class="next-btn-container flex-center-all">

<button class="next-btn flex-center-all">&#8250;</button>

</div>

</div>

<div class="img-nav-container">

<div class="img-nav-item img-nav-item-selected">

<div class="outer-circle pos-center-all"></div>

<div class="inner-circle pos-center-all"></div>

</div>

<div class="img-nav-item">

<div class="outer-circle pos-center-all"></div>

<div class="inner-circle pos-center-all"></div>

</div>

<div class="img-nav-item">

<div class="outer-circle pos-center-all"></div>

<div class="inner-circle pos-center-all"></div>

</div>

<div class="img-nav-item">

<div class="outer-circle pos-center-all"></div>

<div class="inner-circle pos-center-all"></div>

</div>

<div class="img-nav-item">

<div class="outer-circle pos-center-all"></div>

<div class="inner-circle pos-center-all"></div>

</div>

</div>

</div>

CSS

* {

margin: 0;

padding: 0;

box-sizing: border-box;

}

html {

font-size: 62.5%;

}

/* --- UTILITY CLASSES --- */

.flex-center-all {

display: flex;

align-items: center;

justify-content: center;

}

.pos-center-all {

position: absolute;

top: 50%;

left: 50%;

transform: translate(-50%, -50%);

}

/* ----------------------- */

.wrapper {

height: 100vh;

position: relative;

background: #eee;

}

.img-container {

width: 60vw;

height: 60vw;

}

img {

width: 100%;

height: 100%;

/* object-fit: cover; */

}

.visible {

display: inline;

transition: all 0.125s;

}

.hidden {

display: none;

transition: all 0.125s;

}

.next-prev-btns {

position: absolute;

height: 10vh;

width: 100vw;

display: flex;

justify-content: space-between;

padding: 0 7vw;

align-items: center;

}

.prev-btn-container,

.next-btn-container {

height: 8vw;

width: 8vw;

}

button {

background: none;

border: 0;

font-size: 10vw;

border-radius: 50%;

background: #387ca1;

width: 100%;

height: 100%;

padding-bottom: 1.25vw;

color: #ddd;

transition: all 0.125s;

}

button:hover {

cursor: pointer;

background: #54b9f0;

color: white;

transition: all 0.125s;

}

.img-nav-container {

position: absolute;

bottom: 0;

height: 4vw;

top: calc(50% + 33vw);

display: flex;

justify-content: space-around;

align-items: center;

}

.img-nav-item {

width: 4vw;

height: 100%;

position: relative;

}

.img-nav-item:not(:last-child) {

margin-right: 0.5vw;

}

.inner-circle {

cursor: pointer;

width: 2vw;

height: 2vw;

background: black;

border-radius: 50%;

box-sizing: content-box;

border: 0.5vw solid white;

}

.img-nav-item-selected > .inner-circle,

.img-nav-item-selected > .outer-circle {

cursor: unset;

}

.outer-circle {

cursor: pointer;

position: absolute;

width: 3.5vw;

height: 3.5vw;

border-radius: 50%;

transition: background 0.125s;

}

.img-nav-item-selected > .outer-circle {

background: #999;

transition: background 0.125s;

}

.img-nav-item:hover > .outer-circle {

width: 3.75vw;

height: 3.75vw;

background: black;

cursor: pointer;

}

/* override */

.img-nav-item-selected:hover > .outer-circle {

width: 3.5vw;

height: 3.5vw;

background: #999;

cursor: unset;

}

/* screen is taller than wide */

/* @media (max-aspect-ratio: 100/99) {

.wrapper {

background: blue;

}

} */

/* screen is wider than tall */

@media (min-aspect-ratio: 99/100) {

.img-container {

width: 60vh;

height: 60vh;

}

.next-prev-btns {

height: 10vw;

width: 100vh;

padding: 0 7vh;

}

.prev-btn-container,

.next-btn-container {

height: 8vh;

width: 8vh;

}

button {

font-size: 10vh;

padding-bottom: 1.25vh;

}

.img-nav-container {

height: 4vh;

top: calc(50% + 33vh);

}

.img-nav-item {

width: 4vh;

}

.img-nav-item:not(:last-child) {

margin-right: 0.5vh;

}

.inner-circle {

width: 2vh;

height: 2vh;

border: 0.5vh solid white;

}

.outer-circle {

width: 3.5vh;

height: 3.5vh;

}

.img-nav-item:hover > .outer-circle {

width: 3.75vh;

height: 3.75vh;

}

/* override */

.img-nav-item-selected:hover > .outer-circle {

width: 3.5vh;

height: 3.5vh;

}

}

JavaScript

const images = document.querySelectorAll('img')

const totalImages = images.length;

const prevBtn = document.querySelector('.prev-btn')

const nextBtn = document.querySelector('.next-btn')

const selectedImgBtns = document.querySelectorAll('.img-nav-item')

let currentImgId = 0;

const hideAllImages = () => {

images.forEach(img => {

// hide all images

if (img.classList[0] === 'visible') {

img.classList.remove('visible')

img.classList.add('hidden')

}

})

}

const traverseImages = (direction) => {

hideAllImages()

if (direction === 'prev') {

currentImgId = currentImgId ? (currentImgId - 1) % totalImages : totalImages - 1

} else {

currentImgId = (currentImgId + 1) % totalImages

}

images[currentImgId].classList.remove('hidden')

images[currentImgId].classList.add('visible')

selectedImgBtns.forEach(btn => btn.classList.remove('img-nav-item-selected'))

selectedImgBtns[currentImgId].classList.add('img-nav-item-selected')

}

const handleBtnClick = (btn, i) => {

// not sure about this fuckery, but it works

if (btn.classList.forEach(btnClass => {

if (btnClass === 'img-nav-item-selected') {

return true

}

})) {

return

}

selectedImgBtns.forEach(btn => btn.classList.remove('img-nav-item-selected'))

btn.classList.add('img-nav-item-selected')

hideAllImages()

currentImgId = i

images[currentImgId].classList.remove('hidden')

images[currentImgId].classList.add('visible')

}

prevBtn.addEventListener('click', () => traverseImages('prev'))

nextBtn.addEventListener('click', () => traverseImages('next'))

selectedImgBtns.forEach((btn, i) => {

btn.addEventListener('click', () => handleBtnClick(btn, i))

})