I know im stupid about this, but i cant simply figure out what is called or how to best approach this.
I want to create a slider that has one focus image in the middle and other images extrudes out in the sides. like presented in the image here
And of course when you click left or right it should go in that direction.
My approach so far is to make inline-flex and then make 5 divs where in each are an image and the center one is larger etc. and so on outwards.
But im still curious on how to make this work the right way.
I have prepared an example that should meet all your conditions: swiping, scaling, prev/next buttons, click on card
const gallery = document.querySelector('.gallery')
const cardWrappers = document.querySelectorAll('.card-wrapper')
const prevButton = document.querySelector('.prev-button')
const nextButton = document.querySelector('.next-button')
let selectedIndex = 2
// move card position depend on selected index
const applyCardPositions = () => {
cardWrappers.forEach((cardWrapper, index) => {
const workingIndex = selectedIndex <= 2
? index + (2 - selectedIndex)
: index - selectedIndex + 2
cardWrapper.dataset.index = index
cardWrapper.dataset.position = Math.abs(index - selectedIndex)
cardWrapper.style.left = `${ workingIndex * 20 }%`
})
}
applyCardPositions()
// helpers
const decreaseSelectedIndex = () => {
if (selectedIndex > 0) {
selectedIndex -= 1
applyCardPositions()
}
}
const increaseSelectedIndex = () => {
if (selectedIndex < cardWrappers.length - 1) {
selectedIndex += 1
applyCardPositions()
}
}
// button events
prevButton.addEventListener('click', decreaseSelectedIndex)
nextButton.addEventListener('click', increaseSelectedIndex)
// click on card
cardWrappers.forEach(cardWrapper => {
cardWrapper.addEventListener('click', (e) => {
selectedIndex = parseInt(cardWrapper.dataset.index)
applyCardPositions()
})
})
// swipe events
startPos = [0, 0]
gallery.addEventListener('pointerdown', (e) => {
startPos = [e.clientX, e.clientY]
})
gallery.addEventListener('pointerup', (e) => {
const endPos = [e.clientX, e.clientY]
// threshold
if (Math.abs(endPos[0] - startPos[0]) < 50) {
return
}
if (endPos[0] < startPos[0]) {
increaseSelectedIndex()
}
if (endPos[0] > startPos[0]) {
decreaseSelectedIndex()
}
})
.gallery {
position: relative;
width: 100%;
height: 240px;
background: #eee;
overflow: hidden;
}
.gallery .card-wrapper {
position: absolute;
top: 0;
left: 0;
width: 20%;
height: 90%;
top: 5%;
transition: .5s ease-out;
}
.gallery .card {
display: flex;
align-items: center;
justify-content: center;
font-size: 30px;
width: 90%;
margin-left: 5%;
height: 100%;;
background: #ddd;
user-select: none;
transition: .5s ease-out;
}
.gallery [data-position="0"] .card {
background: #aaa
}
.gallery [data-position="1"] .card {
transform: scale3d(.9, .9, .9);
}
.gallery [data-position="2"] .card {
transform: scale3d(.8, .8, .8);
}
.gallery [data-position="3"] .card {
transform: scale3d(.7, .7, .7);
}
.prev-button,
.next-button {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
background: #fff;
color: #333;
width: 30px;
height: 30px;
border-radius: 50%;
cursor: pointer;
left: 10px;
top: calc(50% - 15px);
user-select: none;
}
.next-button {
left: auto;
right: 10px;
top: calc(50% - 15px);
}
<div class="gallery">
<div class="card-wrapper">
<div class="card">A</div>
</div>
<div class="card-wrapper">
<div class="card">B</div>
</div>
<div class="card-wrapper">
<div class="card">C</div>
</div>
<div class="card-wrapper">
<div class="card">D</div>
</div>
<div class="card-wrapper">
<div class="card">E</div>
</div>
<div class="card-wrapper">
<div class="card">F</div>
</div>
<div class="prev-button">
<
</div>
<div class="next-button">
>
</div>
</div>