Красивый вариант диагональной карусели для фотографий, который не требует JS-библиотек, а скрипт реализующий его занимает менее 50-ти строчек кода.
Пример:
Заголовок
1
Заголовок
2
Заголовок
3
Заголовок
4
Заголовок
5
Заголовок
6
Заголовок
7
Заголовок
8
Заголовок
9
Заголовок
10
HTML:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<div class="carousel"> <div class="carousel-item"> <div class="carousel-box"> <div class="carousel-title">Заголовок</div> <div class="num">1</div> <img src="photo.jpg" /> </div> </div> <!-- Еще фото --> <div class="carousel-item"> <div class="carousel-box"> <div class="carousel-title">Заголовок</div> <div class="num">N</div> <img src="photo.jpg" /> </div> </div> </div> |
CSS:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
.carousel { position: relative; z-index: 1; height: 600px; overflow: hidden; pointer-events: none; background-image: url(background.jpg); background-repeat: no-repeat; background-position: 50% 50%; background-size: cover; box-shadow: 0 4px 12px rgba(0,0,0,0.2), 0 16px 20px rgba(0,0,0,0.2); line-height: 1.3; margin: 20px 0; } .carousel-item { --width: clamp(150px, 30vw, 300px); --height: clamp(200px, 40vw, 400px); --x: calc(var(--active) * 80% * var(--items)); --y: calc(var(--active) * 20% * var(--items)); --rot: calc(var(--active) * 120deg); --opacity: calc(var(--zIndex) / var(--items) * 3 - 2); overflow: hidden; position: absolute; z-index: var(--zIndex); width: var(--width); height: var(--height); margin: calc(var(--height) * -0.5) 0 0 calc(var(--width) * -0.5); border-radius: 10px; top: 50%; left: 50%; user-select: none; transform-origin: 0% 100%; box-shadow: 0 10px 50px 10px rgba(0, 0, 0, 0.5); background: black; pointer-events: all; transform: translate(var(--x), var(--y)) rotate(var(--rot)); transition: transform 0.8s cubic-bezier(0, 0.02, 0, 1); } .carousel-item .carousel-box { position: absolute; z-index: 1; top: 0; left: 0; width: 100%; height: 100%; transition: opacity 0.8s cubic-bezier(0, 0.02, 0, 1); opacity: var(--opacity); font-family: 'Roboto', sans-serif; } .carousel-item .carousel-box:before { content: ""; position: absolute; z-index: 1; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(to bottom, rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0) 30%, rgba(0, 0, 0, 0) 50%, rgba(0, 0, 0, 0.5)); } .carousel-item .carousel-title { position: absolute; z-index: 1; color: #fff; bottom: 18px; left: 20px; transition: opacity 0.8s cubic-bezier(0, 0.02, 0, 1); font-size: clamp(16px, 3vw, 20px); text-shadow: 0 0 12px rgba(0,0,0,0.5), 0 2px 6px rgba(0,0,0,0.7); } .carousel-item .num { position: absolute; z-index: 1; color: #BFE2FF; top: 10px; left: 20px; transition: opacity 0.8s cubic-bezier(0, 0.02, 0, 1); font-size: clamp(20px, 10vw, 50px); font-weight: bold; text-shadow: 0 0 12px rgba(0,0,0,0.5), 0 2px 6px rgba(0,0,0,0.7); } .carousel-item img { width: 100%; height: 100%; object-fit: cover; pointer-events: none; } |
JS:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
let startX = 0 let active = 0 let isDown = false const speedDrag = -0.1 const getZindex = (array, index) => (array.map((_, i) => (index === i) ? array.length : array.length - Math.abs(index - i))) const carousel = document.querySelector('.carousel') const $items = document.querySelectorAll('.carousel-item') let progress = 10 * $items.length / 2 const displayItems = (item, index, active) => { const zIndex = getZindex([...$items], active)[index] item.style.setProperty('--zIndex', zIndex) item.style.setProperty('--active', (index-active)/$items.length) item.style.setProperty('--items', $items.length) } const animate = () => { progress = Math.max(0, Math.min(progress, $items.length * 10)) active = Math.floor(progress/($items.length * 10) * ($items.length-1)) $items.forEach((item, index) => displayItems(item, index, active)) } animate() $items.forEach((item, i) => { item.addEventListener('click', () => { progress = (i/$items.length) * $items.length * 10 + 10 animate() }) }) const handleMouseMove = (e) => { if (!isDown) return const x = e.clientX || (e.touches && e.touches[0].clientX) || 0 const mouseProgress = (x - startX) * speedDrag progress = progress + mouseProgress startX = x animate() } const handleMouseDown = e => { isDown = true startX = e.clientX || (e.touches && e.touches[0].clientX) || 0 } const handleMouseUp = () => { isDown = false } carousel.addEventListener('mousedown', handleMouseDown) carousel.addEventListener('mousemove', handleMouseMove) carousel.addEventListener('mouseup', handleMouseUp) carousel.addEventListener('touchstart', handleMouseDown) carousel.addEventListener('touchmove', handleMouseMove) carousel.addEventListener('touchend', handleMouseUp) |
Первый слайд карусели задается в переменной progress
(в примере это центральный), который рассчитывается по формуле: 10 * кол-во слайдов / 2
За основу взято решение, найденное на codepen.io у пользователя Fabio Ottaviani
Смотрите также:
Слайдер с меняющимися фотографиями и их описанием на чистом CSS
Красивая смена фоновых изображений по клику с использованием WebGL
Несколько вариантов оформления и добавление различных функций к ползунку диапазонов jQuery UI Slider
Добавить комментарий: