Слайдер для сайта на чистом CSS и JavaScript

Слайдер для сайта на чистом CSS и JavaScript

https://itchief.ru/javascript/slider

В этой статье разберём, как подключить на сайт простой адаптивный слайдер ItcSlider, написанный на чистом CSS и JavaScript. Рассмотрим его HTML-структуру и настройку под разные размеры экрана.

Демо слайдера

1. С одним активным слайдом без зацикливания:

Посмотреть

2. С одновременным показом 3 слайдов:

Посмотреть

3. С зацикливанием:

Посмотреть

4. С индикаторами и автоматической сменой слайдов через 7 секунд:

Посмотреть

5. Слайдер для ротации статей (из дополнительных опций – он обновляет своё состояние при изменении размеров окна браузера):

Посмотреть

6. Слайдер в модальном окне:

Посмотреть

7. Несколько слайдеров на странице:

Посмотреть

Другие примеры:

Что такое ItcSlider?

ItcSlider – это легкий адаптивный слайдер для сайта, написанный на чистом JavaScript без каких-либо зависимостей.

Характеристики и особенности слайдера:

  • использует flexbox для вёрстки слайдов;
  • сетка и адаптивность настраивается с помощью CSS;
  • не зависит от каких-либо библиотек JavaScript, например, таких как jQuery, что делает его легким и быстрым;
  • содержит минимально необходимые элементы для навигации: кнопки и индикаторы;
  • имеет режим бесконечной прокрутки, включение которого позволяет сделать слайдер зацикленным;
  • наличие функции автозапуска, для автоматического воспроизведения или иными словами смены слайдов через определённые промежутки времени;
  • перелистывание слайдов смахиванием (swipe) для устройств с сенсорным экраном, а также движением мышью.

Режим зацикленности ItcSlider в отличие от других популярных решений (slick, Splide, Swiper, owlCarousel) реализован по-другому, без создания дублей элементов. То есть, ItcSlider не создаёт копию последнего элемента перед первым и первого – после последнего.

Слайдер ItcSlider – это проект с открытым исходным кодом под лицензией MIT. Его можно использовать совершенно бесплатно. Исходные коды находятся на GitHub: https://github.com/itchief/ui-components/tree/master/slider.

Если нашли какую-то ошибку, то создавайте тикет (issue) на GitHub. Если понравился или помог слайдер, то поддержите его развитие.

Подключение CSS и JavaScript

Исходные коды слайдера расположены на GitHub в репозитории ui-components. В ui-components находится не только этот слайдер, но и другие компоненты пользовательского интерфейса. Данный проект в этом репозитории находится в папке slider.

Слайдер состоит из 2 файлов:

Скачать файлы проекта ui-components с GitHib: master.zip.

После загрузки этих файлов в определённую папку сайта, их нужно подключить к HTML-странице:

<!-- CSS -->
<link rel="stylesheet" href="/assets/css/itc-slider.css">
<!-- JavaScript -->
<script src="/assets/js/itc-slider.js" defer></script>

Здесь файлы itc-slider.css и itc-slider.js были загружены на сайт соответственно в /assets/css/ и /assets/js/.

В теге <script> используется атрибут defer. Он указывает браузеру, что данный скрипт необходимо загрузить в фоне. Используется для ускорения загрузки сайта.

Теперь нам нужно добавить базовый макет ItcSlider в HTML-документ.

HTML-структура

Создание слайдера начинается с добавления его базового макета на страницу:

<div class="itc-slider">
<div class="itc-slider-wrapper">
<div class="itc-slider-items">
<div class="itc-slider-item">
<!-- Контент 1 слайда -->
</div>
<div class="itc-slider-item">
<!-- Контент 2 слайда -->
</div>
<div class="itc-slider-item">
<!-- Контент 3 слайда -->
</div>
</div>
</div>
<!-- Кнопки для перехода к предыдущему и следующему слайду -->
<button class="itc-slider-btn itc-slider-btn-prev"></button>
<button class="itc-slider-btn itc-slider-btn-next"></button>
</div>

Этот базовый HTML-код содержит 3 карточки (.itc-slider-item) и кнопки навигации (itc-slider-btn).

Теперь каждую карточку (.itc-slider-item) необходимо определённым образом разметить. Она может содержать как просто какой-то текст или изображение, которое будет использоваться для его представления. Это может быть как просто изображение, так и сложный HTML-фрагмент.

Если кнопки для перехода к предыдущему и следующему элементу не нужны, то их можно удалить из разметки:

<button class="itc-slider-btn itc-slider-btn-prev"></button>
<button class="itc-slider-btn itc-slider-btn-next"></button>

Добавление индикаторов осуществляется посредством вставки в .itc-slider следующего кода:

<div class="itc-slider">
...
<ol class="itc-slider-indicators">
<!-- data-slide-to="0" – для перехода к 1 слайду -->
<li class="itc-slider-indicator" data-slide-to="0"></li>
<!-- data-slide-to="1" – для перехода к 2 слайду -->
<li class="itc-slider-indicator" data-slide-to="1"></li>
<!-- data-slide-to="2" – для перехода к 3 слайду -->
<li class="itc-slider-indicator" data-slide-to="2"></li>
</ol>
</div>

При этом количество элементов .itc-slider-indicator должно соответствовать количеству слайдов.

Инициализация слайдера

Теперь, когда у нас имеется HTML-код, нам нужно его инициализировать с помощью функции new ItcSlider().

Это можно сделать 2 способами:

1. Посредством добавления атрибута data-slider="itc-slider" к корневому элементу слайдера:

<div class="itc-slider" data-slider="itc-slider">
...
</div>

В этом случае, скрипт itc-slider.js как только DOM страницы будет построена, всё сделает это сам. А именно инициализирует эти элементы как ItcSlider.

Выполняет itc-slider.js это внутри своего кода посредством вызова статического метода ItcSlider.createInstances(). При выполнении этот метод создаёт экземпляры класса ItcSlider для всех элементов на странице, имеющих атрибут data-slider="itc-slider".

2. Через JavaScript. Осуществляется это посредством вызова статического метода getOrCreateInstance и передачи ему в качестве аргумента селектора или DOM-элемента, в который заключён слайдер:

// .slider – селектор для выбора элемента, который нужно активировать как ItcSlider
ItcSlider.getOrCreateInstance('.slider');

Но эту команду необходимо выполнить только после готовности DOM и загрузки скрипта itc-slider.js:

// после готовности DOM
document.addEventListener('DOMContentLoaded', () => {
ItcSlider.getOrCreateInstance('.slider');
});

Внутри getOrCreateInstance() проверяет создан ли экземпляр класса ItcSlider для указанного элемента. Если нет, то вызывает конструктор класса ItcSlider для создания нового экземпляра.

Обратите внимание, что при передаче getOrCreateInstance() селектора, будет инициализирован только первый элемент, соотвествующий ему.

Инициализировать все элементы с определённым классом можно так:

// после готовности DOM
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('.slider').forEach((el) => {
ItcSlider.getOrCreateInstance(el);
});
});
Параметры

Настройка слайдера осуществляется с помощью следующих параметров:

  • autoplay – включает автоматическую смену слайдов (по умолчанию false);
  • interval – определяет интервал в миллисекундах между автоматической сменой слайдов (по умолчанию 5000);
  • loop – указывает нужно ли зацикливать или нет показ слайдов (по умолчанию true);
  • refresh – включает перерасчет размеров слайдера при изменении ширины HTML документа (по умолчанию true);
  • swipe – разрешает листать слайды свайпом и перемещением курсора мыши при зажатой левой кнопки мыши (по умолчанию true).

При инициализация слайдер через data-slider="itc-slider" парметры можно также передать через data-атрибуты. Например:

<div class="itc-slider" data-slider="itc-slider" data-loop="true" data-autoplay="true" data-interval="7000">

Такой способ инициализации слайдера и передачи ему параметров приведён почти во всех примерах, приведённых выше за исключением демки, в котором он отображается в модальном окне. Здесь он активируется посредством JavaScript.

В JavaScript коде передача параметров выполняется в формате объекта, который нужно указать в качестве второго аргумента:

ItcSlider.getOrCreateInstance('.itc-slider', {
loop: false, // без зацикливания
swipe: false // без свайпа
});
Настройка количества слайдов

Регулировка количества слайдов, показывающихся в области видимости ItcSlider выполняется посредством CSS:

.itc-slider-item {
flex: 0 0 100%;
}

Так как слайды являются flex-элементами, то рекомендуется для установки ширины использовать свойство flex. Здесь мы установили в качестве ширины значение 100%. Таким образом у нас на экране будет виден только один .itc-slider-item.

Если предпочитаете использовать свойство width вместо flex-basis, то тогда установку ширины можно осуществлять следующим образом:

.itc-slider-item {
flex: 0 0 auto;
width: 100%;
}

Для показа 2 элементов нужно в качестве flex-basis установить значение 50%:

.itc-slider-item {
flex: 0 0 50%;
/* или */
/* flex: 0 0 auto; */
/* width: 50%; */
}

Эти стили можно добавить в свой CSS-файл или непосредственно на страницу, используя тег <style>.

Адаптивную настройку количества одновременно показывающихся слайдов можно осуществить посредством медиа-запросов:

/* на маленьких устройствах 1 слайд */
.itc-slider-item {
flex: 0 0 100%;
}

/* на средних экранах (ширина больше 768px) 2 слайда */
@media (min-width: 768px) {
.itc-slider-item {
flex: 0 0 50%;
}
}

/* на больших экранах (ширина больше 1200px) 3 слайда */
@media (min-width: 1200px) {
.itc-slider-item {
flex: 0 0 33.3333333333%;
}
}
Отступы между слайдами

Добавление отступов между слайдами осуществляется с помощью gap:

.itc-slider-items {
--gap: 1rem;
gap: var(--gap);
}

Здесь CSS-переменную gap мы создали не просто так. Она нам также понадобится при установке ширины.

Рассмотрим примеры, когда ширину item мы устанавливаем в процентом отношении. Например, при показе 2 активных элементов:

.itc-slider-item {
flex: 0 0 calc(50% - var(--gap) / 2);

В этом случае из ширины одного item нужно вычесть половину gap.

Для отображения в области видимости 3 слайдов, у нас будут видны 2 отступа. Следовательно, ширину одного item необходимо уменьшить на var(--gap) * 2 / 3:

.itc-slider-item {
flex: 0 0 calc(33.3333333333% - var(--gap) * 2 / 3);
}

Для четырёх:

.itc-slider-item {
flex: 0 0 calc(25% - var(--gap) * 3 / 4);
}

Для одного активного слайда уменьшать ширину не нужно. Так как на экране в этом случае не показывается gap, он будет только виден при пролистовании:

.itc-slider-item {
flex: 0 0 100%;
}

Если ширину .itc-slider-item вы задаёте в абсолютных единицах (px, rem и так далее), то тогда её следует рассчитать самостоятельно с учётом gap, либо использовать, как и в примерах приведённых выше функцию calc():

.itc-slider {
width: 700px;
}

.itc-slider-items {
--gap: 30px;
gap: var(--gap);
}

.itc-slider-item {
flex: 0 0 335px;
/* или */
/* flex: 0 0 calc(350px - var(--gap) / 2); */
}
Методы

После инициализации слайдера, получить доступ к его экземпляру ItcSlider можно посредством статического метода getInstance:

// получаем DOM-элемент слайдера
const sliderElem = document.querySelector('.slider');
// получаем его экземпляр класса ItcSlider
const slider = ItcSlider.getInstance(sliderElem);

Также экземляр ItcSlider возвращает метод getOrCreateInstance:

// получаем DOM-элемент слайдера
const sliderElem = document.querySelector('.slider');
// получаем его экземпляр класса
const slider = ItcSlider.getOrCreateInstance(sliderElem);

Но, getOrCreateInstance не только возвращает объект, но и инициализирует указанный элемент, если он до этого не был активирован, как ItcSlider.

После получения экземпляра класса ItcSlider нам будут доступны следующие методы:

  • autoplay.start() – начать автопроизведение;
  • autoplay.stop() – остановить автопроизведение;
  • slideNext() – перейти к следующему слайду;
  • slidePrev() – перейти к предыдущему слайду;
  • slideTo(index) – перейти к слайду, порядковый номер которого соответствует index;
  • reset() – сбросить состояние слайдера к изначальному;
  • dispose() – удаляет обработчики событий и другие элементы слайдера, добавленные при его инициализации.
// получим DOM-элемент слайдера
const sliderElem = document.querySelector('.slider');
// получим экземпляр класса ItcSlider и сохраним его в переменную slider
const slider = ItcSlider.getInstance(sliderElem);
// остановим автоматическую смену слайдов
slider.autoplay.stop();
// перейдём к предыдущему слайду
slider.prev();
// сбросим состояние слайдера к первоначальному
slider.reset();
Устройство и некоторые принципы работы слайдера

Как вы уже знаете слайдер ItcSlider в качестве HTML разметки по умолчанию имеет следующую структуру:

<div class="itc-slider">
<div class="itc-slider-wrapper">
<div class="itc-slider-items">
<div class="itc-slider-item">
<!-- Контент 1 слайда -->
</div>
<div class="itc-slider-item">
<!-- Контент 2 слайда -->
</div>
<div class="itc-slider-item">
<!-- Контент 3 слайда -->
</div>
</div>
</div>
<!-- Кнопки -->
<button class="itc-slider-btn itc-slider-btn-prev"></button>
<button class="itc-slider-btn itc-slider-btn-next"></button>
</div>

Корневой элемент этого компонента имеет класс itc-slider. В нём расположены:

  • .itc-slider-wrapper – используется в качестве обёртки;
  • .itc-slider-btn – кнопки, с помощью которых мы можем перейти соответственно к предыдущему и следующему слайду.

CSS код слайдера очень простой, как мы уже отмечали выше, он находится на GitHub в файле itc-slider.css. В нём нет ничего особенного, здесь мы детальнее остановимся на коде JavaScript.

Сдвиг слайдов в нужном направлении выполняется с помощью приватного метода #move(). Эта метод в зависимости от значения приватного свойства this.#state.direction выполняет изменение положения элемента .itc-slider-items в определённом направлении посредством CSS-трансформации.

Организация зацикленности слайдера выполняется также посредством CSS-трансформаций, но уже не контейнера .itc-slider-items, а посредством самих элементов .itc-slider-item.

Перед тем как понять какой элемент .itc-slider-item и куда нужно переместить, необходимо сначала знать текущее положение и значение трансформации каждого из них. Осуществляется это посредством свойств this.#state.els.index, this.#state.els.order и this.#state.els.translate. Они соответственно содержат порядковый номер или индекс слайда, его текущего положение или порядок, и его значение трансформации. Изначально эти свойства в this.#state.els добавляются на этапе активирования слайдера:

// this.#state.elListItem – это элементы .itc-slider-item
this.#state.elListItem.forEach((el, index) => {
this.#state.els.push({ el, index, order: index, translate: 0 });
});

Экстремальные значения этих данных содержатся также в свойствах: this.#state.exOrderMin, this.#state.exOrderMax, this.#state.exItemMin, this.#state.exItemMax, this.#state.exTranslateMin и this.#state.exTranslateMax.

Обновление значений этих свойств выполняется посредством вызова метода #updateExProperties() в необходимых местах программы, а их трансформация для организации зацикленности осуществляется при вызове метода #balanceItems().

Автоматическая смена слайдов через определённые промежутки времени осуществляется с помощью функции setInterval. Она просто вызывает метод #move() через количество миллисекунд, указанное в this.#config.interval:

this.#state.intervalId = setInterval(() => {
this.#state.direction = 'next';
this.#move();
}, this.#config.interval);

Выключение автоматической смены слайдов, например, осуществляется когда пользователь перемещает курсор в область внутрь границ слайдера. В коде это осуществляется так:

#onMouseEnter() {
this.#autoplay('stop');
}
#onMouseLeave() {
this.#autoplay();
}

Кроме этого, автоматическая смена слайдов выключается, когда страница переходит в фоновый режим, например, при переключении на другую вкладку.

В коде это выполнено с использованием события visibilitychange следующим образом:

#onVisibilityChange() {
if (document.visibilityState === 'hidden') {
this.#autoplay('stop');
} else if (document.visibilityState === 'visible' && this.#config.loop) {
this.#autoplay();
}
}

В слайдере также реализована функция, которая позволяет пересчитать слайдер при изменении ширины viewport. Выполняется это с помощью вызова функции _refresh.

#onResize() {
window.requestAnimationFrame(this.#reset.bind(this));
}

Добавления обработчиков в коде осуществляется через forEach:

Object.keys(this.#state.events).forEach((type) => {
if (this.#state.events[type][2]) {
const el = this.#state.events[type][0];
const fn = this.#state.events[type][1];
el.addEventListener(type, fn);
}
});

Report Page