The multi-functional slider includes styles and a snippet.
Structure:
js -> slix.js + modules (slix-counter.js, slix-navigation.js slix-pagination.js)
css -> slix-style.css + slix-style-full.css
snippets code add to your vs-code
Get code
// slix-pagination.js
export const initPagination = (slides, slidesField, width, moveSlide) => {
const paginationContainer = document.querySelector('.slix-pagination');
if (!paginationContainer) {
console.error('Pagination container not found');
return;
}
slides.forEach((_, index) => {
const dot = document.createElement('div');
dot.classList.add('dot');
if (index === 0) dot.classList.add('active');
dot.dataset.index = index;
paginationContainer.appendChild(dot);
});
const dots = paginationContainer.querySelectorAll('.dot');
const updatePagination = (slideIndex) => {
dots.forEach(dot => dot.classList.remove('active'));
dots[slideIndex - 1].classList.add('active');
};
dots.forEach(dot => {
dot.addEventListener('click', (e) => {
const index = parseInt(e.target.dataset.index);
moveToSlide(index + 1);
});
dot.addEventListener('touchstart', (e) => {
const index = parseInt(e.target.dataset.index);
moveToSlide(index + 1);
});
});
const moveToSlide = (index) => {
const offset = width * (index - 1);
slidesField.style.transform = `translateX(-${offset}px)`;
moveSlide(index);
updatePagination(index);
};
return updatePagination;
};
/*
Slix slider 1.0.1
Snippet (HTML): slix, slixfull
Author: Mykola Papchenko
*/
// basic style
import "../scss/slix-style.scss";
// full style (Navigation, Pagination, Counter)
// import "../scss/slix-style-full.scss";
// connect the function (Navigation, Pagination, Counter)
// import { initNavigation } from './modules/slix-navigation.js';
// import { initCounter } from './modules/slix-counter.js';
// import { initPagination } from './modules/slix-pagination.js';
const slidesWrapper = document.querySelector('.slix__slider-wrapper');
const slidesField = document.querySelector('.slix__slider-inner');
const width = parseInt(window.getComputedStyle(slidesWrapper)
.width);
let slideIndex = 1;
let offset = 0;
let isDragging = false, startPos = 0, currentTranslate = 0, prevTranslate = 0;
const slides = document.querySelectorAll('.slix__slide');
slidesField.style.width = `${100 * slides.length}%`;
slides.forEach(slide => slide.style.width = `${width}px`);
const moveSlide = (direction) => {
if (typeof direction === 'number') {
slideIndex = direction;
offset = width * (slideIndex - 1);
} else {
if (direction === 'next') {
offset = (offset === width * (slides.length - 1)) ? 0 : offset + width;
slideIndex = (slideIndex === slides.length) ? 1 : slideIndex + 1;
} else {
offset = (offset === 0) ? width * (slides.length - 1) : offset - width;
slideIndex = (slideIndex === 1) ? slides.length : slideIndex - 1;
}
}
slidesField.style.transform = `translateX(-${offset}px)`;
if (typeof updateSlideCount === 'function') {
updateSlideCount(slideIndex);
}
if (typeof updatePagination === 'function') {
updatePagination(slideIndex);
}
};
try {
initNavigation(slides, slidesField, width, moveSlide);
} catch (e) {
console.log("Navigation module not loaded");
}
let updateSlideCount;
try {
updateSlideCount = initCounter();
} catch (e) {
console.log("Counter module not loaded");
}
let updatePagination;
try {
updatePagination = initPagination(slides, slidesField, width, moveSlide);
} catch (e) {
console.log("Pagination module not loaded");
}
const startDrag = (pos) => {
isDragging = true;
startPos = pos;
slidesField.style.transition = 'none';
}
const endDrag = () => {
isDragging = false;
const movedBy = currentTranslate - prevTranslate;
if (movedBy < -width / 4) moveSlide('next');
if (movedBy > width / 4) moveSlide('prev');
setPositionByIndex();
}
const dragMove = (pos) => {
if (isDragging) {
currentTranslate = prevTranslate + pos - startPos;
slidesField.style.transform = `translateX(${currentTranslate}px)`;
}
}
const setPositionByIndex = () => {
prevTranslate = -offset;
slidesField.style.transition = '0.5s all';
slidesField.style.transform = `translateX(-${offset}px)`;
if (typeof updateSlideCount === 'function') {
updateSlideCount(slideIndex);
}
if (typeof updatePagination === 'function') {
updatePagination(slideIndex);
}
}
slides.forEach((slide, index) => {
const img = slide.querySelector('img');
img.addEventListener('mousedown', (e) => startDrag(e.clientX));
img.addEventListener('mousemove', (e) => dragMove(e.clientX));
img.addEventListener('mouseup', endDrag);
img.addEventListener('mouseleave', () => isDragging && endDrag());
img.addEventListener('touchstart', (e) => startDrag(e.touches[0].clientX));
img.addEventListener('touchmove', (e) => dragMove(e.touches[0].clientX));
img.addEventListener('touchend', endDrag);
img.addEventListener('dragstart', (e) => e.preventDefault());
});
// slix-counter.js
const formatNumber = num => num < 10 ? `0${num}` : num;
const total = document.querySelector('#total');
const current = document.querySelector('#current');
const slides = document.querySelectorAll('.slix__slide');
export const initCounter = () => {
const updateSlideCount = (slideIndex) => {
total.textContent = formatNumber(slides.length);
current.textContent = formatNumber(slideIndex);
};
updateSlideCount(1);
return updateSlideCount;
};
// slix-navigation.js
export function initNavigation(slides, slidesField, width, moveSlide) {
const prev = document.querySelector('.slides-prev');
const next = document.querySelector('.slides-next');
let slideIndex = 1;
let offset = 0;
const prevSlide = () => moveSlide('prev');
const nextSlide = () => moveSlide('next');
if (prev) {
prev.addEventListener('click', prevSlide);
} else {
console.error("Previous button not found");
}
if (next) {
next.addEventListener('click', nextSlide);
} else {
console.error("Next button not found");
}
return {
getSlideIndex: () => slideIndex,
getOffset: () => offset
};
}
// slix-pagination.js
export const initPagination = (slides, slidesField, width, moveSlide) => {
const paginationContainer = document.querySelector('.slix-pagination');
if (!paginationContainer) {
console.error('Pagination container not found');
return;
}
slides.forEach((_, index) => {
const dot = document.createElement('div');
dot.classList.add('dot');
if (index === 0) dot.classList.add('active');
dot.dataset.index = index;
paginationContainer.appendChild(dot);
});
const dots = paginationContainer.querySelectorAll('.dot');
const updatePagination = (slideIndex) => {
dots.forEach(dot => dot.classList.remove('active'));
dots[slideIndex - 1].classList.add('active');
};
dots.forEach(dot => {
dot.addEventListener('click', (e) => {
const index = parseInt(e.target.dataset.index);
moveToSlide(index + 1);
});
dot.addEventListener('touchstart', (e) => {
const index = parseInt(e.target.dataset.index);
moveToSlide(index + 1);
});
});
const moveToSlide = (index) => {
const offset = width * (index - 1);
slidesField.style.transform = `translateX(-${offset}px)`;
moveSlide(index);
updatePagination(index);
};
return updatePagination;
};
.slix {
position: relative;
max-width: 800px; // change the width for your project
}
.slix__slide {
width: 100%;
height: 400px; // change the height for your project
}
.slix__slide img {
width: 100%;
height: 100%;
object-fit: cover;
cursor: grab;
}
.slix__slider-wrapper {
overflow: hidden;
}
.slix__slider-inner {
display: flex;
transition: 0.5s all; // set glide speed
}
.slix {
position: relative;
max-width: 800px; // change the width for your project
}
.slix__slide {
width: 100%;
height: 400px; // change the height for your project
}
.slix__slide img {
width: 100%;
height: 100%;
object-fit: cover;
cursor: grab;
}
.slix__slider-wrapper {
overflow: hidden;
}
.slix__slider-inner {
display: flex;
transition: 0.5s all; // set glide speed
}
.slides-prev, .slides-next {
width: 54px;
height: 54px;
border-radius: 50%;
border: none;
background-color: #f0f0f0;
display: flex;
align-items: center;
position: relative;
justify-content: center;
cursor: pointer;
font-size: 0;
}
.slides-prev::before, .slides-next::before {
content: '';
display: inline-block;
width: 14px;
height: 14px;
border-top: 5px solid #333;
border-right: 5px solid #333;
}
.slides-prev::before {
position: absolute;
left: 21px;
transform: rotate(-135deg);
}
.slides-next::before {
right: 21px;
transform: rotate(45deg);
}
.slix-navigations {
display: flex;
justify-content: space-around;
padding: 10px;
}
.slix-counter {
display: flex;
justify-content: center;
color: #fff;
font-size: 24px;
gap: 10px;
}
.slix-pagination {
position: absolute;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 10px;
}
.dot {
width: 16px;
height: 16px;
background-color: gray;
border-radius: 50%;
cursor: pointer;
}
.dot.active {
background-color: white;
}
"Slix": {
"scope": "html",
"prefix": "slix",
"body": [
"<div class="${1:block-name}__slider slix">
<div class="${1:block-name}__wrapper slix__slider-wrapper">
<div class="${1:block-name}__inner slix__slider-inner">
<div class="${1:block-name}__slide slix__slider-slide"></div>
</div>
</div>"
],
"description": "Add basic HTML-code of slider Slix"
},
"Slix Full": {
"scope": "html",
"prefix": "slixfull",
"body": [
"<div class="${1:block-name}__slider slix">
<div class="slix-counter">
<span id="current">00</span>
/
<span id="total">00</span>
</div>
<div class="${1:block-name}__wrapper slix__slider-wrapper">
<div class="${1:block-name}__inner slix__slider-inner">
<div class="${1:block-name}__slide slix__slider-slide"></div>
</div>
</div>
<div class="slix-pagination"></div>
<div class="slix-navigations">
<button type="button" class="slides-prev"></button>
<button type="button" class="slides-next"></button>
</div>
</div>"
],
"description": "Add full HTML-code of slider Slix"
},