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

Слайдер для сайта на чистом CSS и JavaScript
Содержание:
  1. Демо слайдера
  2. Что такое ItcSlider?
  3. Подключение CSS и JavaScript
  4. HTML-структура
  5. Инициализация слайдера
  6. Параметры
  7. Настройка количества слайдов
  8. Отступы между слайдами
  9. Методы
  10. Устройство и некоторые принципы работы слайдера
  11. Комментарии

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

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

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

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

Посмотреть

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

Слайдер с одновременным отображением 3 слайдов без зацикливания

Посмотреть

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

Адаптивный слайдер с зацикливанием

Посмотреть

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

Слайдер с автоматической сменой слайдов и индикаторами

Посмотреть

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

Слайдер для ротации статей или постов, который может изменять своё состояние при изменении размеров окна браузера

Посмотреть

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

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

Посмотреть

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

Несколько слайдеров на чистом CSS и JavaScript на странице

Посмотреть

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

Что такое 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-странице:

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-структура

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

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-фрагмент.

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

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

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

HTML
<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" к корневому элементу слайдера:

HTML
<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-элемента, в который заключён слайдер:

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

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

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

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

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

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

JavaScript
// после готовности 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-атрибуты. Например:

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

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

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

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

Настройка количества слайдов

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

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

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

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

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

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

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

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

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

CSS
/* на маленьких устройствах 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:

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

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

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

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

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

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

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

Для четырёх:

CSS
.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():

CSS
.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:

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

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

JavaScript
// получаем 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() – удаляет обработчики событий и другие элементы слайдера, добавленные при его инициализации.
JavaScript
// получим DOM-элемент слайдера
const sliderElem = document.querySelector('.slider');
// получим экземпляр класса ItcSlider и сохраним его в переменную slider
const slider = ItcSlider.getInstance(sliderElem);
// остановим автоматическую смену слайдов
slider.autoplay.stop();
// перейдём к предыдущему слайду
slider.prev();
// сбросим состояние слайдера к первоначальному
slider.reset();

Устройство и некоторые принципы работы слайдера

Как вы уже знаете слайдер 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>

Корневой элемент этого компонента имеет класс 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 добавляются на этапе активирования слайдера:

JavaScript
// 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:

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

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

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

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

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

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

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

JavaScript
#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);
  }
});

Комментарии: 579

ralph
ralph

Здравствуйте! вопрос вкратце, как полностью отменить/удалить всё действие слайдера?

По дизайну слайдер появляется только на мобильном разрешении, соответственно на пк его ещё не должно быть

я сделал логику, чтобы при открытии страницы сначала определялось, какая ширина у пользователя

и, если маленькое, то появлялся слайдер

если симулировать такое через f12 на компе и запустить сайт сначала на маленьком разрешении, потом увеличить, то слайдер остаётся

само собой я понимаю, что нужно его как то отключить/удалить, но как?

я думал, что для этого и нужен slider.dispose()

но это ничем не помогло, - на элементах остаются style атрибуты в тегах, которые до сих пор просчитываются js`ом

Александр Мальцев
Александр Мальцев

Привет! Может метод dispose() как-то не так использовали. Он как раз для этого и предназначен, он удаляет обработчики и некоторые стили:

const sliderElem = document.querySelector('.itc-slider');
if (sliderElem) {
  const slider = ItcSlider.getInstance(sliderElem);
  if (slider) {
    slider.dispose();
  }
}

Но, если нужно чтобы это работало при изменении размеров страницы, то нужно использовать ResizeObserver или событие resize, и написать определённый код в обработчике.

Можно поступить вообще просто и инициализировать слайдер только при определённом разрешении. Например:

const mediaQuery = window.matchMedia('(min-width: 768px)');
if (mediaQuery.matches) {
  // инициализируем слайдер
}
ralph
ralph

window.matchMedia всё равно нужно будет отслеживать потом, так что не подходит

Но, если нужно чтобы это работало при изменении размеров страницы, то нужно использовать
ResizeObserver или событие resize, и написать определённый код в обработчике.
я как раз и сделал resize на window:
if (checkWidthWindow()) { // первая проверка (когда страница только открывается)
    ItcSlider = await loadSliderScript();
    sliderActive = ItcSlider.getOrCreateInstance($sliderDom);
    getRemoveTransformNone(false, $sliderItems, $sliderList); // рассказал дальше в комментарии че это
  }

  window.addEventListener('resize', async (e) => {
    if (checkWidthWindow()) {  // проверка ширины окна (true - если оно маленькое)
      if (sliderActive === null) {  // проверка, что слайдера ещё нет
        if (ItcSlider === null) {  // проверка, что модуль со слайдером ещё не был загружен
          ItcSlider = await loadSliderScript();
        }
        sliderActive = ItcSlider.getOrCreateInstance($sliderDom);  // инициализация
        getRemoveTransformNone(false, $sliderItems, $sliderList);
      }
    } else {
      if (sliderActive !== null) {  // если слайдер есть
        sliderActive.dispose();
        sliderActive = null;
        getRemoveTransformNone(true, $sliderItems, $sliderList);
      }
    }
  })
ralph
ralph

getRemoveTransformNone() - это собственно моё решение данной ситуации :)

там я просто классы на дом-элементы навешиваю с transform: none !important и всё; без этой функции у меня не работает (приложил картинку с голубыми кляксами)

пропадает последняя карточка из за того, что на ней наложены стили transform (вторая картинка)

Bиталий
Bиталий

Здравтвуйте, Александр!

Большое спасибо за отличный слайдер и детальное объяснение!

Извините за наивный вопрос...

При просмотре на компрьютере - все отлично, но при просмотре с телефона слайдер становится существенно шире экрана. Как это можно поправить? Какой парамент отвечает за вписывание слайдера в экран телефона?
Александр Мальцев
Александр Мальцев

Привет! Скорее всего что-то со стилями напутали. Такого нет параметра, всё определяется с помощью CSS.

Dmytro Bazaluk
Dmytro Bazaluk

Добрый вечер. Александр, не могу найти закономерность, настроил слайдеры на странице, все работают правильно, но есть нюанс, слайдер со смещенными кнопками за пределы слайдера плохо отзывается на нажатие кнопок управления next и prev. Когда кнопки на стандартном месте, все работает безупречно, но как только идет смещение за пределы слайдера, начинается магия.

![](/assets/images/storage/1cdf98356f7bcc8468291afaf972a05d.png)

При нажатии на кнопку Next - иногда слайд идет вперед, иногда назад, если делать паузу в нажатии, то точно пойдет слайд вперед.

При нажатии на кнопку Prev - иногда слайд один проворачивается назад, а иногда сразу пачка из 2-3 слайдов.

![](/assets/images/storage/93534a4b31d6274b7a8f703f1eea9e36.png)

А когда даже просто в браузере позиционирую их на стандартные места, все начинает работать нормально.

Подскажите, можно ли как-то решить этот вопрос, или сделать отдельную мини функцию для кнопок, чтобы их позиционирование не влияло на слайдер.

Александр Мальцев
Александр Мальцев

Привет! Скорее всего что-то не так сделали. Кнопки можно поместить куда угодно, но в этом случае их действие нужно прописывать самостоятельно.

Например:
<button type="button" class="btn-prev">Prev</button>
<button type="button" class="btn-next">Next</button>
Код на JavaScript:
const slider = ItcSlider.getInstance(document.querySelector('.itc-slider'));
document.querySelector('.btn-prev').addEventListener('click', () => {
  slider.slidePrev();
});
document.querySelector('.btn-next').addEventListener('click', () => {
  slider.slideNext();
});
flocker
flocker

Здравствуйте, столкнулся с проблемой, не могу нормально заменить slideritem-content на картинки, изображение занимает большее или меньшее пространство при width="100%" height="100%, подскажите как действовать ?

Александр Мальцев
Александр Мальцев

Привет! Не знаю, что подсказать, так как не вижу что делаете. Обычно, если нужна конкретная помощь, то лучше показать свой результат на codepen.io или других подобных сервисах.

Если картинки разного размера, то, чтобы их привести в порядок можно использовать width, height и object-fit (например: object-fit: cover).
Alldoesntmatter
Alldoesntmatter

Скажите пожалуйста, можно ли вывести 2 и более слайдеров в ряд на странице. Пробовал flex и всякое другое - не вышло сделать нормально, то один слайдер с середины страницы получается, а второй в край упирается, то ещё что-то.

Александр Мальцев
Александр Мальцев

Тут необходимо просто обычно разметить. Вот пример с использованием flex.

localbody
localbody

Здравствуйте!

подскажите как использовать метод slideTo()

const slider = ItcSlider.getInstance(document.querySelector('.itc-slider')) // - получил слайдер

slider.slideTo(3) // нет видимого перехода к слайду №3, но если нажать кнопку PREV или NEXT слайды начинают двигаться от слайда №3

localbody
localbody

вопрос снят! у меня при клике слайдер из 4-х видимых слайдов превращался в фулскрин с одним видимым слайдом - сделал slider.reset(); slider.slideTo(3); и сработало !!!

Александр Мальцев
Александр Мальцев

Добрый день! Рад, что всё получилось.

Jerzylets
Jerzylets

Здравствуйте, Александр!

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

Uncaught ReferenceError: ItcSlider is not defined
А если инициализирую в самом файле itc-slider.js, то вылезает ошибка
Uncaught TypeError: Cannot read properties of null (reading 'querySelector')

Инициализирую с помощью

document.addEventListener('DOMContentLoaded', () => {

ItcSlider.getOrCreateInstance('.slider');

});

Использую сборщик.

Александр Мальцев
Александр Мальцев

Добрый день! Скорее всего просто где-то запутались. Слайдер нужно инициализировать после подключения class ItcSlider { ... }, а когда выполняете ItcSlider.getOrCreateInstance('.slider'); должен быть отрисован уже на странице элемент .slider.

alex_uni
alex_uni

Здравствуйте, Александр! Спасибо за ваш слайдер!

Единственное с чем столкнулся - это в консоли получаю набор уведомлений
Added non-passive event listener to a scroll-blocking событие <some>. Consider marking event handler as 'passive' to make the page more responsive.
Можете с этим помочь?

(прикладываю скрин)

уведомления
Александр Мальцев
Александр Мальцев

Добрый день! Рад, что нравится! Внёс изменения на GitHub. Проверяйте.

alex_uni
alex_uni

Отлично! Работает! Спасибо!

Альберт
Альберт

Александр, добрый день! Подскажите, как блок с индикаторами (.itc-slider-indicators) сделать ниже картинок? Спасибо!

Александр Мальцев
Александр Мальцев

Привет! Для этого блока установлено абсолютное позиционирование. Его можно сделать ниже, например, посредством изменения свойства bottom:

.itc-slider-indicators {
  bottom: -36px;
}
Atomoswolf
Atomoswolf

Александр, добрый день! Хочу обернуть картинки слайдера в ссылки, но столкнулся с такой проблемой. Теперь при попытке свайпа сразу происходит переход по ссылке. Хотелось бы переходить только при явном клике на слайд, а если происходит просто перетаскивание, соответственно, никуда не переходить. Подскажите, как это лучше сделать?

Александр Мальцев
Александр Мальцев

Добрый день, поправил этот момент. Обновлённая версия на GitHub.

Atomoswolf
Atomoswolf

Спасибо большое, теперь работает как надо!

amriddin
amriddin

Здравствуйте Александр. Можно ли сделать навигацию слайдеру по фото?

Александр Мальцев
Александр Мальцев

Добрый день. Посмотрите этот пример.

alex_uni
alex_uni

Александр, здравствуйте.

В конце статьи у вас ссылка на слайдер отступами между элементами, который основан на обновленной библиотеке версии 1.0.1 и он не работает.

В консоли горит ошибка:

main.js?ver=13.04.2023:398 Uncaught TypeError: Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'.

и ссылается на эту строку:

// получаем gap между слайдами
const gap = parseFloat(getComputedStyle(this.#state.elItems).gap) || 0;
Как я понимаю это связано с тем, что у this.#state нулевой elItems ?
Александр Мальцев
Александр Мальцев

Добрый день! Поправил пример.

alex_uni
alex_uni

Спасибо!

А если добавить снизу переключатели то, текущая версия слайдера умеет, как предыдущая выделять активным только один буллет при переходе, а не по количеству выводимых слайдов?
Александр Мальцев
Александр Мальцев

Открыл ссылку на https://jsfiddle.net/, всё выделяет. Скриншот присоединил.

alex_uni
alex_uni

Александр, вы меня неправильно поняли. Я имел ввиду количество активных буллетов.

По вашей ссылке сейчас 2 активных при двух слайдах, а в предыдущей версии выделялся 1 при тех же двух слайдах.

Логика в том, что, если я хочу выводить одновременно 5 слайдов при имеющихся 6, то у меня сразу 5 буллетов из 6 будут активными, вместо одного.

Александр Мальцев
Александр Мальцев

Понятно, но это только правки в код вносить.

Tikhon
Tikhon

Добрый день! Хочу сразу отметить, что очень крутой и удобный слайдер сделали). До этого пользовался другими версиями вашей разработки, багов не попадалось. Сейчас решил воспользоваться обновленной версией, но ловлю ровно два бага у себя.

  1. Если выбрать любой другой слайд, кроме первого(который активен по умолчанию) и начать изменять ширину экрана, то при первом же сайзе слайда, он переключается на этот первый(это работает как в "-", так и в "+" изменения ширины экрана).
  2. При включенном loop: true (либо по умолчанию), при том же скролле экрана по ширине, последний слайд постоянно накладываеться на активный.

Настройки:

document.addEventListener('DOMContentLoaded', () => {
        ItcSlider.getOrCreateInstance('.itc-slider', {
          loop: true,
          swipe: false,
          refresh: false,
          autoplay: false,
          interval: 6000
        });
      });
Возможно это все воссоздается только у меня, но у меня пока не получилось это пофиксить самостоятельно)
seric
seric

Подскажите как установить автопрокрутку для слайдера из 5 примера (для ротации статей).

Александр Мальцев
Александр Мальцев

Для включения автопрокрутки установите атрибуту data-autoplay значение true:

<div class="itc-slider" data-autoplay="true" data-interval="5000" data-loop="true" data-refresh="true" data-slider="itc-slider">
  ...
</div>

Установка интервала через которое нужно менять слайдер выполняется посредством data-interval. В этом примере 5 секунд (5000 миллисекунд).

seric
seric

Спасибо!

seric
seric

Не подскажите как можно сделать что бы он вертикально пролистывал или это проблематично?

Александр Мальцев
Александр Мальцев

Не проблематично, просто время на это нужно потратить. Если образно, то там где width, теперь нужен height. Ну и translate переделать по Y, может потребуется что-то ещё. Где-то в комментариях, если не изменяет память, что-то такое уже делал.

seric
seric

Ок, спасибо! Пролистаю комментарии может найду

Александр Мальцев
Александр Мальцев

Вот ссылка на комментарий. Первый что нашёл через «Найти на странице», может ещё какие-то примеры есть.

seric
seric

Спасибо!

Deathnikk
Deathnikk

Подскажите, как включить autoplay для слайдера, не могу разобраться. JS особо не знаю, поэтому не понимаю куда вставлять и как применять различные методы и функции. Поэтому если не сложно, объясните пошагово, что нужно делать.

Александр Мальцев
Александр Мальцев

Можно без использования JavaScript. Для этого к HTML-элементу, в который заключён слайдер, необходимо добавить атрибут data-autoplay со значением true:

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

Если вы инициализирует слайдер через JavaScript, то можно через параметры:

ItcSlider.getOrCreateInstance('.itc-slider', {
  autoplay: true, // включаем autoplay
});

После инициализации уже только с использованием методов:

// получаем HTML-элемент .itc-slider
const sliderElem = document.querySelector('.itc-slider');
// получаем экземпляр ItcSlider
const slider = ItcSlider.getInstance(sliderElem);
// включаем autoplay
slider.sutoplay.start();
serega-pte
serega-pte

Доброго времени суток.

Кто может у себя перепроверить поведение слайдера, не могу понять это я напартачил или баг?

Ституация следующая:

На десктопе начинаем пользоваться слайдером, пролистываем пару раз, затем сворачиваем окно браузера (квадратик возле иконки закрытия браузера), слайдер перестраивается по новой под текущий размер экрана и вот после этого перелистывание начинает работать не правильно, с каждым шагом отрезается часть изображения. Такое же поведение повторяется если сначала попользоаться слайдером в маленьком окне, а потом развернуть на весь экран. Отладчиком вставал reset() вызывается, вроде бы все четко должно быть, но нет...

Спасибо.

serega-pte
serega-pte

Кажется я нашел причину.

Дело в том, что изначально я отображаю по 4 слайда, а при уменьшении окна браузера 3.

В этот момент проблема и вылазит.

Но опять же не пойму, если смотреть в отладчике, то эта часть кода срабатывает:

#onResize() {

window.requestAnimationFrame(this.#reset.bind(this));

}

Разве не должно быть перерисовки и сброса слайдера?

Александр Мальцев
Александр Мальцев

Здравствуйте! Посмотрю в ближайшее время почему не происходит перерисовки.

Александр Мальцев
Александр Мальцев

Для этого создан параметр refresh:

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

Если инициализируете с помощью JavaScript, то так:

ItcSlider.getOrCreateInstance('.itc-slider', { refresh: true });
serega-pte
serega-pte

Добрый день.

Инициализировал с помощью html (data-refresh="true").

Работает не коректно.

Вы пробывали сначала выводить 4 элемента в слайдер, а потом перевести браузер в оконный режим, что бы было например 3 элемента в слайдере?

Если перевести в оконный режим и начать растягивать окно браузера, то все перерисовывается.

Проблема возникает имнно при сворачивании в оконный режим.
Александр Мальцев
Александр Мальцев

Добрый день! Пробывал по-всякому. Не получается воспроизвести проблему. Если имеется возможность, то запишите видео как это получается. Может в каком-то конкретном браузере?

Александр Мальцев
Александр Мальцев

Получилось воспроизвести проблему. Просто в слайдер, который у меня лежит на машине, содержит несколько исправлений и в нём этой проблемы нет. А который находится в доступе их содержит.

serega-pte
serega-pte

Тогда с нетерпением жду обновление на гитхабе.

Спасибо Вам.
Александр Мальцев
Александр Мальцев

Да, сразу выложу, как-то доделаю некоторые улучшения, связанные со свайпом.

Александр Мальцев
Александр Мальцев

Код обновил, можете пробовать.

amriddin
amriddin

Добрый день. Как выключить слайдер с помощью js?

Александр Мальцев
Александр Мальцев

Добрый! А что значит выключить? Есть метод dispose().

amriddin
amriddin

А как воспользоваться?

Делаю вот так:
ItcSlider.dispose(el)
Выдает ошибку:
TypeError: ItcSlider.dispose is not a function
Александр Мальцев
Александр Мальцев

Нужно так:

const slider = ItcSlider.getInstance(el);
slider.dispose();
amriddin
amriddin

Спасибо за ответ, но это тоже не сработало. Мне нужно сразу отключить несколько слайдеров, если ширина экрана больше 767px. Вот код:

// Make some content slider on mobile devices
const sliders = []
function makeSlider() {
  if (window.innerWidth < 767) {
    if (sliders.length === 0) {
      document.querySelectorAll('.run-on-mobile').forEach((el) => {
        const slider = ItcSlider.getOrCreateInstance(el, {
          loop: true,
          autoplay: true
        })
        sliders.push(slider)
      })
    }
    return
  }
  sliders.forEach((el) => {
    el.dispose()
  })
}

Выдает ошибку:

Uncaught TypeError: el.dispose is not a function

Подскажите пожалуйста где ошибка. Ссылка на проект: https://github.com/a-davlatov/eplex

Александр Мальцев
Александр Мальцев

Вроде всё правильно, должно работать.

Для примера сделал немного по-другому (перейти):
document.addEventListener('DOMContentLoaded', () => {
  new ResizeObserver(() => {
    if (window.matchMedia('screen and (max-width: 767px)').matches) {
      document.querySelectorAll('.run-on-mobile').forEach((el) => {
        el.querySelectorAll('.itc-slider-btn').forEach((el) => {
          el.style.removeProperty('display');
        });
        ItcSlider.getOrCreateInstance(el, {
          loop: true,
          autoplay: true
        });
      });
    } else {
      document.querySelectorAll('.run-on-mobile').forEach((el) => {
        const slider = ItcSlider.getOrCreateInstance(el);
        slider.dispose();
        el.querySelectorAll('.itc-slider-btn').forEach((el) => {
          el.style.display = 'none';
        });
      });
    }
  }).observe(document.body);
});
Кроме этого немного обновил исходные коды, коль руки дошли, в основном области именования классов. Попробуйте приведённое решение. Если не получится, тогда уже более подробно посмотрим коды в вашем проекте.
amriddin
amriddin

Вставил ваш код, выдает ту же ошибку. Дело в том что у вас в примере слайдеры изначально инициализированы а у меня нет. У меня они инициализируются при ширине меньше 767 и наоборот должны обратно выключаться при ширине больше 767. Инициализировать получается а выключать нет.

Александр Мальцев
Александр Мальцев

Не знаю, разницы никакой. Изначально они инициализируются или потом. Пример: перейти

amriddin
amriddin

Заработало, ошибка не исчезла но скрипт работает. Спасибо большое!!!

Муругов Никита
Муругов Никита

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

ссылка из примера (эта версия работает):
https://itchief.ru/examples/libs/ui-components/itc-slider.a71ba218.js
Ссылка на гит, с которого если скачать работать не будет:
https://github.com/itchief/ui-components/blob/master/slider/itc-slider.js
Причину не выяснил, временно приходится использовать слайдер из примера
Муругов Никита
Муругов Никита

Может быть я что то не так сделал, но просто изменение файла сработало, код инициализации не трогал, и не менял.

Автор кстати этого слайдера крутой чел, между разными слайдерами твой самый осязаемо понятный, и в исходники можно зайти, и по этим статьям, очень круто, спасибо тебе

Александр Мальцев
Александр Мальцев

Привет! Спасибо за отзыв)

На GitHub была ошибка связанная с gap, а точнее когда он не задан. Сейчас поправил, должно быть всё отлично)
Shved
Shved

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

Ну прям очень надо, а только из-за этого от чудо слайдера отказываться не охото!

Заранее спасибо!!!
Shved
Shved

Решил тем, что каждому элементу дал border в цвет фона, но костыльно.

если будет вариант вставить margin, будет круто)
Александр Мальцев
Александр Мальцев

Привет! Добавил в расчёт ширины gap. Как им пользоваться подробно описал в статье. Пример добавлю позже.

localbody
localbody

Привет!

Слайдер - божественный, но я столкнулся с "глюком": если слайдер генерировать автоматически и там будет только один слайд, то если не указать data-loop="false" получается листает слайд + две пустышки
localbody
localbody

опишу подробнее: есть задача сделать "зацикленный" слайдер с товарами, но если в выбранной категории только один товар, то и в слайдере один слайд.

Александр Мальцев
Александр Мальцев

Привет! Если нужно генерировать динамически, то нужно активировать слайдер с помощью JavaScript.

Для этого, например хранить HTML-структуру слайда будет в <template>:
<template id="slider-template">
  <div class="itc-slider">
    <div class="itc-slider__wrapper">
      <div class="itc-slider__items"></div>
    </div>
    <button class="itc-slider__btn itc-slider__btn_prev"></button>
    <button class="itc-slider__btn itc-slider__btn_next"></button>
  </div>
</template>
Брать слайды будем, например, из массива items. Если количество элементов меньше 3, то будем их клонировать с помощью JavaScript, чтобы их количество было не меньше 3. Например, так (открыть демку):
const items = [
  { img: '/examples/pens/itc-slider/images/1.jpg' },
  { img: '/examples/pens/itc-slider/images/2.jpg' },
  // ...
];
const sliderTemplate = document.querySelector('#slider-template');
const containerElem = document.querySelector('.container');
const sliderContainerElem = sliderTemplate.content.cloneNode(true);
// если нужно добавить клоны слайдов, когда их меньше 3
if (items.length < 3) {
  items.push(items[0]);
  items.push(items[1]);
}
const sliderItems = items.map((item) => {
  return `<div class="itc-slider__item"><img src="${item.img}" alt=""></div>`;
});
sliderContainerElem.querySelector('.itc-slider__items').innerHTML = sliderItems.join('');
containerElem.append(sliderContainerElem);
const sliderElem = document.querySelector('.itc-slider');
if (sliderElem.querySelectorAll('.itc-slider__item').length > 1) {
  ItcSlider.getOrCreateInstance(sliderElem, {
    autoplay: false,
    interval: 5000,
    loop: true,
    refresh: true,
    swipe: true
  });
} else {
  sliderElem.querySelectorAll('.itc-slider__btn').forEach((item) => {
    item.classList.add('itc-slider__btn_hide');
  });
}
localbody
localbody

супер! спасибо - покрутим!!!

uralyanka
uralyanka

Всем привет!

Столкнулась с проблемой: не скролится страница в мобиле при прикосновении в области слайдера. На какой параметр обратить внимание? Где поправить? Заранее благодарю.
uralyanka
uralyanka

временным решением оказалось отключение свайпа - работает перелистывание сейчас по кнопкам.

Александр Мальцев
Александр Мальцев

Привет! Внёс изменения в «itc-slider.js», теперь должно работать.

Герман
Герман

Доброго времени суток! Не получилось обернуть картинки в ссылки, поэтому сделал кнопки-картинки и думал, что решил все проблемы, но с телефона переход по ссылкам не работает, в чем может быть дело? Заранее благодарю за ответ.

Герман
Герман

Узнал, что и ссылки и кнопки не работают из-за swipe: true. Если сделать false, то ссылки будут работать.

Александр Мальцев
Александр Мальцев

Доброго дня! Внёс изменения в код, попробуйте.

Roman_V
Roman_V

Добрый день!

При добавлении слайдера и добавлении bootstrap класса к -> class="itc-slider container", на первый слайд налазит последний (прикреплен скрин). Так же добавил css , но это не влияет на данную проблему -

.itc-slider {
  position: relative;
  max-height: 450px;
  margin-top: 30px;
  overflow: hidden;
}
Как это можно пофиксить? Ссылка на код : https://codepen.io/VodopianovRoman/pen/rNZLwew

Описание картинки

Александр Мальцев
Александр Мальцев

Добрый день! Попробуйте просто обернуть слайдер в контейнер:

<div class="container">
  <div class="itc-slider container" data-slider="itc-slider" data-loop="true" data-autoplay="true" data-interval="5000">...</div>
  ...
</div>
Ganesha604
Ganesha604

Добрый день. Подскажите, пожалуйста, как решить такую проблему: при добавлении любой фотографии она не четкая? И никак не найти размер, который бы ее четко показывал

Александр Мальцев
Александр Мальцев

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

Raib364
Raib364

Добрый день. Подскажите, как можно сделать слайдер примерно как на картинке? Чтобы центральный слайд был больше, а соседние за ним. Описание картинки

deviashin
deviashin

Шалом!

Замечательный урок, спасибо! При использовании адаптивного кода из статьи (со слов: "Адаптивно настроить количество одновременно показывающихся слайдов можно посредством медиа-запросов:") есть проблема: на
flex: 0 0 100%; max-width: 100%;
при нажатии на кнопки "влево/вправо" слайды прыгают через один. На других разрешениях всё отлично. По сути, это уже мобильное устройство и там эти кнопки следует вообще скрывать, оставляя свободу свайпам по экрану, но интересно, почему так происходит?
deviashin
deviashin

Добавлю, если добавить медиа на 996рх, оставив там 33.3%, а на 1200рх сделать 25% тоже ломается, перепрыгивает через два. Да и проверил, от количества слайдов это не зависит.

НО! При автоматической смене слайдов (loop: true), слайды сами щёлкаются по одному, как и положено.

Свайпы работают правильно, что на ПК (Chrome. Версия 110.0.5481.100) в отладчике, что через GH Pages с двух разных смарфонов.

Дело только в кнопках при ручном управлении через обычную ПК версию сайта (но при медиа ниже 768рх).
deviashin
deviashin

Не инициализируйте кнопки через JS, пацаны, они оказывается еще конструктору нужны...

Александр Мальцев
Александр Мальцев

Привет! Не знаю, может у вас ещё какие-то действия привязаны на странице, которые и вызывают дополнительный клик по кнопкам. Кроме этого внес некоторые изменения в код файла itc-slider.js, который находится на GitHub. Попробуйте с ним.

tanyah
tanyah

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

#overlay {
  position: fixed;
  top: 0;
  left: 0;
  display: none;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.65);
  z-index: 1050;
  -webkit-animation: fade .6s;
  -moz-animation: fade .6s;
  animation: fade .6s;
  overflow: auto;
}
<script>
  document.addEventListener('DOMContentLoaded', () => {
    const scrollbar = document.body.clientWidth - window.innerWidth + 'px';
    let elSlider;
    document.querySelector('[data-target="modal"]').addEventListener('click', (e) => {
      e.preventDefault();
      document.body.style.overflow = 'hidden';
      document.querySelector('#modal').style.marginLeft = scrollbar;
      document.querySelector('#modal').classList.add('modal-open');
      if (elSlider === undefined) {
        elSlider = ItcSlider.getOrCreateInstance('.itc-slider', {loop: false});
      } else {
        elSlider.refresh();
      }
    });
    document.querySelector('[data-target="close"]').addEventListener('click', (e) => {
      e.preventDefault();
      document.body.style.overflow = 'visible';
      document.querySelector('#modal').style.marginLeft = '0px';
      document.querySelector('#modal').classList.remove('modal-open');
      elSlider._autoplay('true');
    });
  });
</script>
</head>
<body>
<div class="container">
   <div id="overlay">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <h3 class="modal-title"> </h3>
          <button class="close" title="Закрыть" onclick="document.getElementById('overlay').style.display='none';">Х</button>
        </div>
        <div class="modal-body">
          <div class="itc-slider"><!-- Слайдер (начало) -->
            <div class="itc-slider__wrapper">
              <div class="itc-slider__items">
                <div class="itc-slider__item">
                  <img src="" width="800" height="675" alt="lorem">
                </div>
                <div class="itc-slider__item">
                  <img src="" width="800" height="675" alt="lorem">
                </div>                        
                   </div>
            </div>
            <button class="itc-slider__btn itc-slider__btn_prev"></button>
            <button class="itc-slider__btn itc-slider__btn_next"></button>
          </div><!-- Слайдер (конец) -->
        </div>
      </div>
    </div>
  </div>
</div>
<script type="text/javascript">
  var delay_popup = 1000;
  setTimeout("document.getElementById('overlay').style.display='block'", delay_popup);
</script>
</body>
</html>
Александр Мальцев
Александр Мальцев

Добрый день! Для более детальной помощи лучше выкладывать решение на https://codepen.io/ или каком-нибудь другом подобном сервисе, а не в виде кода. Тут нужно сделать аналогичные действия, то есть после того как вы уже показали модальное окно (пример):

setTimeout(() => {
  document.getElementById('overlay').style.display='block';
  // тут инициализировать слайдер
}, delay_popup);
Иван Александрович
Иван Александрович

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

Александр Мальцев
Александр Мальцев

Здравствуйте! Тогда просто инициализируйте слайдер после открытия модального окна.

Иван Александрович
Иван Александрович

ItcSlider.createInstances();

Эту строчку я так понял нужно вписать в момент открытия модального окна?
Olgakorr
Olgakorr

Здравствуйте. Подскажите пожалуйста как поменять направление движения слайдера на противоположное, сейчас при нажатии на кнопки он движется слева на право, а нужно справа на лево. И соответственно что б стрелки загорались в нужном направлении отображая возможность или не возможность перелистывания.

Александр Мальцев
Александр Мальцев

Добрый день! Не совсем понял вопроса. При нажатие левой кнопки - слева направо, а правой - справа налево. Как нужно?

Olgakorr
Olgakorr

Прокрутка идет по логике слева старт справа в бесконечности нужное количество слайдов. Нужно наоборот что б крайний правый элемент был стартовым, а бесконечность слайдов добавлялась слева. Как для иврит версии, они пишут справа на лева и слайдер должен работать тоже справа налево. Справа начало

Arbusx
Arbusx

Здравствуйте.

ItcSlider.getOrCreateInstance('.slider', { loop: true });

Код не работает в мобильном браузере "UC Browser". Просто молча не работает. Отладку по usb не получается сделать. Как инспектировать тоже не знаю.

Arbusx
Arbusx

Здравствуйте. Не могу заставить работать кнопки мне слайдера. Вы написали

const slider = ItcSlider.getOrCreateInstance('.slider', {loop: true});
document.querySelector('.button_prev').addEventListener('click', function() {
  slider.prev();
});

Но у меня выпадает ошибка Uncaught TypeError: slider.prev is not a function at HTMLButtonElement.<anonymous>

Александр Мальцев
Александр Мальцев

Здравствуйте! Да, там в скрипте не то значение возвращается. Исправил код на Github. Ссылка на пример.

Arbusx
Arbusx

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

Anton
Anton
Добрый день. Во-первых, огромное спасибо! Очень понятный и доступный слайдер для тех кто начал только изучать js. А теперь к проблеме. При событии onclick в любом месте слайдера у меня пропадает ul список из меню. Пробовал менять название класса, пытался вообще обработчик отключить в скрипте, но никак не могу понять в чем проблема. Причем менюшка никак не связана со слайдером. Можете подсказать в какую сторону вообще копать? Спасибо.
Anton
Anton
Разобрался. Дело было не в бобине. Спасибо Вам за труд.
Александр Мальцев
Александр Мальцев
Рад что все получилось!
Anton
Anton
Подскажите пожалуйста. Пользователи safari жалуются что не работает слайдер. Я проверил, такое ощущение что он не стилей не видит не js. Хотя в хроме, опере, иджи все работает отлично.
Александр Мальцев
Александр Мальцев
Под Safari должно работать. А какая версия и какие ошибки в консоли?
Anton
Anton
Смотрели на сафари 15 версии. в консоли пусто. не реагирует даже на вывод в консольлог. И поплыли стили.
Возможно это и у меня где-то ошибка. Заметил что некоторые стили css не отображаются во всем документе. Но почему тогда работает в других браузерах.
Александр Мальцев
Александр Мальцев
На 15 версии должно работать. Может попробовать обновить страницу: Cmd (⌘) + R.
Алексей Валерьевич Алексеев
Алексей Валерьевич Алексеев
Благодарю еще раз за Ваш труд и этот отличный слайдер! Взял его за основу квиза на сайт. Но есть вопрос — можно ли как то реализовать progress bar? пытался прикрутить добавление класса к шкале прогресса при смене класса активного слайда

$(window).load(function() {
if($(".step0").hasClass(«itc-slider__item_active»)) {
$('.progress__bar').addClass('step0-pb');
}else{
$('.progress__bar').removeClass('step0-pb');
};
});

но активный класс меняется динамически. Может быть посоветуете как реализовать добавление класса к прогресс бару в зависимости от номера слайда?
ia
ia
сложно ли делать адаптивную верстку для первого слайдера? не дошла до js, пока что пытаюсь научиться адаптивной верстке
Александр Мальцев
Александр Мальцев
Делается аналогично обычному блоку.
Matve
Matve
Здравствуйте, спасибо за хороший слайдер. Но у меня вопрос, на который я так и не смог найти ответ. Как сделать свои кнопки переключения слайдов вне самого слайдера?
Александр Мальцев
Александр Мальцев
Добрый день! Спасибо!
Для этого можно использовать методы next и prev:
const slider = ItcSlider.getOrCreateInstance('.slider');
slider.next(); // следующий слайд
slider.prev(); // предыдущий слайд
Marta
Marta
здравствуйте! спасибо за классный слайдер.
подскажите, пожалуйста, каким образом можно изменить цвет стрелок навигации? нужен не белый, а синий.
Александр Мальцев
Александр Мальцев
Добрый день! Спасибо за отзыв!
Цвет стрелки определяется в CSS:
.slider__control[data-slide="prev"]::before {
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E");
}
Вместо fff в fill='%23fff' укажите нужный цвет, например #0d6efd: fill='%230d6efd'.
Okean
Okean
Здравствуйте Александр. Спасибо за отличный слайдер. Подскажите, как сделать так что бы при изминении экрана слайдер не возвращался на первый слайд и можно было продолжать листать его с места остановки (например со второго/третьего и тд. слайда).
Оставляю код моего слайдер здесь — jsfiddle.net/Okean/dxrntjhv/12/
Спасибо.
zepplin
zepplin
Здравствуйте Александр. Может подскажете. Применил слайдер № 5, подключен бутстрап 5 и card. Не могу сделать чтобы карточки в слайде имели одну высоту. Добавление в CSS .h-100 (height:100% important) проблему не решает.
Александр Мальцев
Александр Мальцев
Здравствуйте! Вы указали 100%, но 100% это от чего. В этом случае вы должны слайдеру задать какую-то фиксированную высоту. Если этого сделать нельзя, тогда нужно вычислять это с помощью JavaScript.
Михаил
Михаил
Не работает кнопка переключения назад, скопировал все как в статье. В чем может быть проблемма?
Александр Мальцев
Александр Мальцев
Выложите всё что у вас получилось на CodePen.
Volodia
Volodia
Готов задонатить сколько скажете, чтобы сделали нормальный пример инициализации нескольких параллельных слайдеров на странице с использованием скрипта:
github.com/itchief/ui-components/blob/master/itc-slider/itc-slider.min.js
И с использованием верстки, где у slider-item есть родительский slider-items и кнопки листания реализованы через:
<a href="#" class="slider__control" data-slide="prev"></a>
<a href="#" class="slider__control" data-slide="next"></a>
Потому что люди (в т.ч. я) просим это, а нам примеры даете наподобие:
itchief.ru/examples/lab.php?topic=javascript&file=chiefslider-example-6
где реализация вообще другая
Александр Мальцев
Александр Мальцев
Да, бывает привожу так, что нужно сделать что-то подобное, как например в этом примере. Не всегда на всё хватает время.
Для ребрединга в рамках пакета ui-components слайдер переименовал в itc-slider. Также изменил перерасчёт размеров элементов, теперь он выполняется в пикселях. Кроме этого, добавил возможность активирования слайдера через data-атрибуты.
Дополнительно добавил пример с несколькими слайдерами на одной странице. Для улучшения HTML семантики слайдера поменял кнопки на тег <button>. Пока всё что успел.
Volodia
Volodia
Спасибо! Заработало.

Посильно задонатил)

Кстати, не хватает более очевидной кнопки «Задонатить» в хэдере и футере. Пришлось вспоминать, где видел ссылку «Поддержать проект» в самой статье.

Пользуюсь вашим слайдером чуть меньше года и все полностью нравилось. В т.ч. внедрил его на одном ооооочень крупном агрегаторе автозапчастей РФ, когда работал там. Но не хватало вот именно этой штуки с поддержкой нескольких слайдеров на странице. И теперь она, наконец, появилась.

Может опытным фронтендерам эта просьба покажется смешной, но я дизайнер-верстальщик и в гробу видал Жабаскрипт и тем более танцевать с бубном вокруг него) Однако приходится иногда и с ним ковыряться при работе.
Александр Мальцев
Александр Мальцев
Спасибо!
Svetlachok_m
Svetlachok_m
Здравствуйте, не могу понять почему элементы слайдера становятся друг под другом, а не в линию. Скопировала все с сайта.
.slider__wrapper {
  overflow: hidden;
}
.slider__item {
  height: 410px;
  display: inline-block;
  justify-content: center;
  align-items: center;
  flex: 0 0 33.3333333333%;
  max-width: 33.3333333333%;
}
itchief.ru/assets/uploadify/5/4/3/5439d54bac48ca42825e5a0b28d3b04e.png
Александр Мальцев
Александр Мальцев
Здравствуйте! Скорее всего js-скрипт не подключили.
Ара
Ара
Здравствуйте.
Подскажите, как правильно инициализировать несколько слайдеров ChiefSlider с параметрами и своими кнопками?

<div class="btn-wrapper">
	<button class="btn-prev"><span class="_icon-arrow-left"></span></button>
	<button class="btn-next"><span class="_icon-arrow-right"></span></button>
</div>
Реализовал так, но кнопки переключения не работают
// инициализация слайдеров

  var elms = document.querySelectorAll(".slider");
  for (var i = 0, len = elms.length; i < len; i++) {
    // инициализация elms[i] в качестве слайдера
    const slider = new ChiefSlider(elms[i], {
      loop: true ,
      autoplay: true ,
      interval: 4000 ,
      swipe: true,
      refresh: true,
    });

    var btnprev = document.querySelectorAll(".btn-prev");
    for (var i = 0; i < elements.length; i++) {
      btnprev[i].onclick = function () {
        slider.prev();
      };
    }

    var btnnext = document.querySelectorAll(".btn-next");
    for (var i = 0; i < elements2.length; i++) {
      btnnext [i].onclick = function () {
        slider.next();
      };
    }
  }
Александр Мальцев
Александр Мальцев
Добрый день! Можно например так:
<div class="slider" id="slider-1">...</div>
<div class="slider" id="slider-2">...</div>

<button class="btn-prev" data-slider="#slider-1">...</button>
<button class="btn-next" data-slider="#slider-1">...</button>
<button class="btn-prev" data-slider="#slider-2">...</button>
<button class="btn-next" data-slider="#slider-2">...</button>

<script>
  const sliders = {};
  document.querySelectorAll('.slider').forEach((slider) => {
    sliders[slider.id] = new ChiefSlider(slider, {
      loop: true,
      autoplay: true,
      interval: 4000,
      swipe: true,
      refresh: true,
    });
    document.querySelector(`[data-slider="#${slider.id}"].btn-prev`).onclick = () => {
      sliders[slider.id].prev();
    }
    document.querySelector(`[data-slider="#${slider.id}"].btn-next`).onclick = () => {
      sliders[slider.id].next();
    }
  });
</script>
Ара
Ара
Спасибо, Александр. Оперативно показали верное решение.
Вы случайно не обучаете? мне бы фронтенд подтянуть. Мне кажется что вы реальный практик в отличии от многих кто продает видеокурсы.
Александр Мальцев
Александр Мальцев
Пожалуйста! Думал уже об этом, но, когда точно за это возьмусь пока не знаю. Можно только пока личные консультации. В видеокурсах я так понимаю много базовых вещей дают, а потом как решать реальные задачи, используя этот набор знаний наверно просто не понятно. Такие трудности? Или основы JavaScript тоже нужны? Пока просто изучаю целевую аудиторию, чтобы понять в каком направлении двигаться. Что больше интересует, где проблемы? Буду рад, если вы расскажите более подробно.
Ара
Ара
Вариант с личной консультацией тоже интересен. Верно понимаете, часто не понятно как решать реальные задачи, используя набор знаний. Лично я основы JavaScript знаю (функции, циклы, массивы, многомерные массивы, DOM-дерево), если стоит вопрос решить простую задачу с использованием скажем конструкции «switch» — могу решить, а если задача например: при прокрутке до определенного блока, должно происходить анимация и при возвращении к этому блоку анимация должна снова воспроизводиться, могу решать просидев пол дня и то скорее будет куча ошибок и проблемы связанные с решением второй части задачи чтобы анимация повторялась при возвращении к данному блока. Думаю что понимание основ javascript может отличаться, и наверное будет правильно что то типо такого подхода:
1) С помощью теста определить уровень теоретических и практических знаний
2) Исходя из уровня теоретических и практических знаний применять соответствующую программу обучения
3) Аттестация
4) Снова тест на определение поднялся ли уровень теоретических и практических знаний у ученика
Личными консультациями наверное много учеников взять не получится. Я думаю что нужно найти правильное соотношение самостоятельного обучения используя материал (видео или текст) + наставничество.
Александр Мальцев
Александр Мальцев
Спасибо за развернутый ответ! Буду думать в этом направлении.
igorexa343
igorexa343
Добрый день, при попытке добавить gap между slider__item или присвоить им боковой margin, последний элемент залезает на первый как на скрине
Александр Мальцев
Александр Мальцев
Добрый день! Конечно, так просто не получится, в коде происходит вычисление размеров элементов. Для этого нужно что-то дорабатывать. Можно использовать padding, так как они добавляют только внутренние отступы и размер элементов не изменяют.
Anna
Anna
Добрый вечер! Подскажите, пожалуйста, подключила слайдер, он в общем работает, но периодически возникает такая ошибка:
chief-slider.js:61 Uncaught TypeError: Cannot read properties of undefined (reading 'offsetWidth')
at new ChiefSlider (chief-slider.js:61:36)
at HTMLDocument.(index.html?_ijt=qjfji07b1on0k735ism0p3o0pj&_ij_reload=RELOAD_ON_SAVE:505:24)

как ее можно устранить? спасибо
Александр Мальцев
Александр Мальцев
Здравствуйте! Не знаю, нужно посмотреть там, где вы его используете. Если есть, то дайте ссылку на страницу.
Александр Мальцев
Александр Мальцев
Так вам нужно инициализировать слайдер после того как вы вставили контент на страницу, который получили с использованием fetch:
content.forEach((key) => { /* ... */ });
new ChiefSlider('.slider', { loop: true });
Anna
Anna
спасибо!
Anna
Anna
Подскажите, пожалуйста, еще такой вопрос, при добавлении второго слайдера в аналогичном блоке работает только один, можно ли активировать оба слайдера?
Александр Мальцев
Александр Мальцев
Дайте им, например, разные id. А затем в одном месте активируйте первый слайд, а в другом – второй.
// ...
new ChiefSlider('#slider-1', { loop: true });
// ...
new ChiefSlider('#slider-2', { loop: true });
not4sale
not4sale
Александр, прошу прощения, можно код целиком для разных слайдеров html+js. Не выходит самостоятельно. Спасибо за ваши разъяснения!
Александр Мальцев
Александр Мальцев
Есть же пример с двумя слайдерами и в статье:

itchief.ru/examples/lab.php?topic=javascript&file=slider-07

Используйте его.
vlad
vlad
Здравствуйте!

У меня на странице есть карточки товаров. Я написал скрипт для того что бы при нужной ширине экрана они превращались в слайдер. Скрипт просто добавляет класс .slider к основному контейнеру при достижении нужной ширины и инициализирует слайдер. Структура слайдера стандартная. Вот только после срабатывания необходимо обновить страницу что бы слайдер заработал. То же самое, если вернуть ширину к исходному размеру. Можно ли как то сделать это без перезагрузки страницы?

Код скрипта:
if ($(window).width() <= 768 ) {
$('.servises__cards').addClass('slider')
new ChiefSlider('.servises__cards');
}
Александр Мальцев
Александр Мальцев
Так, правильно, этот код выполняется только один раз. Вам нужно использовать обработчик событие resize:
window.addEventListener('resize', (e) => {
  // ...
});
SoHard
SoHard
При переключении фото, переходит в начало страницы и никакого переключения не происходит
Александр Мальцев
Александр Мальцев
Сделайте пример на codepen.io или каком-нибудь другом сервере и дайте ссылку. Так не знаю что подсказать.
Inokent
Inokent
Очень симпатичные демо! Жаль, что подключить слайдер так и не удалось. Подскажите, те, у кого получилось: прописать в html фрагмент слайдера (
и все, что внутри), добавить и подключить файлы slider.js и slider.css недостаточно? Нужные еще какие-то дополнительные файлы/код? Потому что все это проделано, но слайдер отображается как выстроенные в огромный ряд фото, и даже кнопки пролистывания не работают, страница по ним перезагружается и все
Александр Мальцев
Александр Мальцев
Скачайте с Github, там есть примеры и можно всё посмотреть. Кроме подключения файлов нужно ещё инициализировать элемент как слайдер. Например, если корневой элемент слайдера имеет id="slider-1", то так:
new ChiefSlider('#slider-1');
Кирилл
Кирилл
Огромное спасибо за Ваш ресурс. Этот слайдер с настройками — зе бест. Спасибо за ответы и разжевывание. Желаю здоровья, удачи и успехов во всех начинаниях.

Вопрос такой. Скачал этот слайдер
itchief.ru/examples/lab.php?topic=javascript&file=chief-slider-05
Сайт на wordpress, использую bootstrap5, плагины и т.п.
Никак не могу понять почему слайдер ведет себя очень странно.
При обновлении страницы блок с индикаторами
<ol class="slider__indicators">
находится чуть ниже положенного примерно на 50px. При долистывании до последнего слайда он встает на место и дальше уже можно листать куда угодно — стоит как вкопанный. Сравнивал стили для предпоследнего и последнего слайда — одинаковые. Фактически при просмотре последнего слайда меняется высота всей ленты со слайдами, но в стилях никакого упоминания о высоте не нашел. Слайды все одинаковые — из примера взятые.

Сделал костыль — повесили обработчик на событие загрузку и ресайз — вычисление высоты первого блока «slider__item-container» и присваивание в стилях этой высоты блоку «slider__items». Костыль работает, но хочется какого то понимания из-за чего так происходит. Еще раз спасибо за такой сайт.
Кирилл
Кирилл
Обновление именно CTR+F5 ломает высоту, при обычном обновлении все ОК.
Кирилл
Кирилл
Сам спросил — сам ответил.

Проблема была в том, что в шаблоне в коде img указана по умолчанию ширина 350, высота 250, а сами картинки в шаблоне имеют размер 500х281, что при масштабировании до ширины 350 дает 350х197, пока вся лента не просмотрится (прогрузится) браузер не знает какие там картинки в реальности будут — может быть действительно 350х250. Поэтому держит высоту ленты в 250, потом когда вся лента просмотрится, то высота ленты меняется на реальную в 197.
То есть нужно просто было в шаблоне кода поменять размер картинки на 350х197 и все стало работать как надо.
Александр Мальцев
Александр Мальцев
Рад, что всё получилось.
tanteno
tanteno
Александр, ChiefSlider — быстрый и удобный слайдер.
Одни вопрос: Как анимировать с помощью СSS-анимации (с помощью transform и ключевых кадров) контент слайдеров, т.е. содержимое div, заключенное в class=«slider__item». На слайдере Bootstrap 4 эта анимация работает, а вот на слайдере ChiefSlider та же анимация на том же сайте, к сожалению, нет. Вернее, при первоначальной загрузке страницы на первом слайдере движение происходит, а потом нет, ни на других слайдах, ни при повторе первого. Возможно ли реализовать такую анимацию контента на ChiefSlider? Если да, подскажите, как это сделать?
Спасибо, за слайдер и Вашу работу!
uglenpish
uglenpish
Добрый день, подскажите как переместить кнопки управления в другой контейнер. Можно это сделать без js
Александр Мальцев
Александр Мальцев
Здравствуйте! Если можете это сделать с помощью CSS, то JavaScript добавлять не нужно.
Вячеслав
Вячеслав
Александр, как устранить ошибку Pagespeed “Пассивные прослушиватели событий не используются для улучшения производительности при прокрутке”? Перешёл с SimpleAdaptiveSlider на эту весию и стала вылезать ошибка в консоли


Александр Мальцев
Александр Мальцев
Поправлю эту ошибку в ближайшее время.
ltybc
ltybc
Еще раз привет! Замечательный слайдер с широким функционалом. Но остался вопрос, как вынести счётчик слайдов за пределы .slider?
Александр Мальцев
Александр Мальцев
Привет! Спасибо. А разве такое решение не подойдёт.
Вячеслав
Вячеслав
Александр, помогите ради бога! Пытаюсь изменить стиль смены слайдеров, но ничего не получается, т.к. не силён в JS. Нашёл вот такой простой пример codepen.io/SitePoint/pen/KzjpGj, но как его прикрутить к Вашему слайдеру — ума не приложу. Я думаю и другим было бы это очень интересно. И было бы совсем классно, если бы можно было включать эту функцию при инициализации слайдера, типа «autoplay: true». Это позволило бы здорово разнообразить дизайн слайдеров на сайте и не устанавливать разные слайдеры ради одного эффекта.
Александр Мальцев
Александр Мальцев
Сейчас не готов что-то изменять, но эту задачу запишу и подумаю, как её очень красиво реализовать. Если интересно, то могут написать ответ, когда это решение будет выполнено.
Cougar
Cougar
Здравствуйте у меня такой вопрос, почему когда я вставляю фото в
1

то у меня белый экран? может фото битое? Даже из гуггла ссылкой, тоже белый экран слайдера.
Cougar
Cougar
<div class="slider" data-slider="chiefslider">
      <div class="slider__container">
        <div class="slider__wrapper">
          <div class="slider__items">
            <div class="slider__item">
              <div class="slider__item-container">
                <div class="slider__item-content">1</div>
              </div>
            </div>
В
<div class="slider__item-content">1</div>
Вставляется фото с указанием пути?
Cougar
Cougar
Я вставляю таким образом
<div class="s-1.jpg"></div>
Но результат белый экран))
Cougar
Cougar
Извините я нашер решние
<img class="slider__content_img" src="images/s-7.jpg" 
Просто про
<img class="slider__content_img" src="Путь вашего фото
Никто не сказал))0
Александр Мальцев
Александр Мальцев
Рад, что всё получилось.
Djiraf
Djiraf
Здравствуйте, Александр. Как и все благодарные люди выше хочу выразить тысячекратное спасибо за такой продукт, функционал которого зашкаливает. Я во всем практически разобрался просто читая вашу статью и ответы под комментариями. Не понял только, как при наличии 2х слайдеров задать им разные картинки. Объясните хлебушку (мне), пожалуйста.
Александр Мальцев
Александр Мальцев
Здравствуйте! Спасибо за отзыв. Очень рад, что продукт нравится.
Чтобы не объяснять сделал этот пример.
Djiraf
Djiraf
Чувствую себя лохом)
Спасибо, дело было в том, что я пытался сделать все с помощью backgroud .D
Александр Мальцев
Александр Мальцев
Можно и с помощью background, но тогда картинки нужно прописывать в CSS (пример).
Aleks
Aleks
Добрый день, Александр. Возможно ли вынести счётчик слайдов за пределы слайдера (.container) и чтобы он оставался фиксированным?
Александр Мальцев
Александр Мальцев
Привет! Можно создать элемент (.slider-counter) и написать простенький JavaScript для этого (пример):
<div class="slider-counter" style="font-size: 20px; text-align: center; padding: 15px;"></div>
...
<script>document.addEventListener('DOMContentLoaded', function () {
    const slider = new ChiefSlider('.slider', {
      loop: true
    });
    const sliderItems = document.querySelector('.slider__items');
    const sliderCounter = document.querySelector('.slider-counter');
    const updateCounter = () => {
      const index = parseInt(sliderItems.querySelector('.slider__item_active').dataset.index) + 1;
      const count = sliderItems.querySelectorAll('.slider__item').length;
      sliderCounter.textContent = `${index}/${count}`;
    }
    updateCounter();
    sliderItems.addEventListener('transitionend', updateCounter);
  });
</script>

Aleks
Aleks
Ага, спасибо.
Подскажи ещё такой момент: как навесить эффект появления FadeInDown на появление цифры при клике на prev или next. В данном варианте сделать это средствами css вряд ли получится. Я не смог разобраться. Подскажи, буду очень признателен.
Web
Web
Здравствуйте. Отличный слайдер, единственное, что интересует это как по клике на dots перелистывать больше одного слайдера?

Допустим, что у меня есть 14 слайдов. Вывожу на страницу 7. Должно появиться два дотса. При клике на второй прокручивает слайдер к следующим 7 слайдеров
Александр Мальцев
Александр Мальцев
Здравствуйте! Данный слайдер листает по одному слайду. Для того чтобы листать по 7 нужно изменить JavaScript код. Без изменения кода можно создать 2 слайда и каждый из них разметить еще на 7, тогда будет прокручиваться сразу по 7.
Kirill
Kirill
Добрый день, Александр.
Спасибо вам за труд. Очень здорово, когда вы подробно всё объясняете.

У меня задача:
использовать слайдер только в мобильной версии, начиная с планшетной версии он не используется, но переиспользуется его html-код(DOM-узлы).

При ресайзе окна браузера и при ресайзе в режиме разработчика DevTools, слайдер оставляет после себя transform: translate(300px)(который прописывается через script) для каждого item списка. В итоге на планшетной версии элементы item списка смещены за границы экрана. Проблема мною решается через изменение transform через script при увеличении ширины окна начиная с tablet-width.

Проблема:
При открытии сайта в мобильной версии, а затем ресайзе на планшетную версию все норм. Но если затем снова ресайз до мобильной версии, то слайдер отображается правильно и НЕ работает, не листает. Если перезагрузить страницу(получается пересоздать слайдер), то все работает.

Вопрос:
1. Как с самого начала при ресайзе с мобильной версии на планшетную, отключить все изменения внесенные скриптом слайдера на его элементы(имеется ввиду transform)?
2. Если же развивать дальнейший путь моего решения, то как перезапустить слайдер при ресайзе с планшетной версии на мобильную один раз?
Narek
Narek
Здравствуйте, спасибо огромное за скрипт, на WP поставил без проблем и боли
Но заметил что на ios не работает анимация смены слайдов, может и вообще на всех телефонах
Aleks
Aleks
Привет, Александр. Взял табы на чистом CSS из Вашего примера на сайте и пытаюсь реализовать Ваш слайдер в каждом отдельном табе. При попытке инициализации всех элементов с классом .slider из примера, во «Вкладке 1» два слайдера работают отлично, но при переключении на «Вкладку 2», в которой тоже вроде должен был инициализироваться третий слайдер, этого не происходит — не работает слайдер. Я пытался через id-шники получить инициализацию слайдера во второй вкладке, но тоже ничего не вышло. Что я делаю не так? Код прилагаю.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <!-- Подключаем CSS слайдера -->
  <link rel="stylesheet" href="/wp-content/themes/hello-elementor-child/ChiefSlider/chief-slider.min.css">
  <!-- Подключаем JS слайдера -->
  <script defer src="/wp-content/themes/hello-elementor-child/ChiefSlider/chief-slider.min.js"></script>
  <script>
        
  </script>

  <style>
    *,
    *::before,
    *::after {
      box-sizing: border-box;
    }

    body {
      margin: 0;
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
        'Helvetica Neue', Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
        'Segoe UI Symbol';
    }

    .container {
      max-width: 700px;
      margin: 0 auto;
    }

    .slider__wrapper {
      overflow: hidden;
    }

    .slider__item {
      flex: 0 0 33.3333333333%;
      max-width: 33.3333333333%;
      height: 250px;
      display: flex;
      justify-content: center;
      align-items: center;
      color: rgba(255,255,255, 0.8);
      font-size: 7rem;
    }

    .slider__item:nth-child(1) {
      background-color: #f44336;
    }

    .slider__item:nth-child(2) {
      background-color: #9c27b0;
    }

    .slider__item:nth-child(3) {
      background-color: #3f51b5;
    }

    .slider__item:nth-child(4) {
      background-color: #03a9f4;
    }

    .slider__item:nth-child(5) {
      background-color: #4caf50;
    }
    
    

    .tabs {
      font-size: 0;
      /*max-width: 350px;*/
      margin-left: auto;
      margin-right: auto;
    }

    .tabs>input[type="radio"] {
      display: none;
    }

    .tabs>div {
      /* скрыть контент по умолчанию */
      display: none;
      border: 1px solid #e0e0e0;
      padding: 10px 15px;
      font-size: 16px;
    }

    /* отобразить контент, связанный с вабранной радиокнопкой (input type="radio") */
    #tab-btn-1:checked~#content-1,
    #tab-btn-2:checked~#content-2,
    #tab-btn-3:checked~#content-3 {
      display: block;
    }

    .tabs>label {
      display: inline-block;
      text-align: center;
      vertical-align: middle;
      user-select: none;
      background-color: #f5f5f5;
      border: 1px solid #e0e0e0;
      padding: 2px 8px;
      font-size: 16px;
      line-height: 1.5;
      transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out;
      cursor: pointer;
      position: relative;
      top: 1px;
    }

    .tabs>label:not(:first-of-type) {
      border-left: none;
    }

    .tabs>input[type="radio"]:checked+label {
      background-color: #fff;
      border-bottom: 1px solid #fff;
    }
  </style>

</head>

<body>

  <div class="tabs">
    <input type="radio" name="tab-btn" id="tab-btn-1" value="" checked>
    <label for="tab-btn-1">Вкладка 1</label>
    <input type="radio" name="tab-btn" id="tab-btn-2" value="">
    <label for="tab-btn-2">Вкладка 2</label>
    <input type="radio" name="tab-btn" id="tab-btn-3" value="">
    <label for="tab-btn-3">Вкладка 3</label>

    <div id="content-1">
      Содержимое 1...
      <div class="container">
    
        <div class="slider">
          <div class="slider__wrapper">
            <div class="slider__items">
              <div class="slider__item">
                <!-- Контент 1 слайда -->
                1
              </div>
              <div class="slider__item">
                <!-- Контент 2 слайда -->
                2
              </div>
              <div class="slider__item">
                <!-- Контент 3 слайда -->
                3
              </div>
              <div class="slider__item">
                <!-- Контент 4 слайда -->
                4
              </div>
              <div class="slider__item">
                <!-- Контент 5 слайда -->
                5
              </div>
            </div>
          </div>
          <a href="#" class="slider__control" data-slide="prev"></a>
          <a href="#" class="slider__control" data-slide="next"></a>
        </div>
    
      </div>
                        <div class="container">
    
        <div class="slider">
          <div class="slider__wrapper">
            <div class="slider__items">
              <div class="slider__item">
                <!-- Контент 1 слайда -->
                1
              </div>
              <div class="slider__item">
                <!-- Контент 2 слайда -->
                2
              </div>
              <div class="slider__item">
                <!-- Контент 3 слайда -->
                3
              </div>
              <div class="slider__item">
                <!-- Контент 4 слайда -->
                4
              </div>
              <div class="slider__item">
                <!-- Контент 5 слайда -->
                5
              </div>
            </div>
          </div>
          <a href="#" class="slider__control" data-slide="prev"></a>
          <a href="#" class="slider__control" data-slide="next"></a>
        </div>
    
      </div>
    </div>
    <div id="content-2">
      Содержимое 2...
        <div class="container">
    
    <div class="slider">
      <div class="slider__wrapper">
        <div class="slider__items">
          <div class="slider__item">
            <!-- Контент 1 слайда -->
            1
          </div>
          <div class="slider__item">
            <!-- Контент 2 слайда -->
            2
          </div>
          <div class="slider__item">
            <!-- Контент 3 слайда -->
            3
          </div>
          <div class="slider__item">
            <!-- Контент 4 слайда -->
            4
          </div>
          <div class="slider__item">
            <!-- Контент 5 слайда -->
            5
          </div>
        </div>
      </div>
      <a href="#" class="slider__control" data-slide="prev"></a>
      <a href="#" class="slider__control" data-slide="next"></a>
    </div>
    
    </div>
    </div>
    <div id="content-3">
      Содержимое 3...
    </div>
  </div>
<script>
    // после готовности DOM
    document.addEventListener('DOMContentLoaded', function() {
        var elms = document.querySelectorAll('.slider');
        for (var i = 0, len = elms.length; i < len; i++) {
         // инициализация elms[i] в качестве слайдера
        new ChiefSlider(elms[i]);
  }
});
</script>

</body>

</html>
						
Александр Мальцев
Александр Мальцев
Привет!
Слайдер необходимо инициализировать, когда он виден. Т.е. после того, как вы переключаете вкладку. Пример: https://codepen.io/itchief/pen/QWMKLbv.
Aleks
Aleks
Спасибо.
Здесь бы я точно сам не выкрутился.
Странно, что у Вас не реализовано в настройках слайдера center mode и класс для стилизации активного окна по центру. Популярная вещь. Или может есть такая возможность? Вас уже спрашивали в комментариях к первому слайдеру и кто- то предлагал использовать класс slider__item_active. Я пытался через него задать border стили, но принялись они у всех окон в слайдере.
Есть закомментированный участок кода в начале файла chief-slider.dev.js — это не та настройка?
Александр Мальцев
Александр Мальцев
Так класс slider__item_active добавляется к активным слайдам.
Aleks
Aleks
Как отцентрировать к примеру первый слайд, если мы выводим сразу три? Т.е. первый по центру, второй справа и последний слева.
chokolad
chokolad
Шалом, можете помочь с кодом? Нужно сделать из обычного слайдера, плиточный при изменении разрешения, чтоб перелистывать 4-мя блоками
github.com/CHOKOLADis/TW_PGM
hippopotamus
hippopotamus
Добрый день Александр! Прекрасный слайдер, спасибо большое за Вашу работу. Вопрос по выводу слайдера в табы. Два дня воюю с этой темой и не победил. Увидел решение в Ваших постах — но он мне не помогло. Задача стоит — на WP вывести в четырех вкладках — разные слайдеры. Первый слайдер -прекрасно работает — www.grand-climat.ru/test-page-1/ (3-4 вклдка). А вот тот что нужен не работает — www.grand-climat.ru/test-page-2/. Очень нужна Ваша помощь
Александр Мальцев
Александр Мальцев
Добрый день! Добавил пример в статью.
vikaharkov
vikaharkov
Как сделать так, чтобы эти статьи и фотки прямо со страниц сайта вытягивались в слайдер? Ведь статьи и фотки на сайте в блоге постоянно обновляются и хотелось бы, чтобы они сразу появлялись не только на странице сайта, но и в слайдере. Это возможно?
vikaharkov
vikaharkov
Имеется ввиду — автоматически, без дополнительного вмешательства. Статья или фотка появились на странице сайта и автоматом это же появилось в слайдере. Потому что статьи могут быть на странице, которая в глубине сайта. А слайдер на главной
Александр Мальцев
Александр Мальцев
Конечно возможно, но этот код пишется на сервере. Задача здесь заключается в выборе данных и формировании на их основе нужного HTML кода слайдера. Если данные поменяются, то у вас просто сформируется новый код.
vikaharkov
vikaharkov
Я не поняла, что значит «код пишется на сервере»? Вот конкретная задача — вам на сайт поступают каждый день 100 новых фотографий, но они поступают в разные разделы сайта — какие-то в Спорт, какие-то в Аварии и т.д. Обычно это всё вместе выводится в ленте новостей сайта. А слайдер может выполнять эту функцию? Чтобы через него проходили все эти фотки? Все подряд, а не только те, которые туда вставлены ручками. Как такое реализовать можно? Есть ли подобные примеры? Чтобы слайдер висел вверху страницы, например, и в нём появлялись новые фотки по мере их поступления на сайт. Как, например, из Инстаграма есть такая реализация. Но то со стороннего Инстаграма фотки, а хотелось бы со своего сайта чтобы были и выводились в слайдере на главной сайта. Как такое сделать?
Александр Мальцев
Александр Мальцев
Пример PHP скрипта, который создаёт слайдер из всех jpg, находящихся в папке «/examples/images/slider-images/».
<?php

$template = <<<HTML
<div class="slider">
  <div class="slider__container">
    <div class="slider__wrapper">
      <div class="slider__items">{{items}}</div>
    </div>
  </div>
  <a href="#" class="slider__control" data-slide="prev"></a>
  <a href="#" class="slider__control" data-slide="next"></a>
</div>
HTML;

$items = [];
$path = '/examples/images/slider-images/';
$path = $_SERVER['DOCUMENT_ROOT'] . '/examples/images/slider-images/';
$images = glob($path . '*.jpg');
foreach($images as $image) {
  $image = str_replace($_SERVER['DOCUMENT_ROOT'], '', $image);
  $items[] = '<div class="slider__item"><img src="' . $image .'"></div>';
}
$html = str_replace('{{items}}', implode('', $items), $template);

echo $html;
gist.github.com/itchief/4236557238e5b5f67bc868afe10bd4ad
EscaG
EscaG
Вы немного вводите в заблуждение, когда говорите, что этот код пишется на сервере.
Все что делается на сервере это обрабатывается запрос.
Чтобы отрисовать рандомное количество слайдов нужно сделать запрос на сервер и полученный ответ уже со стороны клиента отрисовать.
то есть с помощью цикла заполнить контейнер для слайдов
Александр Мальцев
Александр Мальцев
Можете и на JavaScript создать нужный HTML. Тут каждый выбирает как ему удобнее, мне – на сервере.
vikaharkov
vikaharkov
Здравствуйте! Вопрос имею — откуда в этих слайдерах беруться фотки или статьи? Неужели их туда спецом нужно каждый раз вставлять? Просветите пожалуйста. А то этот момент мною упущен. Если шо, то для Опенкарт 2.3 мне интересно
Александр Мальцев
Александр Мальцев
Здравствуйте! Обычно это делается на сервере. Например, получаете массив картинок из базы данных и далее с помощью foreach перебираете их и формируете нужный HTML. Как это написать зависит от того, что у вас на сервере и где это хранится.
vikaharkov
vikaharkov
Я извиняюсь за свою блондинистость, но шо поделаешь, не всем дано с лету всё понимать… Можно ещё раз, только помедленее? Что означает «получаете массив картинок из БД»? Уточните, каким конкретным образом картинки сайта попадают в слайдер? В примерах я вижу, что эти картинки везде вставлены буквально вручную. А есть ли примеры, где слайдер работает автоматом, без ручного вмешательства показывает новые картинки или новости?
Narek
Narek
Сядьте и почитайте о том как работает интернет и где хранятся данные, а потом подумайте как реализовать такую архитектуру, сложного совсем ничего нету
У вас не хватает знаний в основах веб технологий и сколько бы вы не спрашивали — вы ничего сейчас не поймете
Pipus
Pipus
Подскажите, пожалуйста, для тех, кто ещё не настолько шарит в JS:
где прописать querySelectorAll и перебор коллекции, чтобы при добавлении двух и более идентичных слайдеров работали все, а ещё круче, если бы можно было либо отключать интервал для некоторых, либо изменять его?

Будет ну очень полезно )
Александр Мальцев
Александр Мальцев
Для активирования всех элементов с классом slider можно использовать такой скрипт:
document.addEventListener('DOMContentLoaded', () => {
  document.querySelectorAll('.slider').forEach(element => {
    new ChiefSlider(element, {
      loop: element.dataset.loop || 'true' === 'true',
      autoplay: element.dataset.autoplay || 'false' === 'true',
      interval: +element.dataset.interval || 5000,
      swipe: element.dataset.swipe || 'true' === 'true',
      refresh: element.dataset.refresh || 'false' === 'true'
    });
  });
});
В этом случае для управления настройками можно использовать data-атрибуты:
<!-- Слайдер 1 -->
<div class="slider" data-autoplay="true" data-interval="7000" data-swipe="false">...</div>
<!-- Слайдер 2 -->
<div class="slider" data-loop="false" data-interval="10000" data-refresh="true">...</div>
Если какой-то атрибут не устанавливаем, то используется значение по умолчанию.
Pipus
Pipus
Крууто
Ну как тут не сказать спасибо на Юмани еще раз )
Татьяна
Татьяна
Подскажите пожалуйста как сделать больше 3 слайда одновременно, 4 нужно одновременно?

Напримере вот этого:

.slider__item {
flex: 0 0 33.3333333333%;
max-width: 33.3333333333%;
}
Александр Мальцев
Александр Мальцев
100% — это вся ширина, если нужно 4, то нужно 100 / 4 = 25%:

.slider__item {
  flex: 0 0 25%;
  max-width: 25%;
}
Татьяна
Татьяна
Здравствуйте, что делать с индикаторами слайдера не понятно почему оня рядом стоят, как исправить?

Александр Мальцев
Александр Мальцев
Где-то тег не закрыли, нужно разметку проверить.
Татьяна
Татьяна
Здравствуйте подскажите пожалуйста, как сделать autoplay в двух слайдерах версии 4 с индикаторами и автоматической сменой слайдов через 7 секунд.
Я сделала 2 слайдера и они работаю вместе, только нет автоматической смены слайдов.
Куда нужно добавить этот JS код?
loop: true,
autoplay: false,
interval: 5000,
swipe: true,
refresh: false 
Вот пример:
<!-- Слайдер 1 -->
<div class="slider" data-slider="chiefslider">...</div>
<!-- Слайдер 2 -->
<div class="slider" data-slider="chiefslider">...</div>
<script src="assets/js/chiefslider.js"></script>
<script>
  const $sliders = document.querySelectorAll('[data-slider="chiefslider"]');
  $sliders.forEach(function ($slider) {
    new ChiefSlider($slider);
  });
  document.querySelectorAll('.slider').forEach(function(item, index){ 
    item.setAttribute('slider-id', index);
    multiItemSlider('[slider-id="'+ index +'"]');
  });
</script>
Александр Мальцев
Александр Мальцев
Привет! Для этого нужно написать следующий код (пример):
document.querySelectorAll('.slider').forEach(function(element) {
  new ChiefSlider(element, {
    loop: true,
    autoplay: true,
    interval: 7000,
  });
});
fet
fet
Здравствуйте, спасибо за ваш труд.
Дмитрий
Дмитрий
Александр, спасибо за легкое и простое решение!
Подскажите пожалуйста, как я могу назначить уникальный стиль слайду, который в данный момент находится по центру? (скриншот)
Vadim
Vadim
Через class .slider__item_active.
Евгений
Евгений
пытаюсь подключить 2 слайдера — один на странице, другой в модальном окне. на странице работает, в модельном нет( как это сделать правильно?
сейчас так сделал
<script>
            document.addEventListener('DOMContentLoaded', function () {
                var elms = document.querySelectorAll('#slider-1');
                for (var i = 0, len = elms.length; i < len; i++) {
                    // инициализация elms[i] в качестве слайдера
                    new ChiefSlider(elms[i]);
                }
            });
        </script>
        <script>
            // после готовности DOM
            document.addEventListener('DOMContentLoaded', function () {
                var elms = document.querySelectorAll('#slider-2');
                for (var i = 0, len = elms.length; i < len; i++) {
                    // инициализация elms[i] в качестве слайдера
                    new ChiefSlider(elms[i]);
                }
            });
        </script>
Александр Мальцев
Александр Мальцев
При инициализации слайдера выполняется определение его размеров. Но, это сделать не получится, если слайдер не отображается. Инициализацию слайдера в модальном окне следует делать при его открытии.
Пример как это можно реализовать добавил в статью.
Артур Владимирович Панфилов
Артур Владимирович Панфилов
Здравствуйте, почему если в слайдер с одновременным показом 3 слайдов добавить например 12 слайдов, а не 5, то при прокрутке назад с конца он не возвращается к 1 слайду, а остается на 2
Александр Мальцев
Александр Мальцев
Привет!
Поправил. Файлы на GitHub обновил.
Alexey
Alexey
Здравствуйте Александр!
Огромное спасибо за этот прекрасный слайдер и отличную документацию!
#1: Могли бы вы исправить или подсказать как исправить то, что этот слайдер совершенно не отображается на моем мобильном телефоне? В чем может быть причина? Safari, iPhone 6 Plus.
#2: Со временем, после 10-20 автоматических слайдов, слайдер почему то начинает листать, скажем не на 100% влево, а уже на 99% и потом 1% резко дергается, до конца. Было бы здорово если бы это можно было бы как-то исправить.
Но в целом, я безмерно Вам благодарен. Вы мне очень помогли этим слайдером. Большое спасибо.
Alexey
Alexey
С проблемой #2 я справился. Дело в том, что если поместить слайдер в DIV у которого ширина будет равняться цифре с VW, например 65vw — появится вот такой вот баг. Слайдер со временем начинает дергаться все больше и больше. Стоит сделать этот DIV = 100% баг исчезает.

Проблема #1 до сих пор актуальна :( Этот слайдер почему то не отображается на моем iPhone 6+ Safari. :(
Александр Мальцев
Александр Мальцев
Привет!
Спасибо, второй баг посмотрю.
Первый баг скорее всего из-за стилей. Добавил префиксы в CSS.
Alexey
Alexey
Привет! Спасибо большое за твой ответ!
К сожалению по прежнему не работает, но я понял как именно проблема проявляется. Слайдер все таки появляется. И автоматический листает первый, второй, третий, четвертый слайд, а последнего слайда уже нет и затем слайды просто исчезают. 2ой цикл не появляется. Я проверил твои слайдеры (в том числе и первый), на этом вебсайте, с мобильного safari. Проблема, к сожалению, присутствует.
Заранее большое спасибо.
Александр Мальцев
Александр Мальцев
Значит что-то в JS не поддерживается. А версия Safari какая?
Alexey
Alexey
Большое спасибо за поддержку!
12.5.3 Если версия safari совпадает с версией iOS. (В google пишут, что версия safari == версия iOS)
PS: Баг присутствует когда loop: true.
Alexey
Alexey
В google chrome такая же проблема на мобильном телефоне.
Баг появляется если включить loop:true. Без разницы, autoplay это или нет.
Последний и последующие слайды отсутствуют, в не зависимости от количества слайдов.
Александр Мальцев
Александр Мальцев
Событие transitionstart не поддерживается в iOS 12.x. Немного изменил.
Alexey
Alexey
О да! :) Большое спасибо. Теперь слайдер работает, в том числе на ios 12. Большое спасибо за слайдер и тех поддержку, ты — талант :)
Master
Master
Это работает. Но есть новая проблема. Если присутствует всего один слайд, то при первичной загрузке слайдера его не видно, отображается белое пространство. И да, 2 слайда также работают некорректно.
Если 3 и больше слайдов — все работает как надо.

Как возможно это поправить? Спасибо.
Александр Мальцев
Александр Мальцев
Какая ОС? Какой браузер и версия?
Master
Master
Проверял на ios 13 мобильный safari и chrome. На десктопе chrome и FireFox та же проблема.

3 и более слайда работают везде на всех платформах.
2 слайда некорректно в ios13 chrome и Safari Мобильном.
1 слайд некорректно везде на всех устройствах.
moytop
moytop

Здравствуйте, а если не секрет то что именно меняли? я просто использую старую версию simple-adaptive-slider и там как раз та же проблема со слайдерами в ios

Александр Мальцев
Александр Мальцев

Здравствуйте! На GitHub можно все изменения посмотреть.

Василий
Василий
Здравствуйте, Александр!
Спасибо за отличный слайдер!
Есть необходимость добавить следующую функциональность: навигация по слайдам с помощью ползунка… или стандартного input type=«range», или(и даже лучше в плане стилизации), кастомного.
На подобие как здесь — https://darsa.in/sly/examples/horizontal.html
В комментариях такого примера не нашел(может плохо искал;)))
Подскажите, пожалуйста, в каком направлении лучше копать? Может хотя бы алгоритм или псевдокод…
Заранее огромное спасибо!!!
sankavankina
sankavankina
Доброго времени суток! Очень понравился ваш слайдер, прекрасно подошёл для моей задачи, единственное, что вообще никак не могу сделать, так это счётчик слайдов (1/3). Подскажите, пожалуйста, как это реализовать. Очень нужно… Спасибо!
Александр Мальцев
Александр Мальцев
Привет! Спасибо за отзыв.
Это можно выполнить разными способами. Например, с помощью CSS счётчиков (первый пример в статье):
.slider__items {
  counter-reset: slide;
}
.slider__item {
  position: relative;
  counter-increment: slide;
}
.slider__item::before {
  content: counter(slide) "/5";
  position: absolute;
  top: 10px;
  right: 20px;
  color: #fff;
  font-style: italic;
  font-size: 32px;
  font-weight: bold;
  display: block;
}
Master
Master
Спасибо, Александр, за столь ценный IT продукт. Использовал его в адаптивном сайте. Только заметил проблему: слайдер с зацикливанием работает не корректно в мобильных браузерах (проверял на Safari и Google Chrome). После пролистывания всех слайдов с изображениями, бесконечно идут пустые окна и слайдер не возвращается к первому изображению. В чем может быть проблема?
snakeTLN
snakeTLN
Александр, спасибо вам за труд. Не сильна в JS, но ваш слайдер v2 легко использовать, даже не особо разбираясь в JS. Но заметили такой минус. Слайдер со свайпом не работает в IE11, т е не только свайп не работает, но и сам слайдер полностью. Как их подружить?
Александр Мальцев
Александр Мальцев
Пожалуйста! В Internet Explorer, работающим под управлением Windows 10 работает. А какая ошибка в консоли выводится?
kadochnikov_k
kadochnikov_k
Александр, хочу еще раз поблагодарить за слайдер! Перехожу сейчас с первой версии на вторую, не могу разобраться в некоторых моментах:
1. Есть ли возможность добавлять индикаторы автоматически по количеству слайдов в слайдере?
2. Есть ли возможность не листать слайды и не выводить кнопки управления слайдером если все слайды умещаются на странице?
Александр Мальцев
Александр Мальцев
Пожалуйста! Конечно можно.
Пример решения (открыть):
const $sliders = document.querySelectorAll('[data-slider="chiefslider"]');
$sliders.forEach(function ($item) {
  if ($item.querySelector('.slider__item').getBoundingClientRect().width * $item.querySelectorAll('.slider__item').length > $item.querySelector('.slider__wrapper').getBoundingClientRect().width) {
    // добавим индикаторы
    const $indicators = document.createElement('ol');
    $indicators.className = 'slider__indicators';
    let inner = '';
    $item.querySelectorAll('.slider__item').forEach(function ($sliderItem, index) {
      inner += `<li data-slide-to="${index}"></li>`;
    });
    $indicators.innerHTML = inner;
    $item.appendChild($indicators);
    // инициализируем слайдер
    new ChiefSlider($item);
  } else {
    $item.querySelectorAll('.slider__control').forEach(function ($control) {
      $control.style.display = 'none';
    })
  }
});
kadochnikov_k
kadochnikov_k
Круто! Огромное спасибо еще раз
kadochnikov_k
kadochnikov_k
Добрый день! Подскажите, как во второй версии инициализировать слайдер, если их несколько на странице?
Александр Мальцев
Александр Мальцев
Привет!
Можно назначить каждому id, а затем их инициализировать следующим образом:
// инициализируем слайдер с id="slider-1"
new ChiefSlider(document.querySelector('#slider-1'));
// инициализируем слайдер с id="slider-2"
new ChiefSlider(document.querySelector('#slider-2'));
Можно, например, посредством forEach (открыть):
const $sliders = document.querySelectorAll('[data-slider="chiefslider"]');
$sliders.forEach(function ($slider) {
  new ChiefSlider($slider);
});
kadochnikov_k
kadochnikov_k
Огромное спасибо! И еще: есть ли возможность во второй версии добавлять индикаторы автоматически в зависимости от количества слайдов?
damir
damir
Почему кнопки управления не работают? js и css подключены, использую предложенный вами пример
Вячеслав
Вячеслав
Александр, огромное спасибо за слайдер! Не могли бы Вы подсказать, как поменять стиль анимации? Сейчас у Вас только перелистование, а мне надо, чтобы на некоторых слайдерах было плавное исчезновение. Может имеет смысл дополнить скрипт слайдера функцией выбора анимации?
Serega
Serega
Здравствуйте у вас классные слайдеры. Я пока только учусь создавать сайты HTML. Я разместил фотографии в слайдере у вас на примере это Адаптивный слайдер с зацикливанием. Скажите а можно как то раелизовать что бы при клике на фото они увеличивались и их могли пролистывать люди как на пк так и на мобильном. Заранее благодарю.
Михаил
Михаил
Можно ли реализовать навигацию в виде превьюшек?
Александр Мальцев
Александр Мальцев
Можно, включу в список задач. После релиза новой версии этого скрипта добавлю такой пример в статью.
Дмитрий Покормяхо
Дмитрий Покормяхо
Добрый день! Большое спасибо за статью. Всё написано просто и понятно, но с php выдаёт ошибку в консоль: Cannot read property 'querySelector' of null at script.js:23 at script.js:238.
Подскажите, пожалуйста, где ошибка.
PHP
<!DOCTYPE html>
<html>

<head>
    <title>ТатаМед</title>
    <link rel="stylesheet" href="style/style.css">
	<link rel="shortcut icon" href="/images/logo_ed_2.png" type="image/png">
	<script src="script/script.js"></script>
	<script src="https://code.jquery.com/jquery-2.1.0.js"></script>
</head>

<body>
	<?
		include 'rewievs/uploadDataBase.php';
		if ( isset($_GET["page"]) )
		{
			$page = $_GET["page"];
		}
		else 
		{
			$page = 1;
		}
		
		$arrayOfMagazInfo = [ ["Мёд разнотравье, 0,7 литра в стеклянной баночке", "Мёд акациевый, 1 литра в стеклянной баночке", "Мёд в сотах, 1 кг"],
		["105грн", "150грн", "250грн"], 
		["images/magaz_photo_1.jpg", "images/magaz_photo_2.jpg", "images/magaz_photo_3.jpg"] ];
	?>
    <header class="header">
        <div class="logo">
            <img src="images/logo_ed_2.png" alt="Тата Мед" class="logo_image">
        </div>
        <h1>ТатаМед</h1>
        <nav class="head_nav">
            <ul class="head_menu">
				<?
					if ($page == 1)
					{
						echo "<li class='head_menu_element'><a href='?page=1' class='select'>Головна</a></li>
								<li class='head_menu_element'><a href='?page=2' class='head_menu_link'>Наша продукція</a></li>
								<li class='head_menu_element'><a href='?page=3' class='head_menu_link'>Контакти</a></li>
								<li class='head_menu_element'><a href='?page=4' class='head_menu_link'>Відгуки</a></li>";
					}
					else if ($page == 2)
					{
						echo "<li class='head_menu_element'><a href='?page=1' class='head_menu_link'>Головна</a></li>
								<li class='head_menu_element'><a href='?page=2' class='select'>Наша продукція</a></li>
								<li class='head_menu_element'><a href='?page=3' class='head_menu_link'>Контакти</a></li>
								<li class='head_menu_element'><a href='?page=4' class='head_menu_link'>Відгуки</a></li>";
					}
					else if ($page == 3)
					{
						echo "<li class='head_menu_element'><a href='?page=1' class='head_menu_link'>Головна</a></li>
								<li class='head_menu_element'><a href='?page=2' class='head_menu_link'>Наша продукція</a></li>
								<li class='head_menu_element'><a href='?page=3' class='select'>Контакти</a></li>
								<li class='head_menu_element'><a href='?page=4' class='head_menu_link'>Відгуки</a></li>";
					}
					else if ($page == 4)
					{
						echo "<li class='head_menu_element'><a href='?page=1' class='head_menu_link'>Головна</a></li>
								<li class='head_menu_element'><a href='?page=2' class='head_menu_link'>Наша продукція</a></li>
								<li class='head_menu_element'><a href='?page=3' class='head_menu_link'>Контакти</a></li>
								<li class='head_menu_element'><a href='?page=4' class='select'>Відгуки</a></li>";
					}
				?>
            </ul>
        </nav>
    </header>
	<main>
		<?
			if ($page == 1)
			{
				echo "
					<h2>Сонячний мед</h2>
					<p class='aboutText'>
						Мед перебрався в красиві баночки...
						Просто шматочок літа під золотою кришечкою.
					</p>
					<div class='firstVideoContainer'>
						<video src='videos/sun_honey.mp4' controls='controls' class='video video_1'></video>
					</div>
					<div class='secondVideoContainer'>
						<video src='videos/Video_02.mp4' controls='controls' class='video video_2'></video>
					</div>
			
					<div class='slider'>
						<div class='slider__wrapper'>
							<div class='slider__item'>
								<div style='height: 250px; background: orange;'>1</div>
							</div>
							<div class='slider__item'>
								<div style='height: 250px; background: green;'>2</div>
							</div>
							<div class='slider__item'>
								<div style='height: 250px; background: violet;'>3</div>
							</div>
							<div class='slider__item'>
								<div style='height: 250px; background: coral;'>4</div>
							</div>
						</div>
						<a class='slider__control slider__control_left' href='#' role='button'></a>
						<a class='slider__control slider__control_right slider__control_show' href='#' role='button'></a>
					</div>

					";
			}
			else if ($page == 2)
			{
				echo "<h2>Наша продукція</h2>";
				for ($i = 0; $i < count($arrayOfMagazInfo[0]); $i++)
				{
					echo "<div class='magaz_block'>
							<img class='magazImg' src=".$arrayOfMagazInfo[2][$i].">
							<p class='productName'>".$arrayOfMagazInfo[0][$i]."</p>
							<p class='price'>Цена: ".$arrayOfMagazInfo[1][$i]."</p>
						</div>";
				}
			}
			else if ($page == 3)
			{
				echo "<h2>Контакти</h2>
						<p class='contacts'>
							Телефон: <a class='contacts contactsHref' href='tel:380975572806'>+38-050-281-3750</a>
							Почта: <a class='contacts contactsHref' href='mailto:tatamed@gmail.com'>tatamed@gmail.com</a>
						</p>";
			}
			else if ($page == 4)
			{
				$tab = mysql_query("SELECT * FROM `rewiev` ");
				
				echo "<h2>Відгуки</h2>";
				echo "<table class='rewievTable' align='center' cellspacing='0px'>
							<tr>
								<th>Ім'я</th>
								<th>Відгук</th>
							</tr>";
				
				while ($row = mysql_fetch_array($tab) )
				{
					echo "<tr>
								<td align='center'>
									".$row['name']."
								</td>
								<td id='comment'>
									<i>".$row['rewiev']."</i>
								</td>
							</tr>";
				}
				echo "</table>
						<form type='submit' method='POST' action='rewievs/rewievSend.php'>
							<p align='center'>
								<b>
									<i class='writeRewievText'>Ваше ім'я:</i>
								</b>
								
								<input class='writeRewievInput' type='text' name='name'>
								
								<b>
									<i class='writeRewievText'>Ваш відгук:</i>
								</b>
								
								
								<textarea class='writeRewievInput' name='k' rows='4'></textarea>
								
								
								<input class='writeRewievButton' type='submit' value='Надіслати'>
							</p>";
			}
		?>
	</main>
</body>

</html>
CSS
	body, html {
	margin: 0;
    background-color: #FFCF48;
    min-width: 675px;
}

.header {
	background: url(../images/header_background.jpg);
    background-size:  100% 500px;
    overflow: hidden;
}

.logo_image {
    width: 150px;
    margin: 10px 10px 10px 35px;
    display: inline-block;
    float: left;
}

h1 {
    margin: 30px 0 30px 225px;
	font-family: Comic Sans MS;
	font-size: 60px;
	-webkit-text-stroke: 2.5px brown;
    color: yellow;
	text-shadow: 3px 3px 10px black;
}

h2 {
	font-family: Comic Sans MS;
	font-size: 40px;
	-webkit-text-stroke: 1.2px brown;
    color: yellow;
	margin-left: 0px;
	text-shadow: 2px 2px 7px grey;
}

.head_menu {
    display: inline-block;
}

.head_menu_element {
	display: inline-block;
    list-style-type: none;
    margin-top: 10px;
    margin-bottom: 5px;
}

.head_menu_link {
	margin: 10px auto;
    padding: 5px;
    background-color: yellow;
    border: 3px solid orange;
    border-radius: 15px;
    font-family: Comic Sans MS;
    text-decoration: none;
}

.head_menu_link:hover {
    border: 3px solid orangered;
}

.select {
	margin: 10px auto;
    padding: 5px;
    background-color: yellow;
    border: 3px solid red;
    border-radius: 15px;
    font-family: Comic Sans MS;
    text-decoration: none;
}

main {
	text-align: center;
}

.aboutText {
	font-family: Comic Sans MS;
	color: DarkOrange;
	font-size: 30px;
	-webkit-text-stroke: 0.6px brown;
}

.video, .video:active, .video:focus {
	width: 600px;
	border: 4px solid Chocolate;
	overflow: hidden;
	padding: 0px;
	outline: none;
}

.video_1 {
	margin: 0px 40px 40px 0px;
}

.video_2 {
	margin: 0px 40px 0px 0px;
}

.magaz_block {
	display: inline-block;
	padding: 10px;
	margin: 20px;
	border: 2px solid brown;
	background-color: lightyellow;
	width: 406px;
}

.magazImg {
	width: 400px;
	height: 300px;
}

.productName, .price {
	color: DarkOrange;
	/*#df8100*/
	font-family: Comic Sans MS;
}

.contacts {
	font-family: Comic Sans MS;
	font-size: 30px;
	-webkit-text-stroke: 0.6px brown;
    color: DarkOrange;
	text-decoration: none;
	/*text-shadow: 3px 3px 10px grey;*/
}

.contactsHref:hover {
	text-decoration: underline;
	text-decoration-color: Chocolate;
	color: orangered;
}

.rewievTable {
	background-color: #ffe559;
	text-align: center;
	border: 2px solid Chocolate;
	width: 50%;
	font-size: 20px;
}

td, th {
	border: 1px solid Chocolate;
	padding: 8px;
	color: #cf7903;
}

.writeRewievText {
	color: #cf7903;
	font-size: 20px;
}

.writeRewievInput, .writeRewievInput:active, .writeRewievInput:focus {
	width: 500px;
	outline: none;
	color: Chocolate;
	background-color: #ffdd28;
	border-color: orange;
	border-radius: 10px;
	padding: 5px;
	font-family: comic Sans MS;
	font-size: 20px;
}

.writeRewievButton, .writeRewievButton:active, .writeRewievButton:focus {
	border-radius: 10px;	 
    outline: none;
	color: Chocolate;
	background-color: #ffdd28;
	border-color: orange;
	border-radius: 10px;
	padding: 5px;
	font-family: comic Sans MS;
	font-size: 20px;
}

textarea {
	color: Chocolate;
	border: 2px solid orange;
	min-width: 500px;
	max-width: 800px;
	min-height: 100px;
	max-height: 200px;
}

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

.slider {
      position: relative;
      overflow: hidden;
    }

    .slider__wrapper {
      display: flex;
      transition: transform 0.6s ease;
    }

    .slider__item {
      flex: 0 0 100%;
      max-width: 100%;
    }

    @media (min-width: 980px) {
      .slider__item {
        flex: 0 0 50%;
        max-width: 50%;
      }
    }

    .slider__control {
      position: absolute;
      top: 50%;
      display: flex;
      align-items: center;
      justify-content: center;
      width: 40px;
      color: #fff;
      text-align: center;
      opacity: 0.5;
      height: 50px;
      transform: translateY(-50%);
      background: rgba(0, 0, 0, .5);
    }

    .slider__control:hover,
    .slider__control:focus {
      color: #fff;
      text-decoration: none;
      outline: 0;
      opacity: .9;
    }

    .slider__control_left {
      left: 0;
    }

    .slider__control_right {
      right: 0;
    }

    .slider__control::before {
      content: '';
      display: inline-block;
      width: 20px;
      height: 20px;
      background: transparent no-repeat center center;
      background-size: 100% 100%;
    }

    .slider__control_left::before {
      background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E");
    }

    .slider__control_right::before {
      background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E");
    }

    .slider__item>div {
      line-height: 250px;
      font-size: 100px;
      text-align: center;
    }
JS
	'use strict';
    var multiItemSlider = (function () {

      function _isElementVisible(element) {
        var rect = element.getBoundingClientRect(),
          vWidth = window.innerWidth || doc.documentElement.clientWidth,
          vHeight = window.innerHeight || doc.documentElement.clientHeight,
          elemFromPoint = function (x, y) { return document.elementFromPoint(x, y) };
        if (rect.right < 0 || rect.bottom < 0
          || rect.left > vWidth || rect.top > vHeight)
          return false;
        return (
          element.contains(elemFromPoint(rect.left, rect.top))
          || element.contains(elemFromPoint(rect.right, rect.top))
          || element.contains(elemFromPoint(rect.right, rect.bottom))
          || element.contains(elemFromPoint(rect.left, rect.bottom))
        );
      }

      return function (selector, config) {
        var
          _mainElement = document.querySelector(selector), // основный элемент блока
          _sliderWrapper = _mainElement.querySelector('.slider__wrapper'), // обертка для .slider-item
          _sliderItems = _mainElement.querySelectorAll('.slider__item'), // элементы (.slider-item)
          _sliderControls = _mainElement.querySelectorAll('.slider__control'), // элементы управления
          _sliderControlLeft = _mainElement.querySelector('.slider__control_left'), // кнопка "LEFT"
          _sliderControlRight = _mainElement.querySelector('.slider__control_right'), // кнопка "RIGHT"
          _wrapperWidth = parseFloat(getComputedStyle(_sliderWrapper).width), // ширина обёртки
          _itemWidth = parseFloat(getComputedStyle(_sliderItems[0]).width), // ширина одного элемента    
          _positionLeftItem = 0, // позиция левого активного элемента
          _transform = 0, // значение транфсофрмации .slider_wrapper
          _step = _itemWidth / _wrapperWidth * 100, // величина шага (для трансформации)
          _items = [], // массив элементов
          _interval = 0,
          _html = _mainElement.innerHTML,
          _states = [
            { active: false, minWidth: 0, count: 1 },
            { active: false, minWidth: 980, count: 2 }
          ],
          _config = {
            isCycling: false, // автоматическая смена слайдов
            direction: 'right', // направление смены слайдов
            interval: 5000, // интервал между автоматической сменой слайдов
            pause: true // устанавливать ли паузу при поднесении курсора к слайдеру
          };

        for (var key in config) {
          if (key in _config) {
            _config[key] = config[key];
          }
        }

        // наполнение массива _items
        _sliderItems.forEach(function (item, index) {
          _items.push({ item: item, position: index, transform: 0 });
        });

        var _setActive = function () {
          var _index = 0;
          var width = parseFloat(document.body.clientWidth);
          _states.forEach(function (item, index, arr) {
            _states[index].active = false;
            if (width >= _states[index].minWidth)
              _index = index;
          });
          _states[_index].active = true;
        }

        var _getActive = function () {
          var _index;
          _states.forEach(function (item, index, arr) {
            if (_states[index].active) {
              _index = index;
            }
          });
          return _index;
        }

        var position = {
          getItemMin: function () {
            var indexItem = 0;
            _items.forEach(function (item, index) {
              if (item.position < _items[indexItem].position) {
                indexItem = index;
              }
            });
            return indexItem;
          },
          getItemMax: function () {
            var indexItem = 0;
            _items.forEach(function (item, index) {
              if (item.position > _items[indexItem].position) {
                indexItem = index;
              }
            });
            return indexItem;
          },
          getMin: function () {
            return _items[position.getItemMin()].position;
          },
          getMax: function () {
            return _items[position.getItemMax()].position;
          }
        }

        var _transformItem = function (direction) {
          var nextItem;
          if (!_isElementVisible(_mainElement)) {
            return;
          }
          if (direction === 'right') {
            _positionLeftItem++;
            if ((_positionLeftItem + _wrapperWidth / _itemWidth - 1) > position.getMax()) {
              nextItem = position.getItemMin();
              _items[nextItem].position = position.getMax() + 1;
              _items[nextItem].transform += _items.length * 100;
              _items[nextItem].item.style.transform = 'translateX(' + _items[nextItem].transform + '%)';
            }
            _transform -= _step;
          }
          if (direction === 'left') {
            _positionLeftItem--;
            if (_positionLeftItem < position.getMin()) {
              nextItem = position.getItemMax();
              _items[nextItem].position = position.getMin() - 1;
              _items[nextItem].transform -= _items.length * 100;
              _items[nextItem].item.style.transform = 'translateX(' + _items[nextItem].transform + '%)';
            }
            _transform += _step;
          }
          _sliderWrapper.style.transform = 'translateX(' + _transform + '%)';
        }

        var _cycle = function (direction) {
          if (!_config.isCycling) {
            return;
          }
          _interval = setInterval(function () {
            _transformItem(direction);
          }, _config.interval);
        }

        // обработчик события click для кнопок "назад" и "вперед"
        var _controlClick = function (e) {
          if (e.target.classList.contains('slider__control')) {
            e.preventDefault();
            var direction = e.target.classList.contains('slider__control_right') ? 'right' : 'left';
            _transformItem(direction);
            clearInterval(_interval);
            _cycle(_config.direction);
          }
        };

        // обработка события изменения видимости страницы
        var _handleVisibilityChange = function () {
          if (document.visibilityState === "hidden") {
            clearInterval(_interval);
          } else {
            clearInterval(_interval);
            _cycle(_config.direction);
          }
        }

        var _refresh = function () {
          clearInterval(_interval);
          _mainElement.innerHTML = _html;
          _sliderWrapper = _mainElement.querySelector('.slider__wrapper');
          _sliderItems = _mainElement.querySelectorAll('.slider__item');
          _sliderControls = _mainElement.querySelectorAll('.slider__control');
          _sliderControlLeft = _mainElement.querySelector('.slider__control_left');
          _sliderControlRight = _mainElement.querySelector('.slider__control_right');
          _wrapperWidth = parseFloat(getComputedStyle(_sliderWrapper).width);
          _itemWidth = parseFloat(getComputedStyle(_sliderItems[0]).width);
          _positionLeftItem = 0;
          _transform = 0;
          _step = _itemWidth / _wrapperWidth * 100;
          _items = [];
          _sliderItems.forEach(function (item, index) {
            _items.push({ item: item, position: index, transform: 0 });
          });
        }

        var _setUpListeners = function () {
          _mainElement.addEventListener('click', _controlClick);
          if (_config.pause && _config.isCycling) {
            _mainElement.addEventListener('mouseenter', function () {
              clearInterval(_interval);
            });
            _mainElement.addEventListener('mouseleave', function () {
              clearInterval(_interval);
              _cycle(_config.direction);
            });
          }
          document.addEventListener('visibilitychange', _handleVisibilityChange, false);
          window.addEventListener('resize', function () {
            var
              _index = 0,
              width = parseFloat(document.body.clientWidth);
            _states.forEach(function (item, index, arr) {
              if (width >= _states[index].minWidth)
                _index = index;
            });
            if (_index !== _getActive()) {
              _setActive();
              _refresh();
            }
          });
        }

        // инициализация
        _setUpListeners();
        if (document.visibilityState === "visible") {
          _cycle(_config.direction);
        }
        _setActive();

        return {
          right: function () { // метод right
            _transformItem('right');
          },
          left: function () { // метод left
            _transformItem('left');
          },
          stop: function () { // метод stop
            _config.isCycling = false;
            clearInterval(_interval);
          },
          cycle: function () { // метод cycle 
            _config.isCycling = true;
            clearInterval(_interval);
            _cycle();
          }
        }

      }
    }());

    var slider = multiItemSlider('.slider', {
      isCycling: true
    })
Site
Дмитрий Покормяхо
Дмитрий Покормяхо
Извиняюсь. Сам разобрался. Не там подключал js. :)
kadochnikov_k
kadochnikov_k
Александр, еще раз спасибо за слайдер! Я использую этот вариант слайдера, но в нем не было свайпа и я его решил добавить, используя ваш код. Но свайп так и не заработал, не могу понять в чем моя ошибка, возможно вы подскажете? Вот что у меня получилось:
'use strict';
var multiItemSliderVertical = (function () {

    function _isElementVisible(element) {
        var
            rect = element.getBoundingClientRect(),
            windowHeight = (window.innerHeight || document.documentElement.clientHeight),
            windowWidth = (window.innerWidth || document.documentElement.clientWidth),
            vertInView = (rect.top <= windowHeight) && ((rect.top + rect.height) >= 0),
            horInView = (rect.left <= windowWidth) && ((rect.left + rect.width) >= 0);
        return (vertInView && horInView);
    }

    return function (selector, config) {
        var
            _mainElement = document.querySelector(selector),
            _sliderWrapper = _mainElement.querySelector('.slider__wrapper_vertical'),
            _sliderItems = _mainElement.querySelectorAll('.slider__item_vertical'),
            _sliderControls = _mainElement.querySelectorAll('.slider__control_vertical'),
            _sliderControlLeft = _mainElement.querySelector('.slider__control_left_vertical'),
            _sliderControlRight = _mainElement.querySelector('.slider__control_right_vertical'),
            _wrapperWidth = parseFloat(getComputedStyle(_sliderWrapper).width),
            _itemWidth = parseFloat(getComputedStyle(_sliderItems[0]).width),
            _wrapperHeight = parseFloat(getComputedStyle(_sliderWrapper).height),
            _itemHeight = parseFloat(getComputedStyle(_sliderItems[0]).height),
            _html = _mainElement.innerHTML,
            _indexIndicator = 0,
            _maxIndexIndicator = _sliderItems.length - 1,
            _indicatorItems,
            _positionLeftItem = 0,
            _transform = 0,
            _step = _itemWidth / _wrapperWidth * 100,
            _stepHeight = _itemHeight / _wrapperHeight * 100,
            _items = [],
            _interval = 0,
            _states = [
                { active: false, minWidth: 0, count: 1 },
                { active: false, minWidth: 576, count: 2 },
                { active: false, minWidth: 992, count: 3 },
                { active: false, minWidth: 1200, count: 4 },
            ],
            _config = {
                isCycling: false,
                direction: 'right',
                interval: 10000,
                pause: true
            };

        for (var key in config) {
            if (key in _config) {
                _config[key] = config[key];
            }
        }

        _sliderItems.forEach(function (item, index) {
            _items.push({ item: item, position: index, transform: 0 });
        });

        var _setActive = function () {
            var _index = 0;
            var width = parseFloat(document.body.clientWidth);
            _states.forEach(function (item, index, arr) {
                _states[index].active = false;
                if (width >= _states[index].minWidth)
                    _index = index;
            });
            _states[_index].active = true;
        }

        var _getActive = function () {
            var _index;
            _states.forEach(function (item, index, arr) {
                if (_states[index].active) {
                    _index = index;
                }
            });
            return _index;
        }

        var position = {
            getMin: 0,
            getMax: _items.length - 1,
        }

        var _transformItem = function (direction) {
            var nextItem, currentIndicator = _indexIndicator;
            if (!_isElementVisible(_mainElement)) {
                return;
            }
            if (direction === 'right') {
                if ((_positionLeftItem + _wrapperWidth / _itemWidth - 1) >= position.getMax) {
                    return;
                }
                _positionLeftItem++;
                _transform -= _stepHeight;
                _indexIndicator = _indexIndicator + 1;
                if (_indexIndicator > _maxIndexIndicator) {
                    _indexIndicator = 0;
                }
            }
            if (direction === 'left') {
                if (_positionLeftItem <= position.getMin) {
                    return;
                }
                _positionLeftItem--;
                _transform += _stepHeight;
                _indexIndicator = _indexIndicator - 1;
                if (_indexIndicator < 0) {
                    _indexIndicator = _maxIndexIndicator;
                }
            }
            _sliderWrapper.style.transform = 'translateY(' + _transform + '%)';
            _indicatorItems[currentIndicator].classList.remove('active');
            _indicatorItems[_indexIndicator].classList.add('active');
        }

        var _slideTo = function (to) {
            var i = 0, direction = (to > _indexIndicator) ? 'right' : 'left';
            while (to !== _indexIndicator && i <= _maxIndexIndicator) {
                _transformItem(direction);
                i++;
            }
        }

        var _cycle = function (direction) {
            if (!_config.isCycling) {
                return;
            }
            _interval = setInterval(function () {
                _transformItem(direction);
            }, _config.interval);
        }

        var _controlClick = function (e) {
            if (e.target.classList.contains('slider__control_vertical')) {
                e.preventDefault();
                var direction = e.target.classList.contains('slider__control_right_vertical') ? 'right' : 'left';
                _transformItem(direction);
                clearInterval(_interval);
                _cycle(_config.direction);
            }
            if (e.target.getAttribute('data-slide-to-vertical')) {
                _slideTo(parseInt(e.target.getAttribute('data-slide-to-vertical')));
                clearInterval(_interval);
                _cycle(_config.direction);
            }
        };

        var _handleVisibilityChange = function () {
            if (document.visibilityState === "hidden") {
                clearInterval(_interval);
            } else {
                clearInterval(_interval);
                _cycle(_config.direction);
            }
        }

        var _refresh = function () {
            clearInterval(_interval);
            _mainElement.innerHTML = _html;
            _sliderWrapper = _mainElement.querySelector('.slider__wrapper_vertical');
            _sliderItems = _mainElement.querySelectorAll('.slider__item_vertical');
            _sliderControls = _mainElement.querySelectorAll('.slider__control_vertical');
            _sliderControlLeft = _mainElement.querySelector('.slider__control_left_vertical');
            _sliderControlRight = _mainElement.querySelector('.slider__control_right_vertical');
            _wrapperHeight = parseFloat(getComputedStyle(_sliderWrapper).height);
            _itemHeight = parseFloat(getComputedStyle(_sliderItems[0]).height);
            _positionLeftItem = 0;
            _transform = 0;
            _indexIndicator = 0;
            _maxIndexIndicator = _sliderItems.length - 1;
            _step = _itemWidth / _wrapperWidth * 100;
            _stepHeight = _itemHeight / _wrapperHeight * 100;
            _items = [];
            _sliderItems.forEach(function (item, index) {
                _items.push({ item: item, position: index, transform: 0 });
            });
            _addIndicators();
        }

        var _setUpListeners = function () {
            _mainElement.addEventListener('click', _controlClick);
            if (_config.pause && _config.isCycling) {
                _mainElement.addEventListener('mouseenter', function () {
                    clearInterval(_interval);
                });
                _mainElement.addEventListener('mouseleave', function () {
                    clearInterval(_interval);
                    _cycle(_config.direction);
                });
            }

            document.addEventListener('visibilitychange', _handleVisibilityChange, false);
            window.addEventListener('resize', function () {
                var
                    _index = 0,
                    width = parseFloat(document.body.clientWidth);
                _states.forEach(function (item, index, arr) {
                    if (width >= _states[index].minWidth)
                        _index = index;
                });
                if (_index !== _getActive()) {
                    _setActive();
                    _refresh();
                }
            });

            _mainElement.addEventListener('touchstart', function (e) {
                _startX = e.changedTouches[0].clientX;
            });
            _mainElement.addEventListener('touchend', function (e) {
                var
                    _endX = e.changedTouches[0].clientX,
                    _deltaX = _endX - _startX;
                if (_deltaX > 50) {
                    _transformItem('left');
                    clearInterval(_interval);
                    _cycle(_config.direction);
                } else if (_deltaX < -50) {
                    _transformItem('right');
                    clearInterval(_interval);
                    _cycle(_config.direction);
                }
            });

            _mainElement.addEventListener('mousedown', function (e) {
                _startX = e.clientX;
            });
            _mainElement.addEventListener('mouseup', function (e) {
                var
                    _endX = e.clientX,
                    _deltaX = _endX - _startX;
                if (_deltaX > 50) {
                    _transformItem('left');
                } else if (_deltaX < -50) {
                    _transformItem('right');
                }
            });
        }

        var _addIndicators = function () {
            var sliderIndicators = document.createElement('ol');
            sliderIndicators.classList.add('slider__indicators_vertical');
            for (var i = 0; i < _sliderItems.length; i++) {
                var sliderIndicatorsItem = document.createElement('li');
                if (i === 0) {
                    sliderIndicatorsItem.classList.add('active');
                }
                sliderIndicatorsItem.setAttribute("data-slide-to-vertical", i);
                sliderIndicators.appendChild(sliderIndicatorsItem);
            }
            _mainElement.appendChild(sliderIndicators);
            _indicatorItems = _mainElement.querySelectorAll('.slider__indicators_vertical > li')
        }

        // добавляем индикаторы
        _addIndicators();
        // инициализация
        _setUpListeners();

        if (document.visibilityState === "visible") {
            _cycle(_config.direction);
        }
        _setActive();

        return {
            right: function () {
                _transformItem('right');
            },
            left: function () {
                _transformItem('left');
            },
            stop: function () {
                _config.isCycling = false;
                clearInterval(_interval);
            },
            cycle: function () {
                _config.isCycling = true;
                clearInterval(_interval);
                _cycle();
            }
        }

    }
}());

document.querySelectorAll('.slider_vertical').forEach(function (item, index) {
    item.setAttribute('data-slider-id-vertical', index);
    var sliderSelector = '[data-slider-id-vertical="' + index + '"]';
    var sliderElem = document.querySelector(sliderSelector);
    // если слайдов в слайдере нет, то завершаем текущую работу функции
    if (sliderElem.querySelectorAll('.slider__item_vertical').length === 0) {
        return;
    }
    if (
        sliderElem.querySelector('.slider__item_vertical').getBoundingClientRect().width *
        sliderElem.querySelectorAll('.slider__item_vertical').length >
        sliderElem.querySelector('.slider__wrapper_vertical').getBoundingClientRect().width
    ) {
        multiItemSliderVertical('[data-slider-id-vertical="' + index + '"]', {
            isCycling: true,
        });
    } else {
        var sliderControls = sliderElem.querySelectorAll('.slider__control_vertical');
        for (var i = 0; i < sliderControls.length; i++) {
            sliderControls[i].style.display = 'none';
        }
    }
});
Александр Мальцев
Александр Мальцев
Пожалуйста! В ближайшее время обновлю скрипт слайдера. Он будет включать возможность включения свайпа из коробки.
kadochnikov_k
kadochnikov_k
Спасибо большое!
kadochnikov_k
kadochnikov_k
Все-таки возможно подскажите, почему в моем случае не сработало добавление этого кода для свайпа?
_mainElement.addEventListener('touchstart', function (e) {
                _startX = e.changedTouches[0].clientX;
            });
            _mainElement.addEventListener('touchend', function (e) {
                var
                    _endX = e.changedTouches[0].clientX,
                    _deltaX = _endX - _startX;
                if (_deltaX > 50) {
                    _transformItem('left');
                    clearInterval(_interval);
                    _cycle(_config.direction);
                } else if (_deltaX < -50) {
                    _transformItem('right');
                    clearInterval(_interval);
                    _cycle(_config.direction);
                }
            });

            _mainElement.addEventListener('mousedown', function (e) {
                _startX = e.clientX;
            });
            _mainElement.addEventListener('mouseup', function (e) {
                var
                    _endX = e.clientX,
                    _deltaX = _endX - _startX;
                if (_deltaX > 50) {
                    _transformItem('left');
                } else if (_deltaX < -50) {
                    _transformItem('right');
                }
            });
Виталий
Виталий
День добрый. А вы не добавили еще свайп в слайдер?
Александр Мальцев
Александр Мальцев
Новая версия в процессе разработки, свайп туда уже добавил.
SinGlEBW
SinGlEBW
Хотел бы указать некоторую проблему с слайдером. У меня на сайте планируется 5 слайдеров (не спрашивайте зачем). 4 не похожих на 1.
Используя одинаковые классы в слайдере придётся добавлять доп. классы слайдерам и переназначать стили или как вариант копировать всю функцию и переназначать классы там. Что бы этого не городить пришлось чуть улучшить
querySelector||All

Флаги указывал чтоб сходу понятно было, что метод не стандартный.
  Element.prototype.querySelector = function (selectOrRegExp, flag = false){
    if(selectOrRegExp.constructor === RegExp.prototype.constructor && flag){
      return [...this.children].find((item) => selectOrRegExp.test(item.className));
    }else{
      return this.querySelector(selectOrRegExp);
    }
  }
  
  Element.prototype.querySelectorAll = function (selectOrRegExp, flag = false){
    if(selectOrRegExp.constructor === RegExp.prototype.constructor && flag){
      return [...this.children].filter((item) => selectOrRegExp.test(item.className));
    }else{
      return this.querySelectorAll(selectOrRegExp);
    }
  }
Результат:
 let  _mainElement = document.querySelector(selector),
      _sliderWrapper = _mainElement.querySelector(/\w*__wrap/, true),
      _sliderItems = _sliderWrapper.querySelectorAll(/\w*__item/, true),
      _sliderControls = _mainElement.querySelectorAll(/\w*__control/, true),
      _sliderControlLeft = _mainElement.querySelector(/\w*__control_left/, true),
      _sliderControlRight = _mainElement.querySelector(/\w*__control_right/, true),
	....
Тут повнимательней, получить элементы можно Родитель-дочерний(е), но не Предок-Родитель-дочерний.
	_sliderItems = _sliderWrapper.querySelectorAll(/\w*__item/, true),
SinGlEBW
SinGlEBW
До конца не проверил. Если обычная строка попадает в метод querySelector
то она зацикликся.
Методы всё же лучше назвать по другому. Например
Element.prototype.с_querySelector
Element.prototype.с_querySelectorAll
Тимофей
Тимофей
Привет, вопрос не по теме. У вас не нашел ответа. Подскажите по input type=range. Сам код выложил по адресу range.cmstext.ru Вроде всё работает.
1. Проблема в том, что не всегда срабатывает onmouseover адекватно. т.е. при нажитии мышкой на левый срабатывает правый так как они в абсолюте лежат в одном z-index как победить это проблему? помогите
2. Как заставить javascript обрабатывать значения ползунков чтобы они не пересекались. Пробовал проверять значение не получается. Помогите
Заранее спасибо. Вы бог
Тимофей
Тимофей
Александр здравствуйте, спасибо за ваш труд. Очень интересно и полезно. Хочу использовать Ваш слайдер, посмотрел все примеры но не нашел как изменить количество активных (отображаемых) блоков при использовании нескольких слайдеров на странице по ID. Например у слайдера #slider1 по 5 блоков, у #slider2 3 блока. Спасибо Вам заранее. Очень рад, что нашел эту страницу.
Александр Мальцев
Александр Мальцев
Привет! Спасибо за отзыв. Это делается с помощью CSS:
/* по 5 блоков */
#slider1 .slider__item {
  flex: 0 0 20%;
  max-width: 20%;
}
/* по 3 блока */
#slider2 .slider__item {
  flex: 0 0 33.3333333333%;
  max-width: 33.3333333333%;
}
Сергей
Сергей
Здравствуйте. Отличный лаконичный слайдер, и главное, спасибо за подробную «документацию».
Прочитав комментарии я понял, что
/* Без изменения кода слайдера инициализировать все слайдеры на странице можно так: */
document.querySelectorAll('.slider').forEach(function (item, index) {
item.setAttribute('slider-id', index);
multiItemSlider('[slider-id="' + index + '"]');
});

Или нужно инициализировать каждый слайдер таким образом:
var slider = multiItemSlider('#product-slider', {
isCycling: false, // автоматическая смена слайдов

});

У меня вопрос: как «совместить» эти способы. Т.е. в большинстве мест проекта хочется автоматически инициализировать слайдеры. Однако, есть страницы или элементы, где нужно настроить — время зацикливания или отсутствие зацикливания, например. Убрать элементы управления можно с помощью css. Но как можно автоматически инициализировать все слайдеры, при этом, программировать настройки нужных?
Александр Мальцев
Александр Мальцев
Здравствуйте. Версия слайдера с возможностью его настройки посредством параметров сейчас находится в разработке.
В данный момент пока планирую реализовать следующие параметры:
{
  infinite: infinite, // будет определять с зацикливанием или без зацикливания
  autoplay: autoplay, // будет включать автоматическую смену слайдов
  autoplaySpeed: autoplaySpeed, // устанавливает время между автоматической сменой слайдов
}
Если нужны ещё какие-то параметры для настройки, то напишите.
Александр
Александр
Доброго времени суток, спасибо за предоставленную идею со слайдером, все отлично, за исключением одного нюанса. У меня 3 слайда, при ширине больше 1024px отображаются все три, с этим проблем нет.
При разрешении меньше 1024px нужно, чтобы оставался один слайд и они листались с помощью стрелочек, тут тоже проблем нет, однако слайды начинаются не с первого, а со второго, который ставится первым, затем второй (который должен быть третьим), а после него идет пустой слайд =(
Причем прокрутить назад с первого слайда я не могу, хотя по сути он вторым должен быть.
в js ничего не менял, менял только стили для стрелочек.
вот html: itchief.ru/assets/uploadify/4/4/6/44635217d677050eda4b318355f664ba.png
Если можно решить эту проблему, то буду очень признателен, такое ощущение, что в массив со слайдами слайды пушатся как-то неверно((
Вот пустой слайд: itchief.ru/assets/uploadify/4/e/5/4e54621a0b7cd6b9941040c393e2a8a2.png
Должно быть так, только с другой картинкой и текстом соответственно: itchief.ru/assets/uploadify/8/6/0/8607820a94db91ea200dbc4883cd7ec7.png
Александр Мальцев
Александр Мальцев
Привет! Сделайте пример на «codepen.io» или в другой песочнице, по картинкам трудновато что-то дельное подсказать.
Александр
Александр
Думаю так будет даже лучше и проще: trifle22.github.io/slider-test/
Если открывать с мобильного устройства, так слайдер вообще не работает, и начинает работать только после перезагрузки страницы =((
Kolya
Kolya
Здравстуйте, огромное спасибо за слайдер, а можно как-то переключать сразу 3-4 слайда?
Александр
Александр
Думаю да, надо бы только скрипт подправить, где функции переключения прописаны, но чего-то конкретного сказать не могу ((
Александр Мальцев
Александр Мальцев
Здравствуйте! Посмотрите ответ в этом комментарии.
Фёдор Васькин
Фёдор Васькин
Здравствуйте, Александр! Использую Ваш слайдер в учебных целях. Если я добавляю скрипт и стили в htm файле, то слайдер работает отлично. Если стили подключаю отдельным файлом, то тоже отлично. А если переношу код js в отдельный файл и подключаю скрипт, то при на нажатии на стрелку прокрутки меня почему-то перебрасывает на начало странице, и картинка не прокручивается. Подскажите, пожалуйста, в чём может быть причина и как её можно исправить?
Фёдор Васькин
Фёдор Васькин
Разобрался, всё получилось.
Александр Мальцев
Александр Мальцев
Отлично!
Анна Бондаренко
Анна Бондаренко
Добрый день. Подскажите, каким было решение…
Isa
Isa
У меня с этим слайдером проблемы, при подключении css меняется отображение сайта полностью, и плюс слайдер не работает, при нажатии на стрелки картинки не листает
Александр Мальцев
Александр Мальцев
Скорее всего у вас конфликт со стилями и скриптами вашего сайта.
Isa
Isa
Здравствуйте Александр, я воспользовался вашим сладером, у меня возник такая сетуция, у меня выводятся пару картинок вернее их 5штук выводятся из бд, для каждой картинки указана ссылка в виде
<? if(!empty($item->iconurl)) '<div class="items-ico"> echo <img src="' . $item->iconurl . '"></div>';?>
<? if(!empty($item->iconurl2)) '<div class="items-ico"> echo <img src="' . $item->iconurl2 . '"></div>';?>
как мне пристроить к ним ваш слайдер? Стуле и жава прикрепил через отделеные страницы. Но вот их выводом затруднительно. Подскажите пожалуйста как мне все правильно сделать, чтоб эти картинки как у вас на слайдере можно было листать
Александр Мальцев
Александр Мальцев
Здравствуйте! Такое в php обычно выводят циклом (через foreach).
Алексей Валерьевич Алексеев
Алексей Валерьевич Алексеев
Спасибо Вам за Вашу работу очень хорошее решение!
Хотел бы спросить есть ли возможность у слайдера перемещаться к конкретному слайду отдельно. Я хочу немного доработать его под свои задачи и сделать мини превью каждого слайда при нажатии на которые происходит переход к нужной картинке по принципу работы индикаторов.

Заранее благодарен!
Александр Мальцев
Александр Мальцев
Пожалуйста!
Такой стандартной возможности нет, но это просто решается (пример).
Kitsu-NeshKaa
Kitsu-NeshKaa
Александр, доброго времени суток! Начал использовать ваш слайдер — полет отличный! Вопрос встал когда решил сам его допиливать. Дал всем блокам в слайдере ID и хочу их скрывать в зависимости от того на какой странице находится пользователь. Например блок 5.
window.onload = function() {
document.getElementById('5').style.display = «none»;
}
Скрытие происходит, но сами слайды не схлопываются и остается пустое место от скрытого слайда. Как их схлопнуть?
Александр Мальцев
Александр Мальцев
Привет!
Для этого нужно в скрипте изменить одну строчку:
// замените эту
_sliderItems = _mainElement.querySelectorAll('.slider__item'),
// на следующую
_sliderItems = _mainElement.querySelectorAll('.slider__item:not([style*="display: none;"])'),
Kitsu-NeshKaa
Kitsu-NeshKaa
Спасибо за ответ. Блок исчезает но теперь остается пустое место в конце слайдера =(
Kitsu-NeshKaa
Kitsu-NeshKaa
Причем если засунуть в not и в блок класс — то срабатывает
Kitsu-NeshKaa
Kitsu-NeshKaa
Нашел ответ — window.onload слишком поздно срабатывает. Делайте инициализацию слайдера после того как дали класс или скрыли блок слайдера. Александр спасибо!
Александр Мальцев
Александр Мальцев
Пожалуйста!
Kitsu-NeshKaa
Kitsu-NeshKaa
Еще вопрос появился: что нужно добавить при тач-скролинге что бы не листалась вверх-вниз страница?
Александр Мальцев
Александр Мальцев
Для этого нужно просто отменить стандартное поведение браузера в обработчике этого события (пример):
_mainElement.addEventListener('touchstart', function (e) {
  e.preventDefault();
  //...
});
_mainElement.addEventListener('touchend', function (e) {
  e.preventDefault();
  //...
});
Kitsu-NeshKaa
Kitsu-NeshKaa
не совсем то. Свайпы должны работать по вертикали а по горизонтали страница не должна прокручиваться =)
Александр Мальцев
Александр Мальцев
Пример со свайпом по вертикали (открыть).
Andrey
Andrey
Доброго времени суток! Подскажите, пожалуйста, как решить проблему. Данный слайдер установлен на CMS Drupal. Он выводит блоки в представлении. В кастомном скрипте прописано количество выводимых блоков — 4.
Drupal.behaviors.Carousel = {
  attach: function (context, settings) {
    $('.responsive').slick({
      dots: true,
      infinite: false,
      speed: 300,
      slidesToShow: 4,
      slidesToScroll: 4,
      responsive: [{
        breakpoint: 768,
        settings: {
          slidesToShow: 2,
          slidesToScroll: 2
        }
      },
      {
        breakpoint: 480,
        settings: {
          slidesToShow: 1,
          slidesToScroll: 1
        }
      }]
    });
  }
};
Но проблема возникла на страницах, где количество блоков меньше 4. Не просчитывается ширина и слайды неверного размера получаются.
Подскажите, пожалуйста, как лучше выйти в данной ситуации? Делать условие на проверку количества выводимых блоков и задавать им ширину от этого или изначально принудительно задать ширину слайда?
Александр Мальцев
Александр Мальцев
Здравствуйте! Можно проверять количество блоков, и формировать вызов функции slick уже в зависимости от их количества.
kadochnikov_k
kadochnikov_k
Добрый день! Спасибо за ваш слайдер, не перестаю восхищаться его универсальностью! В одном из проектов возникла потребность сделать вертикальный слайдер с листанием слайдов скроллом или свайпом экрана, когда слайдер занимает весь экран. Я сделал вертикальную смену слайдов, но не могу придумать как привязаться к прокрутке колеса мыши и свайпу экрана для перелистывания. Код прикрепляю, буду благодарен, если сможете помочь.
'use strict';
var multiItemSlider = (function () {

    function _isElementVisible(element) {
        var
            rect = element.getBoundingClientRect(),
            windowHeight = (window.innerHeight || document.documentElement.clientHeight),
            windowWidth = (window.innerWidth || document.documentElement.clientWidth),
            vertInView = (rect.top <= windowHeight) && ((rect.top + rect.height) >= 0),
            horInView = (rect.left <= windowWidth) && ((rect.left + rect.width) >= 0);
        return (vertInView && horInView);
    }

    return function (selector, config) {
        var
            _mainElement = document.querySelector(selector),
            _sliderWrapper = _mainElement.querySelector('.slider__wrapper'),
            _sliderItems = _mainElement.querySelectorAll('.slider__item'),
            _sliderControls = _mainElement.querySelectorAll('.slider__control'),
            _sliderControlLeft = _mainElement.querySelector('.slider__control_left'),
            _sliderControlRight = _mainElement.querySelector('.slider__control_right'),
            _wrapperWidth = parseFloat(getComputedStyle(_sliderWrapper).width),
            _itemWidth = parseFloat(getComputedStyle(_sliderItems[0]).width),
            _wrapperHeight = parseFloat(getComputedStyle(_sliderWrapper).height),
            _itemHeight = parseFloat(getComputedStyle(_sliderItems[0]).height),
            _html = _mainElement.innerHTML,
            _indexIndicator = 0,
            _maxIndexIndicator = _sliderItems.length - 1,
            _indicatorItems,
            _positionLeftItem = 0,
            _transform = 0,
            _step = _itemWidth / _wrapperWidth * 100,
            _stepHeight = _itemHeight / _wrapperHeight * 100,
            _items = [],
            _interval = 0,
            _states = [
                { active: false, minWidth: 0, count: 1 },
                { active: false, minWidth: 576, count: 2 },
                { active: false, minWidth: 992, count: 3 },
                { active: false, minWidth: 1200, count: 4 },
            ],
            _config = {
                isCycling: false,
                direction: 'right',
                interval: 10000,
                pause: true
            };

        for (var key in config) {
            if (key in _config) {
                _config[key] = config[key];
            }
        }

        _sliderItems.forEach(function (item, index) {
            _items.push({ item: item, position: index, transform: 0 });
        });

        var _setActive = function () {
            var _index = 0;
            var width = parseFloat(document.body.clientWidth);
            _states.forEach(function (item, index, arr) {
                _states[index].active = false;
                if (width >= _states[index].minWidth)
                    _index = index;
            });
            _states[_index].active = true;
        }

        var _getActive = function () {
            var _index;
            _states.forEach(function (item, index, arr) {
                if (_states[index].active) {
                    _index = index;
                }
            });
            return _index;
        }

        var position = {
            getMin: 0,
            getMax: _items.length - 1,
        }

        var _transformItem = function (direction) {
            var nextItem, currentIndicator = _indexIndicator;
            if (!_isElementVisible(_mainElement)) {
                return;
            }
            if (direction === 'right') {
                if ((_positionLeftItem + _wrapperWidth / _itemWidth - 1) >= position.getMax) {
                    return;
                }
                _positionLeftItem++;
                _transform -= _stepHeight;
                _indexIndicator = _indexIndicator + 1;
                if (_indexIndicator > _maxIndexIndicator) {
                    _indexIndicator = 0;
                }
            }
            if (direction === 'left') {
                if (_positionLeftItem <= position.getMin) {
                    return;
                }
                _positionLeftItem--;
                _transform += _stepHeight;
                _indexIndicator = _indexIndicator - 1;
                if (_indexIndicator < 0) {
                    _indexIndicator = _maxIndexIndicator;
                }
            }
            _sliderWrapper.style.transform = 'translateY(' + _transform + '%)';
            _indicatorItems[currentIndicator].classList.remove('active');
            _indicatorItems[_indexIndicator].classList.add('active');
        }

        var _slideTo = function (to) {
            var i = 0, direction = (to > _indexIndicator) ? 'right' : 'left';
            while (to !== _indexIndicator && i <= _maxIndexIndicator) {
                _transformItem(direction);
                i++;
            }
        }

        var _cycle = function (direction) {
            if (!_config.isCycling) {
                return;
            }
            _interval = setInterval(function () {
                _transformItem(direction);
            }, _config.interval);
        }

        var _controlClick = function (e) {
            if (e.target.classList.contains('slider__control')) {
                e.preventDefault();
                var direction = e.target.classList.contains('slider__control_right') ? 'right' : 'left';
                _transformItem(direction);
                clearInterval(_interval);
                _cycle(_config.direction);
            }
            if (e.target.getAttribute('data-slide-to')) {
                _slideTo(parseInt(e.target.getAttribute('data-slide-to')));
                clearInterval(_interval);
                _cycle(_config.direction);
            }
        };

        var _handleVisibilityChange = function () {
            if (document.visibilityState === "hidden") {
                clearInterval(_interval);
            } else {
                clearInterval(_interval);
                _cycle(_config.direction);
            }
        }

        var _refresh = function () {
            clearInterval(_interval);
            _mainElement.innerHTML = _html;
            _sliderWrapper = _mainElement.querySelector('.slider__wrapper');
            _sliderItems = _mainElement.querySelectorAll('.slider__item');
            _sliderControls = _mainElement.querySelectorAll('.slider__control');
            _sliderControlLeft = _mainElement.querySelector('.slider__control_left');
            _sliderControlRight = _mainElement.querySelector('.slider__control_right');
            _wrapperHeight = parseFloat(getComputedStyle(_sliderWrapper).height);
            _itemHeight = parseFloat(getComputedStyle(_sliderItems[0]).height);
            _positionLeftItem = 0;
            _transform = 0;
            _indexIndicator = 0;
            _maxIndexIndicator = _sliderItems.length - 1;
            _step = _itemWidth / _wrapperWidth * 100;
            _stepHeight = _itemHeight / _wrapperHeight * 100;
            _items = [];
            _sliderItems.forEach(function (item, index) {
                _items.push({ item: item, position: index, transform: 0 });
            });
            _addIndicators();
        }

        var _setUpListeners = function () {
            _mainElement.addEventListener('click', _controlClick);
            if (_config.pause && _config.isCycling) {
                _mainElement.addEventListener('mouseenter', function () {
                    clearInterval(_interval);
                });
                _mainElement.addEventListener('mouseleave', function () {
                    clearInterval(_interval);
                    _cycle(_config.direction);
                });
            }

            document.addEventListener('visibilitychange', _handleVisibilityChange, false);
            window.addEventListener('resize', function () {
                var
                    _index = 0,
                    width = parseFloat(document.body.clientWidth);
                _states.forEach(function (item, index, arr) {
                    if (width >= _states[index].minWidth)
                        _index = index;
                });
                if (_index !== _getActive()) {
                    _setActive();
                    _refresh();
                }
            });
        }

        var _addIndicators = function () {
            var sliderIndicators = document.createElement('ol');
            sliderIndicators.classList.add('slider__indicators');
            for (var i = 0; i < _sliderItems.length; i++) {
                var sliderIndicatorsItem = document.createElement('li');
                if (i === 0) {
                    sliderIndicatorsItem.classList.add('active');
                }
                sliderIndicatorsItem.setAttribute("data-slide-to", i);
                sliderIndicators.appendChild(sliderIndicatorsItem);
            }
            _mainElement.appendChild(sliderIndicators);
            _indicatorItems = _mainElement.querySelectorAll('.slider__indicators > li')
        }

        // добавляем индикаторы
        _addIndicators();
        // инициализация
        _setUpListeners();

        if (document.visibilityState === "visible") {
            _cycle(_config.direction);
        }
        _setActive();

        return {
            right: function () {
                _transformItem('right');
            },
            left: function () {
                _transformItem('left');
            },
            stop: function () {
                _config.isCycling = false;
                clearInterval(_interval);
            },
            cycle: function () {
                _config.isCycling = true;
                clearInterval(_interval);
                _cycle();
            }
        }

    }
}());

document.querySelectorAll('.slider').forEach(function (item, index) {
    item.setAttribute('data-slider-id', index);
    var sliderSelector = '[data-slider-id="' + index + '"]';
    var sliderElem = document.querySelector(sliderSelector);
    // если слайдов в слайдере нет, то завершаем текущую работу функции
    if (sliderElem.querySelectorAll('.slider__item').length === 0) {
        return;
    }
    if (
        sliderElem.querySelector('.slider__item').getBoundingClientRect().width *
        sliderElem.querySelectorAll('.slider__item').length >
        sliderElem.querySelector('.slider__wrapper').getBoundingClientRect().width
    ) {
        multiItemSlider('[data-slider-id="' + index + '"]', {
            isCycling: true,
        });
    } else {
        var sliderControls = sliderElem.querySelectorAll('.slider__control');
        for (var i = 0; i < sliderControls.length; i++) {
            sliderControls[i].style.display = 'none';
        }
    }
});
Александр Мальцев
Александр Мальцев
Здравствуйте! Спасибо за отзыв!
Пример решения:
'use strict';
// 1. Добавляем функцию
const isTouchDevice = function () {
  return !!('ontouchstart' in window || navigator.maxTouchPoints);
};
var multiItemSlider = (function () {...}());
document.querySelectorAll('.slider').forEach(function (item, index) {
  // ...
  // 2. Сохраняем инстанс слайдера в константу slider
  const slider = multiItemSlider('[data-slider-id="' + index + '"]', {
    isCycling: true,
  });
  // 3. Добавляем код
  (function (slider, selector) {
      let startY = 0;
      const $slider = document.querySelector(selector);
      if (isTouchDevice()) {
        $slider.addEventListener('touchstart', function (e) {
          startY = e.changedTouches[0].clientY;
        });
        $slider.addEventListener('touchend', function (e) {
          const endY = e.changedTouches[0].clientY;
          const deltaY = startY - endY;
          if (deltaY > 50) {
            slider.left();
          } else if (deltaY < -50) {
            slider.right();
          }
        });
      } else {
        $slider.addEventListener('mousedown', function (e) {
          startY = e.clientY;
        });
        $slider.addEventListener('mouseup', function (e) {
          const endY = e.clientY;
          const deltaY = startY - endY;
          if (deltaY > 50) {
            slider.left();
          } else if (deltaY < -50) {
            slider.right();
          }
        });
      }
      let a = true;
      $slider.addEventListener('wheel', function (e) {
        e.preventDefault();
        if (a === false) {
          return;
        }
        const delta = e.deltaY;
        console.log(delta);
        if (delta > 0) {
          slider.right();
          a = false;
        } else {
          slider.left();
          a = false;
        }
        window.setTimeout(() => {
          a = true;
        }, 300);
      })
    })(slider, '[data-slider-id="' + index + '"]');
  } else {
  // ...
});
SinGlEBW
SinGlEBW
Хотя вот что, при использовании _itemWidth / _wrapperWidth и добавление border блоку wraper будем при каждом слайде всё больше и больше видеть кусок предыдущего слайда. Придётся в slider_item
добавлять flex: 0 0 calc(100% + (2 * бордер_wrapper));

Код предыдущего поста без такой беды. Вот css, почти не пострадал.
*,
::after,
::before {
  box-sizing: border-box;
}

:root {}

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
  color: #fff;
}

.container1 {
  max-width: 1200px;
  margin: 0 auto;
  border: 1px solid #000;
}

.slider1 {
  position: relative;
}

.slider__wrapper1 {
  display: flex;
  overflow: hidden;
}

.slider__item1 {
 flex: 0 0 100%;
 transition: transform 0.6s ease;
}

.slider__content1 {
  height: 250px;
  font-size: 100px;
  padding: 55px 5%;
  text-align: center;
}

.el1 {
  background-color: orange;
}

.el2 {
  background-color: green;
}

.el3 {
  background-color: violet;
}

.el4 {
  background-color: coral;
}

.slider__btn1 {
  width: 50px;
  height: 60px;

  display: none;
  position: absolute;
  z-index: 100;
  top: 50%;
  transform: translateY(-50%);
  transition: all .2s ease-in;
  border: 2px solid darkorchid;
}
.slider__btn--show1{
  display: block;
}

.slider__btn--left1 {
  left: 0px;
}

.slider__btn--right1 {
  right: 0px;
}

.slider__btn--right1:hover {
  background-color: crimson;
}

.slider__btn1::before {
  content: '';
  width: 20px;
  height: 20px;
  display: block;
  position: relative;
  top: 50%;
  left: 50%;
  border-top: 1px solid #000;
  border-left: 1px solid #000;
}

.slider__btn--left1::before {
  transform: translate(-25%, -50%) rotate(-45deg);
}

.slider__btn--right1::before {
  transform: translate(-75%, -50%) rotate(-225deg);
}

SinGlEBW
SinGlEBW
Извините простите но не смог удержаться, даже зарегался. Изучая ваш материал я не понял зачем усложнять код. Посидев и потыкав, уменьшил его в 2е. Хотя JS мне изучать и изучать. Мне интересны тонкости и выслушать опыт, зачем и почему. Создавать функцию в файле понятно, локальная область, но зачем пару строк оборачивать тоже в функцию?

function directedSlider (selector) {
  let
    mainElement = document.querySelector(selector),// основный элемент блока. Нужно это что бы поиск был от него, а не где-то на сайте 
    sliderItemAll = mainElement.querySelectorAll('.slider__item1'),
    sliderBtnLeft = mainElement.querySelector('.slider__btn--left1'), // кнопка "LEFT"
    sliderBtnRight = mainElement.querySelector('.slider__btn--right1'), // кнопка "RIGHT"
    positionItem = 0;

  //Этап 1
  [sliderBtnLeft, sliderBtnRight].forEach((item) => item.addEventListener('click', btnStep))
  //Этап 2
  function btnStep(e){
  
    if(e.target === sliderBtnRight){
    
      if(!sliderBtnLeft.classList.contains('slider__btn--show1'))
      sliderBtnLeft.classList.add('slider__btn--show1')
     
      if(positionItem < sliderItemAll.length - 1){
        positionItem++
      }
      if(positionItem >= sliderItemAll.length - 1){
        sliderBtnRight.classList.remove('slider__btn--show1')
      }
    }
    
    if(e.target === sliderBtnLeft){
      if(!sliderBtnRight.classList.contains('slider__btn--show1'))
        sliderBtnRight.classList.add('slider__btn--show1')
   
      if(positionItem > 0){
        positionItem--
      }
      if(positionItem === 0){
        sliderBtnLeft.classList.remove('slider__btn--show1')
      }
    }

    sliderItemAll.forEach((item, index) => item.style.transform = `translate(${-100 * positionItem}%)`)  
      
  }
}

directedSlider('.slider1')


1. Получил обе кнопки по отдельности и так же их массив. Зачем массив если можно так: [left, Right].forEach()
2. Упаковывать в отдельную функцию цикл раздачи события элементам. Зачем, плодить функции и усложнять код? Где именно такой подход хоть раз себя оправдал?
3. Последовательность взаимодействия с элементами должна описываться в коде в той же последовательности.
Событие вызывает функцию, так значит не нужно где-то в недрах кода это событие присваивать, а перед ним писать
функционал.
4. При событии зачем обращаться снова к элементу через класс, если уже достали этот элемент изначально. Так правильно: e.target === sliderBtnRight
5. Требуется пояснительная бригада для формулы _itemWidth / _wrapperWidth

Выполняя расчёт _itemWidth / _wrapperWidth мы постоянно встречаемся с 0. В чём соль?
Александр Мальцев
Александр Мальцев
Код JavaScript изначально создавался так, чтобы обеспечить работу слайдера именно в режиме зацикливания, а также чтобы он функционировал в устаревших браузерах. После этого он уже дорабатывался для слайдера без зацикливания. Поэтому он, конечно, не оптимизирован конкретно для этой ситуации, да и не вижу в этом смысл. Цель сделать код более универсальным для различных сценариев работы слайдера.

А так ваше стремление сделать код более оптимальным (особенно с использованием новых возможностей языка) — это конечно хорошо. Но пока дальше двигать этот слайдер нет времени. Только комментариев под этой темой 290. Если у кого-то есть желание в этом развиваться, то я только буду рад этому. Можно создать для этой темы отдельный проект на Github (вынести его из how-to). Тем более это очень хорошая практика для изучения JavaScript. Можно будет делать всем вместе. Первая задача – это конечно объединить различные коды JavaScript слайдера в один и сделать его настройку для различных сценариев через параметры. Потом уже переходить к следующим этапам. Если будут желающие улучшать и оптимизировать, то напишите об этом. А если нет, то буду это делать сам, но позже.
Anvar
Anvar
Здравствуйте

Александр Мальцев.

Вапрос!

Из за чего слайдер прекращает прокрутку блоков?(картин с текстом)

Если поменять

.slider__wrapper {
  display: flex;


.slider__item {
  flex: 0 0 100%;

на

.slider__item {
   display: grid;

.slider__wrapper {
  display: grid;
  grid-template-columns: repeat(4,1fr);


полный код



.slider {
  display: grid;		
  position: relative;
  overflow: hidden;
}


.slider__wrapper {
  display: grid;
  grid-template-columns: repeat(4,1fr); 
  transition: transform 0.6s ease; 


}
.slider__item {
  display: grid; 
  max-width: 50%; 

<s></s>



Вапрос!

Из за чего слайдер прекращает прокрутку блоков?

Благодарю за внимание.

Слайдер сделать на CSS Grid так как управлять блоками легче,
можно добовлять убавлять блоки.
grid-template-columns
а также растягивать и сужать блоки
grid-template-columns

Александр Мальцев
Александр Мальцев
Здравствуйте! В этом случае нужно явно указывать ширину блокам в процентах.
Например:
.slider {
  display: grid;
  position: relative;
  overflow: hidden;
}
.slider__wrapper {
  display: grid;
  grid-template-columns: repeat(4, 50%);
  transition: transform 0.6s ease;
}
.slider__item {
  display: grid;
  max-width: 100%;
}
Ola
Ola
Спасибо Вам Огромное Александр что Вы нам помогаете и делитесь с нами своими знаниями!
Вы наш добрый Ангел!***))) Все работает! Как всегда полезный и обьяснен до мелочей чудо-урок!
кстати, все ваши видео на Ютуб также шикарны, я ваш верный подписчик, Спасибо!!!
Александр Мальцев
Александр Мальцев
Спасибо за отзыв! Рад, что полезен.
Ola
Ola
Спасибо Вам Огромное Александр что Вы нам помогаете и делитесь с нами своими знаниями!
Вы наш добрый Ангел!***))) Все работает!!! Как всегда полезный и обьяснен до мелочей чудо-урок!
кстати, все ваши видео на Ютуб также шикарны, я ваш верный подписчик, Спасибо!!!
Artur Zavaziev
Artur Zavaziev
Здравствуйте! Спасибо большое за слайдер!

Я вывел его в шапке и в цикле для постов wordpress (как галерею каждого проекта), в итоге на странице получился основной слайдер в шапке, и слайдеры у каждого поста. Есть проблема в том, что не работает прокрутка слайдов при нажатии ctrl + F5 у слайдеров постов (работает только у слайдера в шапке), или иногда, когда заходишь на страницу впервые. Но стоит просто обновить и все работает, пока снова не завершишь сеанс надолго. В чем может быть проблема? Что-то с кэшем связано? Пробовал вставлять все коды, которые вы тут приводили на проверку наличия слайдов, не помогло. Помогите пожалуйста, заранее благодарю!!!
Александр Мальцев
Александр Мальцев
Здравствуйте! Спасибо!
Попробуйте их инициализировать как показано в этом примере.
Artur Zavaziev
Artur Zavaziev
К сожалению, проблема не решилась, даже наоборот, слайдер в шапке тоже перестает работать. Очень хочется использовать ваш легкий и быстрый слайдер в проектах, только не знаю как решить эту проблему.

Самый близкий к решению сейчас такой код:
(при нем не работает анимация на всех слайдерах после первого слайдера, только в случае первого посещения сайта или обновления путем ctrl f5. Если же зайти на сайт еще раз или просто обновить все работает идеально.)

document.querySelectorAll('.slider').forEach(function (item, index) {
item.setAttribute('data-slider-id', index);
var sliderSelector = '[data-slider-id="' + index + '"]';
var sliderElem = document.querySelector(sliderSelector);

if (sliderElem.querySelectorAll('.slider__item').length === 0) {
return;
}
if (
sliderElem.querySelector('.slider__item').getBoundingClientRect().width *
sliderElem.querySelectorAll('.slider__item').length >
sliderElem.querySelector('.slider__wrapper').getBoundingClientRect().width
) {
multiItemSlider('[data-slider-id="' + index + '"]', {
isCycling: true,
});
} else {
var sliderControls = sliderElem.querySelectorAll('.slider__control');
for (var i = 0; i < sliderControls.length; i++) {
sliderControls[i].style.display = 'none';
}
}
});

Что интересно, если оставить код в таком виде:
document.querySelectorAll('.slider').forEach(function (item, index) {
item.setAttribute('data-slider-id', index);
multiItemSlider('[data-slider-id="' + index + '"]', {
isCycling: true,
});
});

То анимация dots'ов работает при любом раскладе, даже управляются при помощи стрелок слайдера, но картинки не меняются.
Александр Мальцев
Александр Мальцев
Тут однозначно сложно подсказать, может какие-то другие JavaScript плагины, подключенные к странице, на это влияют. Так в коде, который вы привели, всё чётко.

Попробуйте убрать все другие js-скрипты и стили, подключенные к странице, и проверить будут ли работать слайдеры. Если будет всё работать отлично, то тогда нужно искать стили и скрипты, которые мешают работе слайдеров. Если это подтвердится, то тогда (если необходимы стили и скрипты, с которыми идёт конфликт) нужно менять название классов у элементов, а затем внести соответствующие изменения в CSS и JavaScript файлы слайдера (т.е. изменить одни имена классов на другие).
Алексей
Алексей
Добрый день!

Установил на главную страницу сайта (new.avtoshkola.dp.ua) 4 слайдера. И возникли следующие проблемы:

1. Не работает скролл мышкой на десктопе и тапом на телефонах
2. При изменении разрешения экрана (перевернув телефон) карусель неправильно скролится (неверный шаг) и неправильно отображается (часто на половину обрезанные первый и последний слайд)
3. Вторая карусель вообще не работает (возможно проблема что она вместе с первой помещена в табы, первая работает (она в активном табе), а вторая как включаешь таб никак не реагирует).
4. Третья и четвертая карусель. При клике по стрелочке (как назад, так и вперед) пропадают кнопки навигации.

Код скрипта:

'use strict';
    var multiItemSlider = (function () {
      return function (selector, config) {
        var
          _mainElement = document.querySelector(selector), // основный элемент блока
          _sliderWrapper = _mainElement.querySelector('.slider__wrapper'), // обертка для .slider-item
          _sliderItems = _mainElement.querySelectorAll('.slider__item'), // элементы (.slider-item)
          _sliderControls = _mainElement.querySelectorAll('.slider__control'), // элементы управления
          _sliderControlLeft = _mainElement.querySelector('.slider__control_left'), // кнопка "LEFT"
          _sliderControlRight = _mainElement.querySelector('.slider__control_right'), // кнопка "RIGHT"
          _wrapperWidth = parseFloat(getComputedStyle(_sliderWrapper).width), // ширина обёртки
          _itemWidth = parseFloat(getComputedStyle(_sliderItems[0]).width), // ширина одного элемента    
          _positionLeftItem = 0, // позиция левого активного элемента
          _transform = 0, // значение транфсофрмации .slider_wrapper
          _step = _itemWidth / _wrapperWidth * 100, // величина шага (для трансформации)
          _items = []; // массив элементов

        // наполнение массива _items
        _sliderItems.forEach(function (item, index) {
          _items.push({ item: item, position: index, transform: 0 });
        });

        var position = {
          getItemMin: function () {
            var indexItem = 0;
            _items.forEach(function (item, index) {
              if (item.position < _items[indexItem].position) {
                indexItem = index;
              }
            });
            return indexItem;
          },
          getItemMax: function () {
            var indexItem = 0;
            _items.forEach(function (item, index) {
              if (item.position > _items[indexItem].position) {
                indexItem = index;
              }
            });
            return indexItem;
          },
          getMin: function () {
            return _items[position.getItemMin()].position;
          },
          getMax: function () {
            return _items[position.getItemMax()].position;
          }
        }

        var _transformItem = function (direction) {
          var nextItem;
          if (direction === 'right') {
            _positionLeftItem++;
            if ((_positionLeftItem + _wrapperWidth / _itemWidth - 1) > position.getMax()) {
              nextItem = position.getItemMin();
              _items[nextItem].position = position.getMax() + 1;
              _items[nextItem].transform += _items.length * 100;
              _items[nextItem].item.style.transform = 'translateX(' + _items[nextItem].transform + '%)';
            }
            _transform -= _step;
          }
          if (direction === 'left') {
            _positionLeftItem--;
            if (_positionLeftItem < position.getMin()) {
              nextItem = position.getItemMax();
              _items[nextItem].position = position.getMin() - 1;
              _items[nextItem].transform -= _items.length * 100;
              _items[nextItem].item.style.transform = 'translateX(' + _items[nextItem].transform + '%)';
            }
            _transform += _step;
          }
          _sliderWrapper.style.transform = 'translateX(' + _transform + '%)';
        }

        // обработчик события click для кнопок "назад" и "вперед"
        var _controlClick = function (e) {
          if (e.target.classList.contains('slider__control')) {
            e.preventDefault();
            var direction = e.target.classList.contains('slider__control_right') ? 'right' : 'left';
            _transformItem(direction);
          }
        };

        var _setUpListeners = function () {
          // добавление к кнопкам "назад" и "вперед" обрботчика _controlClick для событя click
          _sliderControls.forEach(function (item) {
            item.addEventListener('click', _controlClick);
          });
        }

        // инициализация
        _setUpListeners();

        return {
          right: function () { // метод right
            _transformItem('right');
          },
          left: function () { // метод left
            _transformItem('left');
          }
        }

      }
    }());

    var slider=multiItemSlider('.slider_cars',{});
    var slider=multiItemSlider('.slider_reviews',{});
    var slider=multiItemSlider('.slider_practice',{});
    var slider=multiItemSlider('.slider_theory',{});
Первая карусель (Наша команда, вкладка практика):

<div class="slider slider_practice">
    <div class="slider__wrapper">
      	<div class="slider__item">
        	<div class="team_element">
				<div class="team_image" style="background: url(/wp-content/themes/prospekt/img/maksim.jpg);"></div>
				<div class="team_name h5">Максим</div>
				<div class="person_car team_descr_1">
				    <div class="info_1">Транспортное средство:</div>
				    <div class="info_2">Nissan Leaf (Электро)</div>
				</div>
				<div class="person_exp team_descr_2">
				    <div class="info_1">Стаж вождения:</div>
				    <div class="info_2">14 лет</div>
				</div>
		    </div>
      	</div>

      	...

		<div class="slider__item">
		    <div class="team_element">
				<div class="team_image" style="background: url(/wp-content/themes/prospekt/img/ivan.jpg);"></div>
				<div class="team_name h5">Иван</div>
				<div class="person_car team_descr_1">
				    <div class="info_1">Транспортное средство:</div>
				    <div class="info_2">Chevrolet Aveo МКП</div>
				</div>
				<div class="person_exp team_descr_2">
				    <div class="info_1">Стаж вождения:</div>
				    <div class="info_2">15 лет</div>
				</div>
			</div>
		</div>
	</div>
	<a class="slider__control slider__control_left" href="javascript:void(0);" role="button"></a>
    <a class="slider__control slider__control_right slider__control_show" href="javascript:void(0);" role="button"></a>
</div>
Вторая карусель (Наша команда, вкладка теория):

<div class="slider slider_theory">
    <div class="slider__wrapper">
      	<div class="slider__item">
        	<div class="team_element">
				<div class="team_image" style="background: url(/wp-content/themes/prospekt/img/kristina_2.jpg);"></div>
				<div class="team_name h5">Кристина</div>
				<div class="team_descr_3">
				    <div class="info_1">Адрес:</div>
				    <div class="info_2">ул. Шевченка, 59</div>
				</div>
		    </div>
      	</div>
      						
      	...

      	<div class="slider__item">
        	<div class="team_element">
				<div class="team_image" style="background: url(/wp-content/themes/prospekt/img/marina.jpg);"></div>
				<div class="team_name h5">Марина</div>
				<div class="team_descr_3">
				    <div class="info_1">Адрес:</div>
				    <div class="info_2">ул. Шевченка, 56</div>
				</div>
		    </div>
      	</div>
    </div>
    <a class="slider__control slider__control_left" href="javascript:void(0);" role="button"></a>
    <a class="slider__control slider__control_right slider__control_show" href="javascript:void(0);" role="button"></a>
</div>
Третья карусель (Наши автомобили):

<div class="slider slider_cars">
	 <div class="slider__wrapper">
	     <div class="slider__item">
	        <div class="car_element">
				<div class="car_image" style="background: url(/wp-content/themes/prospekt/img/nissan.jpg);"></div>
				<div class="car_name h5">Nissan Leaf</div>
				<div class="car_descr_1">
					<div class="info_1">Коробка передач:</div>
					<div class="info_2">АКП/Автомат</div>
				</div>
				<div class="car_descr_2">
					<div class="info_1">Кондиционер:</div>
					<div class="info_2">Да</div>
				</div>
				<div class="car_descr_3">
					<div class="info_1">Тип авто:</div>
					<div class="info_2">Электромобиль</div>
				</div>
				<div class="car_descr_4">
					<div class="info_1">Усилитель руля:</div>
					<div class="info_2">Да</div>
				</div>
			</div>
	    </div>
	    
	    ...

	    <div class="slider__item">
	        <div class="car_element">
				<div class="car_image" style="background: url(/wp-content/themes/prospekt/img/dacia.jpg);"></div>
				<div class="car_name h5">Dacia Sandero</div>
				<div class="car_descr_1">
					<div class="info_1">Коробка передач:</div>
					<div class="info_2">МКП/Механика</div>
				</div>
				<div class="car_descr_2">
					<div class="info_1">Кондиционер:</div>
					<div class="info_2">Да</div>
				</div>
				<div class="car_descr_3">
					<div class="info_1">Объем двигателя:</div>
					<div class="info_2">1.4</div>
				</div>
				<div class="car_descr_4">
					<div class="info_1">Усилитель руля:</div>
					<div class="info_2">Да</div>
				</div>
			</div>
	    </div>
	</div>
	<a class="slider__control slider__control_left" href="javascript:void(0);" role="button"></a>
	<a class="slider__control slider__control_right slider__control_show" href="javascript:void(0);" role="button"></a>
</div>
Четвертая карусель (Блок Видео отзывы):

<div class="slider slider_reviews">
	<div class="slider__wrapper">
	    <div class="slider__item">
	        <div class="review_element">
				<iframe width="100%" src="https://www.youtube.com/embed/MohECwj06ww?controls=0" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"></iframe>
			</div>
	    </div>
	    
	    ...
	      				
	     <div class="slider__item">
	        <div class="review_element">
				<iframe width="100%" src="https://www.youtube.com/embed/qoGkLCr-Kj4?controls=0" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"></iframe>
			</div>
	    </div>
	</div>
	<a class="slider__control slider__control_left" href="javascript:void(0);" role="button"></a>
	<a class="slider__control slider__control_right slider__control_show" href="javascript:void(0);" role="button"></a>
</div>
Заранее спасибо
Александр Мальцев
Александр Мальцев
Здравствуйте! Как добавить слайдеру управление тапом можно посмотреть в примерах, которые приведены в комментариях. Оттуда нужно взять соответствующий код и добавить его в свой.
Также в статье и комментариях имеются примеры, в которых показана возможность обновления состояния слайдера при изменении экрана. Из них тоже можно извлечь нужный код и добавить его в свой.

Когда слайдер вы помещаете во вкладки таба, которые в данный момент не показываются. Их следует инициализировать только в тот момент, когда вы её открываете. Примеры работы слайдеров во вкладках имеются в комментариях. Посмотрите, как там это реализовано.

В планах имеется, конечно, сделать единый JavaScript код слайдера с возможностью его настройкой для разных ситуаций с помощью аргументов. Но пока такого кода нет. В данный момент единственным решением будет — это самостоятельно собрать код, который вы хотите из различных примеров.
Sheldon
Sheldon
Здравствуйте. Как сделать чтобы при ресайзе шаг у слайдера не ломался? Когда меняю размер браузера без обновления страницы у меня срабатывает медиа запрос, при котором количество слайдов в видимой области меняется. Шаг слайдера становится не правильным.
Sheldon
Sheldon
Александр Мальцев
Александр Мальцев
Здравствуйте. Добавил такую возможность в скрипт. Слайдер: itchief.ru/examples/lab.php?topic=javascript&file=chiefslider-example-32
Sheldon
Sheldon
Спасибо. Не ожидал что так быстро ответите. Есть ли у вас канал на ютубе? Или другой ресурс, на который можно подписаться?
Sheldon
Sheldon
Еще раз спасибо.
Sheldon
Sheldon
Еще одна проблемка только уже с другим слайдером itchief.ru/examples/lab.php?topic=javascript&file=chiefslider-example-12. Если уменьши количество item'ов в слайдере, например до 4-х, то у слайдера при ресайзе тоже ломается адаптивность. При быстром листании слайдера не успевают подгрузится новые слайды и видно как они появляются. Для того чтобы это увидеть нужно уменьшить высоту .slider__control до 50px.
Александр Мальцев
Александр Мальцев
Пожалуйста! Ссылки на социальные сети и другие ресурсы приведены в футере сайта.
Александр Мальцев
Александр Мальцев
Можно скриншот первой проблемы, чтобы понять в чём она заключается. Вторая проблема заключается в том, что, например, при нажатии вправо, когда количество отображаемых слайдов практически равно их количеству, нам необходимо левый слайд переместить вправо для его отображения там, и в этот момент на его месте ничего не будет, т.е. будет видна «пустота». В этом случае необходимо обеспечить, чтобы количество слайдов в слайдере было больше на 3 чем видимых. В скрипте это пока не реализовано. Сейчас, это можно сделать вручную или посредством кода. Суть тут простая, если, например, у вас 4 слайда, то нужно после их вставить ещё четыре. Т.е. 1 слайд у вас будет на 1 и 5 позициях, 2 слайд – на 2 и 6 и т.д.
Например:
<div class="slider__wrapper">
  <!-- 1 слайдер -->
  <div class="slider__item">...</div>
  <!-- 2 слайдер -->
  <div class="slider__item">...</div>
  <!-- 3 слайдер -->
  <div class="slider__item">...</div>
  <!-- 4 слайдер -->
  <div class="slider__item">...</div>
  <!-- 1 слайдер -->
  <div class="slider__item">...</div>
  <!-- 2 слайдер -->
  <div class="slider__item">...</div>
  ...
</div>
Sheldon
Sheldon
Не знаю как сделать скриншот первой проблемы, вы же ее уже решили. Шаг у слайдера (https://itchief.ru/examples/lab.php?topic=javascript&file=chiefslider-example-2) при ресайзе больше не ломается. Спасибо за ответ.
Дмитрий
Дмитрий
Добрый день, слайдер супер давно его использую в работе! Но сейчас стоит задача слайдер в Табах и уже есть готовый вариант но первая вкладка работает а остальные не отвечают на нажатия стрелок ((( подскажите пожалуйста очень нужна Ваша помощь, пробовал вариант из комментарий не вышло(
		<svg class="hidden">
			<defs>
		<path id="tabshape" d="M80,60C34,53.5,64.417,0,0,0v60H80z"/>
			</defs>
		</svg>
		<div class="container">

	<section>
		<div class="tabs tabs-style-shape">
			<nav>
				<ul>
				<li>
					<a href="#section-shape-1">
					<svg viewBox="0 0 80 60" preserveAspectRatio="none"><use xlink:href="#tabshape"></use></svg>
					<span>до $10 000</span>
					</a>
					</li>
					<li>
					<a href="#section-shape-2">
					<svg viewBox="0 0 80 60" preserveAspectRatio="none"><use xlink:href="#tabshape"></use></svg>
					<svg viewBox="0 0 80 60" preserveAspectRatio="none"><use xlink:href="#tabshape"></use></svg>
					<span>$10 000 - $16 000</span>
					</a>
		            		</li>
					<li>
					<a href="#section-shape-3">		
					<svg viewBox="0 0 80 60" preserveAspectRatio="none"><use xlink:href="#tabshape"></use></svg>
					<svg viewBox="0 0 80 60" preserveAspectRatio="none"><use xlink:href="#tabshape"></use></svg									
					<span>$16 000 - $25 000</span>
					</a>
					</li>
					<li>
					<a href="#section-shape-4">
					<svg viewBox="0 0 80 60" preserveAspectRatio="none"><use xlink:href="#tabshape"></use></svg>
					<svg viewBox="0 0 80 60" preserveAspectRatio="none"><use xlink:href="#tabshape"></use></svg>
					<span>больше $25 000</span>
					</a>
					</li>
					<li>
					<a href="#section-shape-5">
					<svg viewBox="0 0 80 60" preserveAspectRatio="none"><use xlink:href="#tabshape"></use></svg>
					<span>Эксклюзив</span>
					</a>
					</li>
					</ul>
					</nav>
					<div class="content-wrap">
					<section id="section-shape-1">
					<div class="slider">
    					<div class="slider__wrapper">
					<div class="slider__item">
        				<div>
			<p><img src="https://onexport.com/assets/images/front/cars/1.jpg" alt=""></p>
			<div class="iwpmheg">Hyundai Sonata 2014</div>
			<div class="iwpmpricebg">
			<div class="iwpmprice">9500$</div>
				<div class="iwpmpricetext">средня ціна під ключ в Україні</div>
				</div>
			<div class="iwpmukprice">12500$</div>
			<div  class="iwpmria">средня ціна на  <img src="https://onexport.com/assets/images/front/ria.png" alt="" style=" padding-left: 10px; "></div>
			<div class="iwpmmore">більше деталей </div>
		  </div>
      </div>
		<div class="slider__item">
        <div>
			<p><img src="https://onexport.com/assets/images/front/cars/3.jpg" alt=""></p>
			<div class="iwpmheg">Chevrolet Cruze 2016</div>
			<div class="iwpmpricebg">
			<div class="iwpmprice">8700$</div>
				<div class="iwpmpricetext">средня ціна під ключ в Україні</div>
				</div>
			<div class="iwpmukprice">11500$</div>
			<div  class="iwpmria">средня ціна на  <img src="https://onexport.com/assets/images/front/ria.png" alt="" style=" padding-left: 10px; "></div>
			<div class="iwpmmore">більше деталей </div>
		  </div>
      </div>
		<div class="slider__item">
        <div>
			<p><img src="https://onexport.com/assets/images/front/cars/15.jpg" alt=""></p>
			<div class="iwpmheg">Ford focus 2017</div>
			<div class="iwpmpricebg">
			<div class="iwpmprice">8700$</div>
				<div class="iwpmpricetext">средня ціна під ключ в Україні</div>
				</div>
			<div class="iwpmukprice">11500$</div>
			<div  class="iwpmria">средня ціна на  <img src="https://onexport.com/assets/images/front/ria.png" alt="" style=" padding-left: 10px; "></div>
			<div class="iwpmmore">більше деталей </div>
		  </div>
      </div>
		<div class="slider__item">
        <div>
			<p><img src="https://onexport.com/assets/images/front/cars/13.jpg" alt=""></p>
			<div class="iwpmheg">Volkswagen Jetta 2015</div>
			<div class="iwpmpricebg">
			<div class="iwpmprice">9000$</div>
				<div class="iwpmpricetext">средня ціна під ключ в Україні</div>
				</div>
			<div class="iwpmukprice">12000$</div>
			<div  class="iwpmria">средня ціна на  <img src="https://onexport.com/assets/images/front/ria.png" alt="" style=" padding-left: 10px; "></div>
			<div class="iwpmmore">більше деталей </div>
		  </div>
      </div>
    </div>
    <a class="slider__control slider__control_left" href="#" role="button"></a>
    <a class="slider__control slider__control_right slider__control_show" href="#" role="button"></a>
  </div>
						</section>
						<section id="section-shape-2">
												<div class="slider">
    <div class="slider__wrapper">
		<div class="slider__item">
        <div>
			<p><img src="https://onexport.com/assets/images/front/cars/11.jpg" alt=""></p>
			<div class="iwpmheg">Mazda CX-5 2015</div>
			<div class="iwpmpricebg">
			<div class="iwpmprice">15000$</div>
				<div class="iwpmpricetext">средня ціна під ключ в Україні</div>
				</div>
			<div class="iwpmukprice">19500$</div>
			<div  class="iwpmria">средня ціна на  <img src="https://onexport.com/assets/images/front/ria.png" alt="" style=" padding-left: 10px; "></div>
			<div class="iwpmmore">більше деталей </div>
		  </div>
      </div>
		<div class="slider__item">
        <div>
			<p><img src="https://onexport.com/assets/images/front/cars/17.jpg" alt=""></p>
			<div class="iwpmheg">VW Passat B7 2014</div>
			<div class="iwpmpricebg">
			<div class="iwpmprice">11000$</div>
				<div class="iwpmpricetext">средня ціна під ключ в Україні</div>
				</div>
			<div class="iwpmukprice">13000$</div>
			<div  class="iwpmria">средня ціна на  <img src="https://onexport.com/assets/images/front/ria.png" alt="" style=" padding-left: 10px; "></div>
			<div class="iwpmmore">більше деталей </div>
		  </div>
      </div>
		<div class="slider__item">
        <div>
			<p><img src="https://onexport.com/assets/images/front/cars/10.jpg" alt=""></p>
			<div class="iwpmheg">Mazda 6 2017</div>
			<div class="iwpmpricebg">
			<div class="iwpmprice">14000$</div>
				<div class="iwpmpricetext">средня ціна під ключ в Україні</div>
				</div>
			<div class="iwpmukprice">19000$</div>
			<div  class="iwpmria">средня ціна на  <img src="https://onexport.com/assets/images/front/ria.png" alt="" style=" padding-left: 10px; "></div>
			<div class="iwpmmore">більше деталей </div>
		  </div>
      </div>
		<div class="slider__item">
        <div>
			<p><img src="https://onexport.com/assets/images/front/cars/8.jpg" alt=""></p>
			<div class="iwpmheg">Ford Fusion 2015</div>
			<div class="iwpmpricebg">
			<div class="iwpmprice">11000$</div>
				<div class="iwpmpricetext">средня ціна під ключ в Україні</div>
				</div>
			<div class="iwpmukprice">13000$</div>
			<div  class="iwpmria">средня ціна на  <img src="https://onexport.com/assets/images/front/ria.png" alt="" style=" padding-left: 10px; "></div>
			<div class="iwpmmore">більше деталей </div>
		  </div>
      </div>
    </div>
    <a class="slider__control slider__control_left" href="#" role="button"></a>
    <a class="slider__control slider__control_right slider__control_show" href="#" role="button"></a>
  </div>
							</section>
						<section id="section-shape-3"><p>3</p></section>
						<section id="section-shape-4"><p>4</p></section>
						<section id="section-shape-5">
								<div class="slider">
    <div class="slider__wrapper">
		<div class="slider__item">
        <div>
			<p><img src="https://onexport.com/assets/images/front/cars/1.jpg" alt=""></p>
			<div class="iwpmheg">Hyundai Sonata 2014</div>
			<div class="iwpmpricebg">
			<div class="iwpmprice">9500$</div>
				<div class="iwpmpricetext">средня ціна під ключ в Україні</div>
				</div>
			<div class="iwpmukprice">12500$</div>
			<div  class="iwpmria">средня ціна на  <img src="https://onexport.com/assets/images/front/ria.png" alt="" style=" padding-left: 10px; "></div>
			<div class="iwpmmore">більше деталей </div>
		  </div>
      </div>
		<div class="slider__item">
        <div>
			<p><img src="https://onexport.com/assets/images/front/cars/3.jpg" alt=""></p>
			<div class="iwpmheg">Chevrolet Cruze 2016</div>
			<div class="iwpmpricebg">
			<div class="iwpmprice">8700$</div>
				<div class="iwpmpricetext">средня ціна під ключ в Україні</div>
				</div>
			<div class="iwpmukprice">11500$</div>
			<div  class="iwpmria">средня ціна на  <img src="https://onexport.com/assets/images/front/ria.png" alt="" style=" padding-left: 10px; "></div>
			<div class="iwpmmore">більше деталей </div>
		  </div>
      </div>
		<div class="slider__item">
        <div>
			<p><img src="https://onexport.com/assets/images/front/cars/15.jpg" alt=""></p>
			<div class="iwpmheg">Ford focus 2017</div>
			<div class="iwpmpricebg">
			<div class="iwpmprice">8700$</div>
				<div class="iwpmpricetext">средня ціна під ключ в Україні</div>
				</div>
			<div class="iwpmukprice">11500$</div>
			<div  class="iwpmria">средня ціна на  <img src="https://onexport.com/assets/images/front/ria.png" alt="" style=" padding-left: 10px; "></div>
			<div class="iwpmmore">більше деталей </div>
		  </div>
      </div>
		<div class="slider__item">
        <div>
			<p><img src="https://onexport.com/assets/images/front/cars/13.jpg" alt=""></p>
			<div class="iwpmheg">Volkswagen Jetta 2015</div>
			<div class="iwpmpricebg">
			<div class="iwpmprice">9000$</div>
				<div class="iwpmpricetext">средня ціна під ключ в Україні</div>
				</div>
			<div class="iwpmukprice">12000$</div>
			<div  class="iwpmria">средня ціна на  <img src="https://onexport.com/assets/images/front/ria.png" alt="" style=" padding-left: 10px; "></div>
			<div class="iwpmmore">більше деталей </div>
		  </div>
      </div>
    </div>
    <a class="slider__control slider__control_left" href="#" role="button"></a>
    <a class="slider__control slider__control_right slider__control_show" href="#" role="button"></a>
  </div>
						</section>
					</div><!-- /content -->
				</div><!-- /tabs -->
			</section>
	</div>
<!-- скрипт табов -->
<script src="js/cbpFWTabs.js"></script>
		<script>
			(function() {
				[].slice.call( document.querySelectorAll( '.tabs' ) ).forEach( function( el ) {
					new CBPFWTabs( el );
				});
			})();
		</script>
	<!-- скрипт табов закончен -->
	<!--скрипт слайдера -->
<script>
    'use strict';
    var multiItemSlider = (function () {
      return function (selector, config) {
        var
          _mainElement = document.querySelector(selector), // основный элемент блока
          _sliderWrapper = _mainElement.querySelector('.slider__wrapper'), // обертка для .slider-item
          _sliderItems = _mainElement.querySelectorAll('.slider__item'), // элементы (.slider-item)
          _sliderControls = _mainElement.querySelectorAll('.slider__control'), // элементы управления
          _sliderControlLeft = _mainElement.querySelector('.slider__control_left'), // кнопка "LEFT"
          _sliderControlRight = _mainElement.querySelector('.slider__control_right'), // кнопка "RIGHT"
          _wrapperWidth = parseFloat(getComputedStyle(_sliderWrapper).width), // ширина обёртки
          _itemWidth = parseFloat(getComputedStyle(_sliderItems[0]).width), // ширина одного элемента
          _positionLeftItem = 0, // позиция левого активного элемента
          _transform = 0, // значение транфсофрмации .slider_wrapper
          _step = _itemWidth / _wrapperWidth * 100, // величина шага (для трансформации)
          _items = [], // массив элементов
          _interval = 0,
          _config = {
            isCycling: false, // автоматическая смена слайдов
            direction: 'right', // направление смены слайдов
            interval: 5000, // интервал между автоматической сменой слайдов
            pause: true // устанавливать ли паузу при поднесении курсора к слайдеру
          };

        for (var key in config) {
          if (key in _config) {
            _config[key] = config[key];
          }
        }

        // наполнение массива _items
        _sliderItems.forEach(function (item, index) {
          _items.push({ item: item, position: index, transform: 0 });
        });

        var position = {
          getItemMin: function () {
            var indexItem = 0;
            _items.forEach(function (item, index) {
              if (item.position < _items[indexItem].position) {
                indexItem = index;
              }
            });
            return indexItem;
          },
          getItemMax: function () {
            var indexItem = 0;
            _items.forEach(function (item, index) {
              if (item.position > _items[indexItem].position) {
                indexItem = index;
              }
            });
            return indexItem;
          },
          getMin: function () {
            return _items[position.getItemMin()].position;
          },
          getMax: function () {
            return _items[position.getItemMax()].position;
          }
        }

        var _transformItem = function (direction) {
          var nextItem;
          if (direction === 'right') {
            _positionLeftItem++;
            if ((_positionLeftItem + _wrapperWidth / _itemWidth - 1) > position.getMax()) {
              nextItem = position.getItemMin();
              _items[nextItem].position = position.getMax() + 1;
              _items[nextItem].transform += _items.length * 100;
              _items[nextItem].item.style.transform = 'translateX(' + _items[nextItem].transform + '%)';
            }
            _transform -= _step;
          }
          if (direction === 'left') {
            _positionLeftItem--;
            if (_positionLeftItem < position.getMin()) {
              nextItem = position.getItemMax();
              _items[nextItem].position = position.getMin() - 1;
              _items[nextItem].transform -= _items.length * 100;
              _items[nextItem].item.style.transform = 'translateX(' + _items[nextItem].transform + '%)';
            }
            _transform += _step;
          }
          _sliderWrapper.style.transform = 'translateX(' + _transform + '%)';
        }

        var _cycle = function (direction) {
          if (!_config.isCycling) {
            return;
          }
          _interval = setInterval(function () {
            _transformItem(direction);
          }, _config.interval);
        }

        // обработчик события click для кнопок "назад" и "вперед"
        var _controlClick = function (e) {
          if (e.target.classList.contains('slider__control')) {
            e.preventDefault();
            var direction = e.target.classList.contains('slider__control_right') ? 'right' : 'left';
            _transformItem(direction);
            clearInterval(_interval);
            _cycle(_config.direction);
          }
        };

        var _setUpListeners = function () {
          // добавление к кнопкам "назад" и "вперед" обрботчика _controlClick для событя click
          _sliderControls.forEach(function (item) {
            item.addEventListener('click', _controlClick);
          });
          if (_config.pause && _config.isCycling) {
            _mainElement.addEventListener('mouseenter', function () {
              clearInterval(_interval);
            });
            _mainElement.addEventListener('mouseleave', function () {
              clearInterval(_interval);
              _cycle(_config.direction);
            });
          }
        }

        // инициализация
        _setUpListeners();
        _cycle(_config.direction);

        return {
          right: function () { // метод right
            _transformItem('right');
          },
          left: function () { // метод left
            _transformItem('left');
          },
          stop: function () { // метод stop
            _config.isCycling = false;
            clearInterval(_interval);
          },
          cycle: function () { // метод cycle
            _config.isCycling = true;
            clearInterval(_interval);
            _cycle();
          }
        }

      }
    }());

    var slider = multiItemSlider('.slider', {
      isCycling: true
    })

  </script>
	<!-- скрипт слайдера закончен-->
AriYeS
AriYeS
Александр, Здравствуйте, спасибо за ваши примеры слайдеров, всё понятно и доступно. Взял у вас на вооружение следующий слайдер itchief.ru/examples/lab.php?topic=javascript&file=chiefslider-example-29
Но у меня есть вопрос, мне нужно, чтобы элементы управления не находились непосредственно на слайдах, с помощью стилей я эту проблему сам не смог решить(пробовал убрать абсолютную позицию, но они расширяют родителя и слайдов начинает становиться больше чем 3(это я убирал max-width и flex), либо сами слайды становятся больше чем мне нужно(это если не трогать max-width и flex), вся проблема в том, что slider-item плевать хотели на своего родителя, его уменьшать бесполезно, наоборот, только вредит и не приносит желаемого результата, пробовал вытащить элементы из родительского каталога и редактировать js, но ничего адекватного достичь, увы, не смог(просто не знаю синтаксис языка), пробовал грубо создать глобальную переменную которая бы определяла кнопки в вашем скрипте, но так как слайдеров мне нужно три штуки такой метод вдвойне нецелесообразен. Помогите решить проблему, пожалуйста
Александр Мальцев
Александр Мальцев
Здравствуйте! Так там же есть методы left и right. Используйте их для управления слайдами, а код, связанный с этими кнопками, тогда в принципе вообще можно удалить. Например, можно сделать так.
AriYeS
AriYeS
О, об этом я почему то не подумал, спасибо)
Володя
Володя
Здраствуйте) возникла проблема слайдер работает тольлько если он на влазит на весь екран… если прокрутить к приверу чуть ниже — чтобы была половина слайдера видна — перестают работать кнопки и сам слайдер не показывает слайды в цикле…
Александр Мальцев
Александр Мальцев
Добрый день! Посмотрите ответ в этом комментарии.
Александр
Александр
Здравствуйте! Спасибо за слайдер, это реально чудо, поставил уже на нескольких своих проектах. Сейчас возникла такая проблемка — есть скрипт LazyLoad для картинок, и он грузится чуть позже скрипта слайдера, в итоге как я понял — слайдер изначально определяет свою высоту по содержимому и высоте картинок, и с включенным lazyload он не успевает понять высоту картинки и в итоге под слайдером и картинкой получается большой оступ. Как это можно решить без изменения порядка подгрузки скриптов? Пробовал в стилях задавать контейнеру высоту в px, тогда это спасает от части, но все равно кривовато, т.к картинки бывают разные по высоте. Надеюсь внятно объяснил)
Александр Мальцев
Александр Мальцев
Здравствуйте!
Слайдер выполняет расчёты с шириной, высота картинки тут не важна.
С настройкой картинок не вижу никаких проблем.
Например, можно задать размеры картинкам с помощью атрибутов width и height. А также им установить с помощью атрибута src изображение, которое будет отображаться до загрузки основной картинки.
<img class="slider__content_img lazy" src="/examples/images/s-0.png" data-src="/examples/images/s-6.jpg" alt="" width="500" height="281">
Пример слайдера с ленивой загрузкой изображений, которая выполнена с использованием плагина Lazyload.

Если картинки имеют разное соотношение сторон, то их на сервере нужно приводить к какому-то одному значению или использовать их в качестве background.

Как это выглядит (отключен кэш и выбран Slow 3G): yadi.sk/i/LxKU0xMRw_pbLw
kadochnikov_k
kadochnikov_k
Добрый день! Столкнулся с такой проблемой: в слайдер с индикаторами добавил код, приведенный ниже, и индикаторы перестают правильно работать (в моем случае активным всегда остается первый индикатор, хотя переключение по индикаторам происходит нормально). Не могу понять, почему?
Код, который я добавляю:
document.querySelectorAll('.slider').forEach(function (item, index) {
item.setAttribute('slider-id', index);
multiItemSlider('[slider-id="' + index + '"]'); {
var sliderSelector = '[slider-id="' + index + '"]';
var sliderElem = document.querySelector(sliderSelector);
if (sliderElem.querySelector('.slider__item').getBoundingClientRect().width * sliderElem.querySelectorAll('.slider__item').length >= sliderElem.querySelector('.slider__wrapper').getBoundingClientRect().width) {
// слайдов больше, чем на экране

var slider = multiItemSlider('[slider-id="' + index + '"]', {
isCycling: true
})
} else {
// слайдов меньше, чем на экране
// удалить slider__control_show

var sliderControls = sliderElem.querySelectorAll('.slider__control');
for (var i = 0; i < sliderControls.length; i++) {
sliderControls[i].style.display = 'none';
}
}
}
});
Александр Мальцев
Александр Мальцев
Здравствуйте! В коде происходит лишняя инициализация слайдера.
Попробуйте сделать так:
document.querySelectorAll('.slider').forEach(function (item, index) {
  item.setAttribute('data-slider-id', index);
  // multiItemSlider('[slider-id="' + index + '"]');
  var sliderSelector = '[data-slider-id="' + index + '"]';
  var sliderElem = document.querySelector(sliderSelector);
  if (sliderElem.querySelector('.slider__item').getBoundingClientRect().width * sliderElem.querySelectorAll('.slider__item').length > sliderElem.querySelector('.slider__wrapper').getBoundingClientRect().width) {
    // слайдов больше, чем на экране
    multiItemSlider('[data-slider-id="' + index + '"]', {
      isCycling: true
    });
  } else {
    // слайдов меньше, чем на экране
    // удалить slider__control_show
    var sliderControls = sliderElem.querySelectorAll('.slider__control');
    for (var i = 0; i < sliderControls.length; i++) {
      sliderControls[i].style.display = 'none';
    }
  }
});
kadochnikov_k
kadochnikov_k
Спасибо огромное, все заработало!
kadochnikov_k
kadochnikov_k
Добрый день! В процессе использования слайдера столкнулся с такой проблемой: если на странице несколько слайдеров и в одном из них по каким то причинам нет слайдов, то слайдеры ниже перестают работать (им не присваиваются id, но даже если их присвоить то слайдеры не инициализируются). Никак не могу понять в чем дело, может быть вы подскажите?
Александр Мальцев
Александр Мальцев
Здравствуйте!
Для этого добавьте условие для проверки наличия слайдов в слайдере:
document.querySelectorAll('.slider').forEach(function (item, index) {
  item.setAttribute('data-slider-id', index);
  var sliderSelector = '[data-slider-id="' + index + '"]';
  var sliderElem = document.querySelector(sliderSelector);
  // если слайдов в слайдере нет, то завершаем текущую работу функции
  if (sliderElem.querySelectorAll('.slider__item').length === 0) {
    return;
  }
  if (
    sliderElem.querySelector('.slider__item').getBoundingClientRect().width *
      sliderElem.querySelectorAll('.slider__item').length >
    sliderElem.querySelector('.slider__wrapper').getBoundingClientRect().width
  ) {
    multiItemSlider('[data-slider-id="' + index + '"]', {
      isCycling: true,
    });
  } else {
    var sliderControls = sliderElem.querySelectorAll('.slider__control');
    for (var i = 0; i < sliderControls.length; i++) {
      sliderControls[i].style.display = 'none';
    }
  }
});
РУСЛАН
РУСЛАН
Добрый вечер, а как реализовать, чтоб реагировал пролистование через сенсорные экраны, а то не могу найти решение а у вас сделоно отлично. Спасибо за рание за совет.
Александр Мальцев
Александр Мальцев
Здравствуйте! В этом комментарии есть решение как это выполнить.
РУСЛАН
РУСЛАН
Спасибо огромное))
Mihail
Mihail
Александр добрый день. Я к Вам ранее обращался, Вы мне очень помогли с вопросом. Спасибо еще раз. У меня возникла проблема никак не могу ее решить. В комментариях я нашел очень хороший пример слайдера как раз тот, что мне нужен.
https://itchief.ru/examples/lab.php?topic=javascript&file=chiefslider-example-19 
Но в этом примере есть проблема. Мне необходимо .slider__item с 100% уменьшить до 33.333333%; Это получается! Но когда нажимаешь на пагинацию до конца все кнопки, там на половине пустые слайды показываются. Я видел примеры другие где на слайдере по 3 slider__item и пагинация работает исправна, НО МНЕ НУЖНА ПОМОЩЬ ИМЕННО В ЭТОМ ПРИМЕРЕ. Тут боковые слайды как раз именно так выглядят как мне нужно (на половину спрятаны). ЗАРАНЕЕ ВАМ БОЛЬШОЕ СПАСИБО!!! Мне кажется что тут в самом скрипте нужно исправить где то код. Прошу помощи. Мне необходимо чтобы не было пустых окон в слайде, чтобы он зациклено «шел».

.slider__item {
flex: 0 0 33.333333%;
max-width: 33.333333%;
}
Mihail
Mihail
Добрый день! Вопрос снимаю. Прошу прощения, что отвлек. Тупанул. Просто не добавил зацикливание.
VLADIMIR BULANOV
VLADIMIR BULANOV
Здравствуйте! Наконец, нашел нормальное руководство по слайдерам без «скачайте наш плагин или ничего не получится!»)) Отличные примеры, все гуд, но столкнулся с проблемой:
В моем слайдере возможно динамическое изменение HTML кода в слайдах, из-за этого обычный метод _refresh не совсем подходит… (в частности, я «налопатил» уже каким то образом до того, что при изменении хтмл у меня трансформации слайдов «улетают» в рандомных направлениях, делая слайдер неюзабельным пока не обновишь страницу).

Что я ищу — это метод, который полностью «убивает» скрипт слайдера и инициализирует его по-новой, на основе нового DOM внутри. Можете подсказать что-нибудь? Спасибо!
Александр Мальцев
Александр Мальцев
Привет!
Можно просто добавить метод destroy, который будет удалять всё что связано с этим слайдером, т.е. его HTML код и обработчики событий. Пример, в котором показано как это можно сделать. Далее вам необходимо после вставки нового HTML кода на страницу заново инициализировать его обычным способом.
Павел
Павел
Добрый день! Буду очень признателен если найдете время на ответ. Подскажите пожалуйста, каким образом реализовать автопрокрутку первого слайдера?
Александр Мальцев
Александр Мальцев
Привет! Взять слайдер с автопрокруткой, например, 3-ий по порядку в статье и изменить у него CSS так, чтобы в текущий момент показывался только один слайд:
.slider__item {
  flex: 0 0 100%;
  max-width: 100%;
}
stas452
stas452
Добрый день! Слайдер отличный, спасибо большое, но если размещать его в popup окне, картинки не меняют размера при смене экрана, то есть не адаптивны, но при этом popup окно полностью адаптивно, можете подсказать как можно решить проблему? Заранее большое спасибо!

PS: пробовал
.slider__item background-image {
display: block;
max-width: 100%;
height: auto;
}

Ничего не выходило(
Александр Мальцев
Александр Мальцев
Добрый день! Вам необходимо инициализировать слайдер после открытия popup окна. Если вы будете делать это до открытия popup, то слайдер не будет работать, т.к. он не может рассчитать размеры элементов, т.к. они ещё не известны.
stas452
stas452
Всё отлично, а как мне его инициализировать? (СЛАЙДЕР)
Александр Мальцев
Александр Мальцев
Вам необходимо в обработчик события после того как окно будет показано добавить код:
const slider = multiItemSlider('.slider');
stas452
stas452
// инициализация
_setUpListeners();

return {
right: function () { // метод right
_transformItem('right');
},
left: function () { // метод left
_transformItem('left');
}
const slider = multiItemSlider('.slider');
const slider = multiItemSlider('.slider');

}

Так не сработало(
Александр Мальцев
Александр Мальцев
Не знаю, это зависит от того, как у вас реализовано popup окно. Сделайте пример на jsFiddle или посмотрите вот эту реализацию слайдера в popup окне. Кроме этого, в комментариях ещё много других примеров, может там уже есть то, что вы ищите.
stas452
stas452
Я могу вам предоставить код? Можете мне как-то помочь в этом? Сам popup адаптивный под моб.устройста, а вот слайдер внутри него нет, и пример который вы прикрепили тоже не то, уже больше недели не могу найти решение проблемы, всё бы ничего а заказчик ждёт, буду очень признателен вам! Заранее спасибо большое!
Александр Мальцев
Александр Мальцев
Предоставьте на jsFiddle эту часть страницы.
stas452
stas452
jsfiddle.net/yf9n530t/

Вот пожалуйста, этого вам хватит?
Прошу обратить внимание что без слайдера, внутри popup окна, картинки адаптивны.
Александр Мальцев
Александр Мальцев
Нет, вам нужно собрать текущий вариант части страницы, состоящий из popup окна и слайдера с картинками. Причём он должен иметь такой же функционал как у вас на сайте. Другого контента, который у вас есть на странице предоставлять не надо. Т.е. в результате на jsfiddle.net необходимо создать полностью рабочий мини пример этой ситуации без всего лишнего. Так вообще желательно делать, когда вы к кому-то обращаетесь за советом.
Виктор
Виктор
Доброго времени суток!
Александр, помогите пожалуйста разобраться как разместить 2 карусели (одну под другой) с одним элементом управления (карусели должны быть адаптивные и менять количество отображаемых файлов в зависимости от ширины окна). Js только начал изучать и пока не понимаю всю логику заложенную в скрипт, а карусель очень хочется разместить на сайте.
Правильно ли я понимаю что для отключения зацикливания во все isCycling необходимо прописать false? А что сделать для отключения автопрокрутки?
Александр Мальцев
Александр Мальцев
Привет!
В этом комментарии есть подобный пример. А настройка количество отображаемых слайдов в зависимости от ширины окна описана в статье. Она осуществляется через медиа запросы, JavaScript тут не нужен.

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

Параметр isCycling нужен для включения режима автоматического смена слайдов. Т.е. если он false, то слайды автоматически меняться не будут. А если true, то через определённое время определяемым параметром interval.
stas452
stas452
Александр, здравствуйте, вышла такая проблема, при дублирование кода слайдера, на втором перестают работать кнопки и при клике кидает на главную страницу сайта, есть решение проблемы? Ибо нужно чтобы слайдер был в нескольких местах страницы и с разными картинками внутри, заранее спасибо!
Александр Мальцев
Александр Мальцев
Здравствуйте! Можно хоть сколько слайдеров создать на странице. Вот пример с 2 слайдерами.
stas452
stas452
Огромное спасибо!
Владимир
Владимир
Здравствуйте, спасибо Вам большое за слайдеры, всё очень круто и качественно работает!!! Если не затруднит, подскажите, пожалуйста, как сделать в «Адаптивный слайдер с зацикливанием» точки-переключатели (dots). Заранее благодарю!
Александр Мальцев
Александр Мальцев
Здравствуйте! Спасибо за отзыв!
Для этого нужно в него перенести соответствующий код из другого слайдера в котором он имеется. Если ничего не упустил, то держите пример.
Владимир
Владимир
Всё работает, благодарю!
Владимир
Владимир
Доброго времени суток! Спасибо большое за слайдер, очень помогли. Но у меня возникла одна проблема: я воспользовался кодом из «Слайдер с зацикливанием и автоматической сменой слайдов», всё работает отлично, но в IE 11 данный слайдер не работает. Нет никаких ошибок, просто не работает. Подскажите, пожалуйста, как это вылечить. Буду очень благодарен. Нужна поддержка IE 10+.
Владимир
Владимир
Прошу прощения, уже нашёл ответ в комментариях.
Ilya Smolin
Ilya Smolin
Здравствуйте, спасибо за слайдер, но возникла проблема, есть довольно много контента на слайдере (высота 900px) и когда стоишь ровно по центру или чуть ниже то слайдер не листает, а листает только в начале контента. Что мне необходимо изменить чтоб он работал? Заранее спасибо

прикрепил скриншот

<img
src=«https://itchief.ru/assets/uploadify/0/8/d/08d470c30f423a4db8b64001b89e967bs.jpg» class=«fancybox thumbnail center»>
Александр Мальцев
Александр Мальцев
Здравствуйте! Замените в JavaScript коде реализацию функции _isElementVisible на эту:
function _isElementVisible(element) {
  var position = element.getBoundingClientRect();
  if ((position.top >= 0 && position.bottom <= window.innerHeight) || (position.top < window.innerHeight && position.bottom >= 0)) {
    return true;
  }
  return false;
}
Святослав
Святослав
Здравствуйте, помогите пожалуйста разобраться, как мне изменить расположение индикаторов, так как оно находится в скрипте не понимаю как им поменять расположение в блоке слайдера.
Святослав
Святослав
Спасибо вам Александр, разобрался. Вопрос снят.
Денис
Денис
Попробуйте добавить в стили что-то из серии
.slider__indicators {
position: absolute;
top: 0px;
}
Святослав
Святослав
Денис спасибо за ответ. уже разобрался.
Денис
Денис
Доброго времени суток! Огромное спасибо Вам за сайт в целом и слайдер в частности!
К сожалению, моей квалификации не хватает, чтобы по достоинству оценить всю его прелесть, но, надеюсь, что это временно…
Подскажите, пожалуйста, каким образом можно модифицировать код, что бы он работал следующим образом:
— на странице находится произвольное количество слайдеров (например, 10). Между слайдерами размещен произвольный контент.
— количество элементов в каждом слайдере — одинаковое.
— элементы управления есть только на одном (первом слайдере).
— использование элементов управления на этом слайдере влияет на содержание всех остальных слайдеров — содержание меняется на всех слайдерах сразу.
Спасибо большое заранее!
Александр Мальцев
Александр Мальцев
Здравствуйте! Вам просто нужно по-другому инициализировать слайдеры, чтобы всё работало. Пример кода имеется в этом комментарии.
Денис
Денис
Либо лыжи не едут… ткните, глупому, пальцем, пожалуйста, куда вставлять код из этого комментария? и да… если я правильно все понимаю, то код на гите отличается от того, который вы приводите в качестве примеров… может быть в этом проблема?
Александр Мальцев
Александр Мальцев
Да, не то подсказал.
Вот пример.
Владимир
Владимир
Здравствуйте, я новичок и не понимаю как сделать к этому примеру еще и чтобы при наведении на основной слайдер с навигацией другие слайдеры тоже переставали листаться, подскажите пожалуйста.
Александр Мальцев
Александр Мальцев
Здравствуйте! Код для реализации этого функционала добавил в конец скрипта. Пример расположен здесь.
Денис
Денис
Огонь! Все прям как нужно! Спасибо за решение! Скажите, а как теперь их запихать в разные вкладки (бутстраповские). Пробовал сюда приделать решение из этого поста, но оно никак не хочет работать… все-таки магия js для меня непостижима(((
Владимир
Владимир
Спасибо, все работает
Александр Мальцев
Александр Мальцев
Пример, в котором показано как слайдеры можно поместить в разные бутстраповские вкладки.
Денис
Денис
Спасибо огромное! Все работоет как нужно. Почему сам не догадался — непонятн((( Но зато, немного переделал, что бы оно динамически определяло количество вкладок и вызывало функцию инициализации для каждой. Еще раз огромное спасибо!
Егор
Егор
Александр, спасибо за прекрасный ресурс и невероятно функциональные примеры кодов. Данный слайдер отлично работает в современных браузерах (Chrome), но встал вопрос по пользователям IE 11… В этом старом браузере не работает листание (ни авто, ни кликом). Буду очень признателен за любые советы в данном направлении!

UPDATE
Нашел ответ в комментариях. Просто супер!
Спасибо!
Александр Мальцев
Александр Мальцев
Отлично! Рад что всё получилось.
Андрей
Андрей
Добрый день! Спасибо за слайдер, редко такое решение найдешь. Перекопал уже штук 20))

Вопрос. Есть сайт 60-100 страниц на pug/sass. Слайдер используется не на всех. И если на странице скрипт слайдера не находит ".slider__wrapper" или другие классы слайдера, то я получаю ошибку «Cannot read property 'querySelector' of null». При этом формы обратной связи и старые slick слайдеры перестают работать.

Как это исправить? Я так понимаю нужно сделать проверку наличия слайдера на странице и только после инициализировать слайдер? Но пока в js плохо ориентируюсь. Подскажите, пожалуйста)
Александр Мальцев
Александр Мальцев
Добрый день!
Вам необходимо просто проверить если ли элемент на странице и только после этого выполнять уже его инициализацию:
if (document.querySelectorAll('.slider').length) {
  multiItemSlider('.slider');
}
Андрей
Андрей
Спасибо! То есть код можно прочитать примерно так: Если в документе у всех селекторов .slider есть хотя бы один символ содержимого, то для них инициализируем Слайдер. Верно?

Очень благодарен за ваш подход не только с готовыми решениями, но и объяснением смыслов!
Александр Мальцев
Александр Мальцев
Да, вы просто проверяете с помощью length количество элементов с классом slider на странице и выполняете инструкцию инициализации только тогда, когда их найдено больше 0. Сравнение с 0 в данном случае можно опустить, поэтому в примере его указывать не стал.
if (document.querySelectorAll('.slider').length > 0) {
  multiItemSlider('.slider');
}
bc
bc
Привет! Отличный слайдер! Можете подробнее рассказать как получить текущий правый элемент в карусели? Никак не могу сообразить почему так, как у вас получаете.
Александр Мальцев
Александр Мальцев
Привет! Спасибо! Наиболее просто это выполнить — это добавить в скрипт какую-то переменную для хранения значения (индекса) правого слайда. Зная текущее количество активных слайдов это значение можно очень просто вычислить.
bc
bc
PositionItemLeft++
If( positionItemLeft + wrapperItem / itemWidth — 1)
То есть в строке выше получаем значение позиции крайнего правого? Каким образом, расскажите и зачем PositionItemLeft++ каждый раз увеличивать на 1?
Александр Мальцев
Александр Мальцев
Потому что, когда мы сдвигаем слайдер вправо, левый элемент в ней уже будет тот который имеет индекс 2. Далем этого для того, чтобы знать какой слайдер сейчас расположен слева. С помощью выражения (positionItemLeft + wrapperItem / itemWidth — 1) вычисляем индекс крайнего правого слайда.
sasdfasdf
sasdfasdf
Здравствуйте как сделать слайдер адаптивным? Вот код jsfiddle.net/5rvsgp80/
Если изменить ширину экрана и изменить количество видимых элементов, то слайдер не меняет значение ширины.
Александр Мальцев
Александр Мальцев
Здравствуйте! Для этого необходимо добавить событие onresize для window. Пример такого скрипта можете посмотреть в этом слайдере.
adfadsfadsfsad
adfadsfadsfsad
не работает, то же самое jsfiddle.net/e7nkwc5h/2/
sasdfasdf
sasdfasdf
не работает, я не знаю уже как там и что исправлять jsfiddle.net/wo42jqbu/
Александр Мальцев
Александр Мальцев
Вы хотите программно менять количество видимых элементов после смены ширины или как? Ширина слайдера всегда равна 100% доступной ширины контейнера, в котором он расположен. Сами слайды задаются в процентом отношении. Адаптивность настраивается с помощью медиа запросов. Покажите то, что вы хотите на скриншоте.
adfadsfadsfsad
adfadsfadsfsad
Я хотел вот так jsfiddle.net/euqp4v6r/. Код работает, но иногда, при ширине экрана меньше 576px,
и при максимальной возможной, слайдер не скидывает значение ширины, а берет прежние, и получается, что не ровно, слайды идут.

вот фото itchief.ru/assets/uploadify/9/2/7/92706e8dfd4c1fc8630b317ace8783d9.png
Александр Мальцев
Александр Мальцев
Понятно. Скрипт поправил: jsfiddle.net/itchief/rvdjmybx/
adfadsfadsfsad
adfadsfadsfsad
БОЛЬШОЕ СПАСИБО!!!
Mihail
Mihail
Добрый день Александр. Спасибо Вам огромное за Ваш пример слайдера. Помогите, пожалуйста решить пару вопросов по его работе.

Я выбрал из вашего комментария, как Вы написали возможность добавления автоматически каждому слайдеру id:
document.querySelectorAll('.slider').forEach(function(item, index){ 
  item.setAttribute('slider-id', index);
  multiItemSlider('[slider-id="'+ index +'"]');
});
В данном случае возникают ошибки:
1. На первом слайде добавляется 2 раза <ol> и кнопки пагинации у этого слайдера отрабатывают не корректно.
2. Сейчас у всех слайдеров пропала возможность автосмены слайдов.
Как задать в таком случае условие, чтобы допустим у слайда с id=«0» и с id=«2» была возможность автоматической смены слайдов (зацикленная)?

PS. Я выбрал пример с пагинацией, добавил вашу возможность:

1. Зацикливания.
2. Прокрутку слайдов touch.
Благодарю Вас за помощь. Заранее большое спасибо

ВЕСЬ КОД ПРИМЕРА:
<div class="slider">...</div>
<div class="slider">...</div>
<div class="slider">...</div> 

<script>
...
document.querySelectorAll('.slider').forEach(function(item, index){ 
  item.setAttribute('id', index);
  multiItemSlider('[id="'+ index +'"]');
});
// Инициализация слайдера осуществляется следующим образом
var slider = multiItemSlider('.slider', {
  isCycling: true
});
</script>
Александр Мальцев
Александр Мальцев
Здравствуйте!
Это можно сделать так:
1. Сначала просто добавьте к слайдерам id:
document.querySelectorAll('.slider').forEach(function (item, index) {
  item.id = 'slider-' + index;
});
2. Инициализируйте их каждый так, как вам это необходимо (через id):
var slider0 = multiItemSlider('#slider-0', {
  isCycling: true
});
var slider1 = multiItemSlider('#slider-1', {
  isCycling: false
});
var slider2 = multiItemSlider('#slider-2', {
  isCycling: true
});
Mihail
Mihail
Александр добрый день! Все заработало!!! Спасибо Вам огромное!!! Первый и второй пункт заработал. Скажите пожалуйста этот скрипт никак не конфликтует с 1С Битриксом!? Изначально не сразу срабатывает. Спустя время как будто скрипт адаптируется… Я когда его в первый раз поставил без дополнительных возможностей он отказывался работать и кнопки погинации не работали. Отработали чуть позже. Сейчас в этом посте Ваш ответ на пункт 1 и 2 тоже исправил не сразу отработал скрипт, а спустя время. При чем КЭШ чистил. Скрипт подключен после библиотеки JQUERY в самом низу. Понимаю что этот скрипт никак не задействован с jquery, но все же может кто то писал до меня Вам про аналогичные проблемы с 1 С Битрикс!??? СПАСИБО ЕЩЕ РАЗ!!!
Александр Мальцев
Александр Мальцев
Здравствуйте!
Оберните весь код, включаю функцию в следующую конструкцию:
(function(){
  ...
})();
Это исключит создание переменных в глобальной области видимости. Если есть какие-то конфликты, то это должно их убрать.
Также попробуйте перезагрузить страницу с помощью Ctrl+F5. Это позволит сделать это с очисткой её кэша в браузере.
Mihail
Mihail
Огромное Вам Спасибо!!! Это действительно помогло
Артём Валерьевич
Артём Валерьевич
Здравствуйте! Спасибо за статью! В веб-разработке не силен, поэтому прошу помощи.
Интересует два вопроса:
1. Возможно ли добавить подписи под изображениями?
2. При подключении слайдера появляется куча пустого места под футером. Скрины прилагаю
2.1. проблемная страница
2.2. нормальная страница
Александр Мальцев
Александр Мальцев
Здравствуйте!
Конечно, можно. Вот пример.
Если под слайдером появляется пустое место, то нужно посмотреть стили. Может у вас какие-нибудь элементы имеют такое же названия классов как используются в этом слайдере. Тут нужно открыть инспектор элементов в браузере и посмотреть, из-за чего это.
Данияр
Данияр
Здравствуйте!

Опять вернулся к этому классному слайдеру)

В общем, мне надо сделать три вещи на слайдере состоящим из одного слайда на весь экран:
1. Поставить номер слайда формата 01/03, чтобы он оставался при изменении слайдера;
2. Сделать как-бы заполнение индикатора в зависимости от времени до завершения слайда. То есть чтобы индикатор заполнялся цветом в зависимости от времени;
3. Поставить анимацию переходов как здесь: codepen.io/ashthornton/full/ZmxaWv (там же и меняются цифры также как мне и надо).

Можете посоветовать пожалуйста как это можно выполнить и можно ли вообще это сделать с текущим слайдером?
Александр Мальцев
Александр Мальцев
Здравствуйте!
Слайдер имеет исходные коды, вам никто не запрещает их изменять. Конечно всё это можно выполнить, но это потребует значительного изменения кода.
Roman Bizikin
Roman Bizikin
Прекрасный слайдер, ввожу в работу и есть задача с которой никак не могу разобраться в виду слабого понимания JS, а именно привести слайдер к такому виду: скриншот.
я модифицировал код, чтобы получать активный объект по центру при перелистывании, но теперь мне нужно изменить ширину активного элемента, вот эта задача и не выходит
есть параметры ширины, которые определяют кол-во отображаемых элементов:
flex: 0 0 33.33%;
 max-width: 33.33%;
пробовал дать активному элементу 50%, а остальным 25% соответственно, получается брак, т.к. свойство transition при вычислении выбрасывает элементы за пределы экрана, подскажите пожалуйста какое может быть решение
Александр Мальцев
Александр Мальцев
Спасибо! Изменить ширину слайдов не сложно осуществить. Но, на сколько в этом случае должен выполняться сдвиг слайдов? Здесь уже не получиться это выполнять на фиксированную величину. Может вместо сдвига, использовать эффект появления слайдов или какой-то другой?
Alex
Alex
Александр, вечер добрый. Вопрос такого плана, как можно сделать слайдер от маленькой до большой картинки. Допустим у нас есть 3 картинки одна: 150x150, вторая 300x300, третья 500x500. Слайдер начинает движение и картинку 150x150 помещает в в див где была 300x300 картинка, при этом сохраняя размеры дива увеличивая 150x150. ну и т.д. Прикладываю пример, ну и да, они не должны быть в одной линии должны находится диагонально.
скриншот
Александр Мальцев
Александр Мальцев
Добрый день!
Это можно выполнить, например, через CSS анимацию и абсолютное позиционирование. На каждой ключевой точке определяете соответственно размеры и положение слайда.
Пример, в котором показано, как можно сделать такую анимацию: slider-example-1
Alex
Alex
Спасибо!
Дмитрий
Дмитрий
Александр, добрый день, после установки слайдера видимо возник конфликт скриптов, поможете разобраться?
Куда можно отправить ссылку на страницу с проблемой?
Александр Мальцев
Александр Мальцев
Добрый день! Email есть в футере сайта.
Алишер Пигалев
Алишер Пигалев
Доброго времени суток. Наткнулся недавно на ваш сайт и он мне уже во многом помог. Большое спасибо.
Хотелось бы получить вашего совета.
Столкнулся с ситуацией что на странице нужно 3 слайдера. Слайдеры работают исправно, с зацикливанием и автозаменой слайдов. Но в одном слайдере нужно чтобы выводился только один элемент, а в остальных двух уже установленное количество. Пытался сделать через ID и через дублирование класса slider__item в slider__item1, но все равно сбиваются все элементы слайдеров (через ID просто улетает навигация и слегка меняются размеры элементов, через дублирование (для лучшего понимания продублировал все функции и смежные классы для slider_item) ломается полностью автозамена слайдов и навигация).
Подскажите пожалуйста, как лучше это можно реализовать?
Александр Мальцев
Александр Мальцев
Вроде бы всё просто.
Можно, например, к слайдерам добавить id и прописать следующие стили:
#slider-1 .slider__item {
  flex: 0 0 100%;
  max-width: 100%;
}
#slider-2 .slider__item {
  flex: 0 0 50%;
  max-width: 50%;
}
#slider-3 .slider__item {
  flex: 0 0 33.333333%;
  max-width: 33.333333%;
}
Вот ссылка на пример: 3 слайдера на одной странице
Алишер Пигалев
Алишер Пигалев
Огромное спасибо) Пробовал делать через ИД, но видимо где-то допускал ошибку и плыла вся страница. Теперь все работает) Процветания вам и вашему сайту)
Dannik
Dannik
Здравствуйте! В комментариях был ответ по поводу свайпа слайдера (пример itchief.ru/examples/lab.php?topic=javascript&file=chiefslider-touch), к сожалению свайп работает только в мобильниках, возможно ли это сделать дэсктопах? Было бы здорово, т.к пользователи уже привыкли тянуть каждый слайд
Dannik
Dannik
На сколько я понял, за данный функционал отвечает вот этот код:
// добавление к кнопкам "назад" и "вперед" обрботчика _controlClick для событя click
_sliderControls.forEach(function (item) {
  item.addEventListener('click', _controlClick);
});
_mainElement.addEventListener('touchstart', function (e) {
  _startX = e.changedTouches[0].clientX;
});
_mainElement.addEventListener('touchend', function (e) {
  var
    _endX = e.changedTouches[0].clientX,
    _deltaX = _endX - _startX;
  if (_deltaX > 50) {
    _transformItem('left');
  } else if (_deltaX < -50) {
    _transformItem('right');
  }
});
Dannik
Dannik
Вот только не понятно как включить тач на десктопе
Александр Мальцев
Александр Мальцев
На декстопе нет touch событий. Чтобы это реализовать на декстопе нужно использовать какие-то другие события, например, mouseup и mousedown:
_mainElement.addEventListener('mousedown', function (e) {
  _startX = e.clientX;
});
_mainElement.addEventListener('mouseup', function (e) {
  var
    _endX = e.clientX,
    _deltaX = _endX - _startX;
  if (_deltaX > 50) {
    _transformItem('left');
  } else if (_deltaX < -50) {
    _transformItem('right');
  }
});
Пример: Слайдер со свайпом на декстопах
Dannik
Dannik
Спасибо огромное за слайдер! Подскажите пожалуйста, как сделать так что бы пользователь всегда видел половинки картинок предыдущих и следующих слайдов. Хотел сделать слайдер товаров как на www.toyota.com/
Менял, подкручивал css, но что то не выходит. Пока не особо силен в верстке.
Заранее благодарен!
Александр Мальцев
Александр Мальцев
Можно сделать дополнительную обёртку для слайдов и установить ей padding-left и padding-right.
Пример слайда с частичным отображением предыдущего и следующего слайдов.
Dannik
Dannik
Спасибо Вам IT шеф! Желаю здравия Вам и Вашим близким!
Данияр
Данияр
Александр здравствуйте!
Во-первых, хочу сказать Вам огромное спасибо за такой грамотный подход к реализации слайдера. Это действительно очень круто реализовано и самое главное просто и содержит всё необходимое, спасибо!
Во-вторых, у меня есть вопрос, который я не знаю как решить. В общем, я на одной странице использую два слайдера, они полностью работают. Но там есть проблема с индикаторами, почему-то у первого слайдера отображаются два индикатора (можно увидеть это в коде) и визуально при перелистывании слайдов индикатор меняется, но первый продолжает гореть. В коде отображается так, что один индикатор стоит поверх другого и если его удалить, то всё норм, но вопрос как это реализовать и почему такое происходит?

Ссылка на полный код: https://codepen.io/asdasdasdasd111/pen/oNXbKxQ
Александр Мальцев
Александр Мальцев
Здравствуйте, спасибо за отзыв!
Вам необходимо каждый слайдер инициализировать всего один раз. В вашем коде необходимо удалить или закомментировать первый вызов, т.к. он тоже активирует первый слайдер.
...
/* var slider = multiItemSlider('.slider', {
  isCycling: true
}); */
	
var slider1 = multiItemSlider('#slider-1');
var slider2 = multiItemSlider('#slider-2');
И если нужно добавить параметр isCycling к первому слайдеру, то следует сделать так:
...
/* var slider = multiItemSlider('.slider', {
  isCycling: true
}); */
	
var slider1 = multiItemSlider('#slider-1', {
  isCycling: true
});
var slider2 = multiItemSlider('#slider-2');
Данияр
Данияр
Спасибо огромное! Всё получилось, спасибо Вам! Успехов в развитии!)
Ольга
Ольга
Добрый вечер!
Не совсем понятно как добавить дополнительный слайд. К примеру мне необходимо не 4, а 5 слайдов.
Ольга
Ольга
Разобралась сама=)
Александр Мальцев
Александр Мальцев
Привет! Отлично!
ILIA LITVINOV
ILIA LITVINOV
Александр, здравствуйте.

Спасибо Вам за такой гибкий слайдер.

Подскажите пожалуйста, если между слайдами ставить padding, то скрипт нормально отсчитывает насколько ему нужно сдвинуть слайд.

Но если между слайдами добавить вместо padding — margin, скрипт не воспринимает эти отступы и отступает на ширину самого слайда игнорируя margin. С-но все сдвигается не полностью.

Есть какой-то вариант заставить скрипт видеть margin между слайдами?:)
Александр Мальцев
Александр Мальцев
Здравствуйте.
Создайте дополнительную обёртку для каждого слайда. После этого можно будет настраивать отступы с помощью margin:
<div class="slider__item">
  <div style="height: 250px;">
    <div style="background: orange;">
      1
    </div>
  </div>
</div>
Например, установим margin отступы по 10px:
.slider__item>div>div {
  margin: 10px;
}
Слайдер, отступы в котором для слайдов настроены с помощью margin

Установку положения слайда при желании также можно настроить с помощью техники сочетания относительного и абсолютного позиционирования:
.slider__item>div {
  height: 250px;
  position: relative;
}
.slider__item>div>div {
  position: absolute;
  top: 10px;
  left: 10px;
  right: 10px;
  bottom: 10px;
}
kaduk yevheniy
kaduk yevheniy
Добрый вечер Александр. Изначально хотел поблагодарить вас и сказать вам огромное спасибо за всю проделанную вами работу! очень много интересных статей. и у меня вопрос если можно ?!
а возможно ли сделать так чтобы под вашим слайдером были видны минимизированные фото, и средняя показывалась на слайдере.
спасибо за раннее в любом случае.
визуальный пример приведен ниже.
Евгений
src=«itchief.ru/assets/uploadify/b/f/6/bf6dc956cb54483da64e55d544a26d69.jpg» />
Vlad
Vlad
извините за глупый вопрос, а что за отдельный код инициализации скрипта, например
var slider = multiItemSlider('.slider')
?
Его обязательно размещать? Если да, то где?
Александр Мальцев
Александр Мальцев
Очень много компонентов на веб-страницах построены с использованием JavaScript. JavaScript – это код, который добавляет к компоненту определённую логику. В большинстве случаев эта логика организована в виде определённой функции, в данном случае, с помощью multiItemSlider.

Функция само по себе ничего не делает, пока её не запустишь. Инициализация в этом случае – это и есть запуск этой функции. Эта функция может принимать различные аргументы. Первый аргумент обязательный. С помощью него необходимо задать элемент, который на странице будет каруселью. Другими словами, элемент, который содержит определённую HTML структуру этой карусели. Второй аргумент – это дополнительные настройки для карусели, указываются в формате объекта.

Многие компоненты, которые вы добавляете на страницу не нужно инициализировать, т.к. это действие уже прописано в самом скрипте, который вы подключение к странице. Чтобы скрипт узнал для каких элементов это нужно, в большинстве случаев к ним нужно просто добавить определённые атрибуты или классы. Но это в основном касается только простых компонентов, в которых нечего настраивать.

Этот компонент посложнее будет, он может принимать дополнительные параметры, а также возвращает объект, с помощью методов которого вы можете программно управлять им. Вы также можете самостоятельно инициализировать слайдер, который добавили на страницу через AJAX. Но вам никто не мешает сделать так, чтобы слайдеры активировались автоматически после загрузки DOM-страницы, например при наличии у них какого-нибудь класса или атрибута.

Инициализацию слайдера выполнять конечно нужно, если хотите чтобы он работал.
Обычно все скрипты подключают к странице перед закрывающим тегом body. Данный код необходимо разместить после подключения js-скрипта слайдера.
Vlad
Vlad
спасибо за развернутый ответ, теперь понятно.
П.С. у вас шикарный навороченный сайт, сразу видна рука айтишника ) Особенно мне понравилось меню в мобильном с прокруткой. Было бы здорово, если бы вы написали статью, как это сделать, я думаю многим было бы интересно.
Александр Мальцев
Александр Мальцев
Спасибо! Как сделать такое меню напишу.
Vlad
Vlad
Александр, прошу помощи!
Как сделать так, чтобы слайдер был только в мобильной версии?
делаю вот такой элемент из 4 блоков в табах (табы сделал сегодня по вашей статье): itchief.ru/assets/uploadify/f/a/e/faee69f9007c44356567ddb3d7ef893c.jpg
В ПК версии я хочу, чтобы эти 4 блока оставались без карусели.
А вот в мобильной чтобы оставалось 1.5-2 блока, а остальное было справа в горизонтальной прокрутке, и чтобы заголовки табов тоже были в карусели. Вот так:
itchief.ru/assets/uploadify/1/b/2/1b25962e7742738e508fccdc30848d54.jpg

Александр Мальцев
Александр Мальцев
Чтобы табы выполнить с прокруткой, их (сами вкладки) необходимо поместить в контейнер и добавить к нему следующее CSS-свойство:
overflow-x: auto;
Это основной принцип, детальная реализация зависит от разметки.

Для реализации такой карусели возможно потребуется написать дополнительные CSS-правила для ПК-версии и мобильной, например с использованием медиа-запросов.
Чтобы блоки оставались без карусели на ПК-версии, можете просто активировать её только для мобильных устройств:
if (window.matchMedia('screen and (max-width: 543px)').matches) {
  multiItemSlider('.slider');
}
Руслан
Руслан
Добрый день.
Буквально вчера открыл для себя Ваш сайт — и возрадовался. Т.к. уже с первых минут нашёл на нем то, что мне нужно (о слайдере)!
Прочитал все коментарии (чтобы не повторить вопрос), но не нашел ответа на следующий вопрос.
По умолчанию на слайдере есть один условный блок (одна картинка + текст к ней). И слайдер при нажатии на кнопки управления слайдером сдвигает один блок влево или вправо.
На моём варианте Вашего слайдера 4 блока. И моя задача состоит в том, чтобы при нажатии на кнопки управления соответсвующий сдвиг происходил на 4 блока (либо на ширину слайдера — не знаю, как правильно сформулировать, но, думаю, смысл Вы поняли). Подскажите, пожалуйста, как это реализовать. Заранее спасибо
Александр Мальцев
Александр Мальцев
Привет! Спасибо за отзыв.
Для этого можно в скрипт добавить следующее:
var count = Math.round(100 / _step);
while (count > 0) {
  _transformItem(direction);
  count--;
}
Т.е. определить количество слайдов, одновременно отображающихся на странице, а затем вызвать _transformItem это же количество раз.
Пример доступен в песочнице по этой ссылке.
Kasper
Kasper
Добрый день.

Александр, очень не хочется прибегать к jquery, ваш скрипт понравился, но никак не удается его «допилить», чтобы получить нужный мне результат: ссылка на картинку.
Задача состоит реализовать карусель «по кругу» для мобильной версии сайта, очень похожую на ваш вариант «Слайдер с тремя активными слайдами», но отличие в том, что средняя картинка будет всегда центрироваться и от неё будет некоторое расстояние между ней и первой/третьей картинками. Не удается через js задать, чтобы элемент :nth-child(2) в динамике давал margin по бокам и накладывал прямоугольник с тенью на 1-ю и 3-ю картинку на экране.

Можете подсказать?
Александр Мальцев
Александр Мальцев
Привет! Как это реализовать можно посмотреть в этом примере.
Kasper
Kasper
Александр, я вам безумно благодарен! Уже настроил дизайн под слайдер slick, но все равно буду переделывать под вашу реализацию. Спасибо большое!
Kasper
Kasper
Добрый день. Александр, вопрос смежный, но не конкретно про ваш слайдер.

Я поместил ваш слайдер в отдельный блок, задал ему position: absolut, ширину 100%, background-size: 100%, а картинки привязал в css к div-ам через background: url("..").

Слайдер работает прекрасно. Но в параллельном блоке есть статичная информацию с меню, кнопками и текстом (два блока в родителе: слайдер и статичный блок с текстом поверх и кнопками). И у меня никак не получается подогнать грамотно высоту статичного блока под высоту слайдера. Пробовал через min-height: ...vw, но на ipad все уплывает. Подскажите, пожалуйста, как в таком случае указать высоту блока равную высоте параллельного блока от одного родителя с учетом того, что этот параллельный блок (слайдер) размещен через absolut…
Kasper
Kasper
Настроил что хотел. Пришлось вставлять «пыстышку» и указывать ей padding по тому методу, который у вас указан в другой ветке (расчет высоты по соотношению сторон на основе % от ширины). Все хорошо.
Александр Мальцев
Александр Мальцев
Отлично!
AV
AV
Александр добрый день! Давно использую ваш слайдер — все прекрасно работает! Но вот возникла потребность в импользовании пагинации. Посмотрел отдельную тему с таковым сладером — понял, что для меня он не очень удобен. Хотелось бы иметь один полностью универсальный слайдер — как в этом примере, но с вожможностью подключения пагинации в html, также как стрелки для прокрутки влево-вправо. Как можно это реализовать?
Александр Мальцев
Александр Мальцев
Привет!
Это сделать очень просто.
Для этого нужно добавить в слайдер после кнопок-стрелок следующий код:
<ol class="slider__indicators">
  <li class="active" data-slide-to="0"></li>
  <li data-slide-to="1"></li>
  <li data-slide-to="2"></li>
  <li data-slide-to="3"></li>
  <li data-slide-to="4"></li>
  <li data-slide-to="5"></li>
  <li data-slide-to="6"></li>
</ol>
В JavaScript из функции _addIndicators удалить всё кроме одной строчки:
var _addIndicators = function () {
  _indicatorItems = _mainElement.querySelectorAll('.slider__indicators > li')
}
Этот пример доступен по этой ссылке
AV
AV
Да, действительно просто! Спасибо!
kadochnikov_k
kadochnikov_k
Добрый день! Огромное спасибо за слайдер! Подскажите, как обнулять таймер листания при перелистывании слайдов пальцем? Сейчас из-за того, что таймер не обнуляется, происходят двойные перелистывания.
kadochnikov_k
kadochnikov_k
Уже разобрался) Еще вопрос: можно ли сделать так, чтобы слайды не перелистывались, если все слайды сейчас на экране?
Александр Мальцев
Александр Мальцев
Можно просто не инициализировать данный блок как слайдер. Т.е. перед тем, как это выполнить проверить умещаются ли все слайды на экран и если да, то ничего не делать и установить .slider__control значение display равное none:
var sliderSelector = '.slider';
var sliderElem = document.querySelector('.slider');
if (sliderElem.querySelector('.slider__item').getBoundingClientRect().width * sliderElem.querySelectorAll('.slider__item').length !== sliderElem.querySelector('.slider__wrapper').getBoundingClientRect().width) {
  var slider = multiItemSlider('.slider');
} else {
  // удалить slider__control_show
  var sliderControls = sliderElem.querySelectorAll('.slider__control');
  for (var i = 0; i < sliderControls.length; i++) {
    sliderControls[i].style.display = 'none';
  }
}
Пример доступен по этой ссылке.
kadochnikov_k
kadochnikov_k
Работает, спасибо! Только возникла такая сложность: в слайдере с автоматической сменой слайдов стрелочки пропадают, но листаться они не перестают, попробовал дописать код, но не помогло
var sliderSelector = '.slider';
    var sliderElem = document.querySelector('.slider');
    if (sliderElem.querySelector('.slider__item').getBoundingClientRect().width * sliderElem.querySelectorAll('.slider__item').length >= sliderElem.querySelector('.slider__wrapper').getBoundingClientRect().width) {
      var slider = multiItemSlider('.slider');
    } else {
      // удалить slider__control_show
      var sliderControls = sliderElem.querySelectorAll('.slider__control');
      for (var i = 0; i < sliderControls.length; i++) {
        sliderControls[i].style.display = 'none';
      }
        var slider = multiItemSlider('.slider', {
    isCycling: false
    })
    }
Александр Мальцев
Александр Мальцев
Немного не так.
Код будет таким:
var sliderSelector = '.slider';
var sliderElem = document.querySelector(sliderSelector);
if (sliderElem.querySelector('.slider__item').getBoundingClientRect().width * sliderElem.querySelectorAll('.slider__item').length > sliderElem.querySelector('.slider__wrapper').getBoundingClientRect().width) {
    // слайдов больше, чем на экране
    var slider = multiItemSlider(sliderSelector, {
        isCycling: true
    });
} else {
    // слайдов меньше, чем на экране
    // удалить slider__control_show
    var sliderControls = sliderElem.querySelectorAll('.slider__control');
    for (var i = 0; i < sliderControls.length; i++) {
      sliderControls[i].style.display = 'none';
    }
}
kadochnikov_k
kadochnikov_k
Огромное спасибо! Все работает)
Дмитрий
Дмитрий
Доброго дня, подскажите в чем может быть проблема, подключил css и js файлы, в отдельном модуле прописал слайдер, но при инициализации на сайте выдает ошибку slider.js:23 Uncaught TypeError: Cannot read property 'querySelector' of null
return function (selector, config) {
        var
          _mainElement = document.querySelector(selector),
          _sliderWrapper = _mainElement.querySelector('.slider__wrapper'),/*на эту строку ругается*/
          _sliderItems = _mainElement.querySelectorAll('.slider__item'),
          _sliderControls = _mainElement.querySelectorAll('.slider__control'),
          _sliderControlLeft = _mainElement.querySelector('.slider__control_left'),
          _sliderControlRight = _mainElement.querySelector('.slider__control_right'),
Дмитрий
Дмитрий
Проблему решил, дело было в ранней инициализации js скрипта.
Александр Мальцев
Александр Мальцев
Отлично!
Тимур Хабибуллин
Тимур Хабибуллин
Доброго времени суток. Не могу понять, как реализовать слайдер с вкладками. Примеры видел реализации от простых для сложных, который уже тут есть. Но все равно не хочет работать.
Ссылка
Александр Мальцев
Александр Мальцев
Привет!
Это можно решить с помощью следующего кода:
var slider1, slider2, slider3;
var tabs = document.querySelectorAll('#tab_1, #tab_2, #tab_3');    
var tabChecked = document.querySelector('.tabs > input:checked');
var initSliders = function(id) {
  if (id === 'tab_1' && slider1 === undefined) {
    slider1 = multiItemSlider('#slider-1');
  } else if (id === 'tab_2' && slider2 === undefined) {
    slider2 = multiItemSlider('#slider-2');
  } else if (id === 'tab_3' && slider3 === undefined) {
    slider3 = multiItemSlider('#slider-3');
  }
}
if (tabChecked) {
  initSliders(tabChecked.id);
}  
for (var i = 0; i < tabs.length; i++) {
  tabs[i].addEventListener('change', function() {
    initSliders(this.id);
  })
}
Ссылка на пример
Igor
Igor
доброго времени суток! спасибо за Ваши труды)
Есть вопрос:
как отключить зацикливание в данном слайдере?
Александр Мальцев
Александр Мальцев
Привет! Спасибо за отзыв!
Ссылка на пример в котором нет зацикливания.
Igor
Igor
Спасибо, всё работает как часы :)
alyon
alyon
подскажите пожалуйста, как в слайдер несколькими активными слайдами добавить поля migx?
вывожу изображение так
[[getImageList?
&tvname=`photos`
&tpl=`tplCarouselItem`
]]

код чанка
<div class="item [[+idx:is=`1` :then=`active`]]   ">
  <img src="[[+image]]" alt="[[+title]]">
    <div class="carousel-caption">
    </div>
</div>
Александр Мальцев
Александр Мальцев
Откуда это?
Код должен быть таким:
<div class="slider">
  <div class="slider__wrapper">
    [[getImageList?
      &tvname=`photos`
      &tpl=`tplCarouselItem`
    ]]
  </div>
  <a class="slider__control slider__control_left" href="#" role="button"></a>
  <a class="slider__control slider__control_right slider__control_show" href="#" role="button"></a>
</div>
Чанк tplCarouselItem:
<div class="slider__item">
  <img src="[[+image]]" alt="[[+title]]">
</div>
Кроме этого, конечно же не забыть подключить соответствующий CSS и JavaScript код.
alyon
alyon
спасибо!
kadochnikov_k
kadochnikov_k
Здравствуйте! Подскажите, почему в этом примере не работает автоматическая смена слайдов?
Александр Мальцев
Александр Мальцев
Привет!
В этом примере она отключена:
var slider = multiItemSlider('.slider', {
  isCycling: false
});
Если нужно её включить, то установите параметру isCycling значение true:
var slider = multiItemSlider('.slider', {
  isCycling: true
});
kadochnikov_k
kadochnikov_k
Спасибо! Еще заметил проблему — на мобильном, если слайдер находится не по центру экрана (чуть выше или чуть ниже), то перестают срабатывать кнопки, индикаторы и слайды перестают перелистываться
Александр Мальцев
Александр Мальцев
Спасибо, есть такое. Поправил этот момент.
Roman
Roman
Здравствуйте. Очень простой, а поэтому крутой, слайдер.
Столкнулся с такой проблемой: мне надо что бы на одной странице друг за другом шло несколько слайдеров, но когда сделал один и раскопировал его ниже, то работает только первый, а остальные (точная копия!) не хотят.
Подскажите, пожалуйста, в чём может быть дело и как это исправить?(
Roman
Roman
даже в примерах если вставить два раза блок contаiner, то работать будет только первый
Александр Мальцев
Александр Мальцев
Привет! Спасибо за отзыв. На странице можно поместить какое угодно количество слайдов.
После этого их нужно инициализировать. Как это выполнить есть в этом комментарии.
Если через цикл, то показано как это выполнить в этом комментарии.
Roman
Roman
спасибо огромное!
kadochnikov_k
kadochnikov_k
Добрый день! Не могу разобраться со ссылками. Комментариях уже задавали вопрос, вы привели в качестве примера эту ссылку, но в этом примере проблема такая же — ссылки не открываются при нажатии по ним левой кнопкой мыши. Подскажете, что за это отвечает?
Александр Мальцев
Александр Мальцев
Привет! А в каком браузере не работает? Обновил этот пример для наглядности. Попробовал в нескольких браузерах, всё отлично. Вот ещё один пример, здесь есть изображение и ссылка.
kadochnikov_k
kadochnikov_k
Спасибо, примеры работают. Но начинаются проблемы, когда добавляю индикаторы слайдов. Без индикаторов ссылки работают как положено, а с индикаторами открываются только в новых вкладках.
Александр Мальцев
Александр Мальцев
Ага, есть такая проблема. Поправил JavaScript код во всех примерах в статье и комментариях. Теперь проблем с ссылками нет.
Добавил новый пример. Его можно посмотреть здесь.
kadochnikov_k
kadochnikov_k
Огромное спасибо! А в какой части кода была проблема? Было бы интересно разобрать.
Александр Мальцев
Александр Мальцев
Здесь можно посмотреть изменения.
kadochnikov_k
kadochnikov_k
Спасибо!
kadochnikov_k
kadochnikov_k
Большое спасибо за слайдер! А как добавить возможность свайпа слайдов?
Александр Мальцев
Александр Мальцев
Как это добавить можно посмотреть в этом комментарии.
Марина
Марина
Здравствуйте, подскажите что изменить в коде чтобы слайдер с зацикливанием и автоматической сменой слайдов стал вертикальным, возможно ли это?
Александр Мальцев
Александр Мальцев
Привет! Да, можно это выполнить. Пример расположен здесь.
NADEZHDA TABANKOVA
NADEZHDA TABANKOVA
Александр, добрый вечер.
Решила использовать Ваш плагин. Очень понравился.
Есть ли возможность в нем листать при помощи swipe при использовании в мобильных версиях?
Спасибо
Александр Мальцев
Александр Мальцев
Привет! В этом комментарии есть пример с использованием touch событий.
Денис
Денис
Александр, здравствуйте. Подскажите пожалуйста, как сделать так, чтобы изображение сохраняло своё соотношение сторон, а не соотношение слайдера?
Александр Мальцев
Александр Мальцев
Привет! Если нужно что-то убрать, то делайте это. Вот пример слайдера с изображениями, в котором не установлены какие-то фиксированные размеры.
NADEZHDA TABANKOVA
NADEZHDA TABANKOVA
Александр, спасибо большое за карусель. Все отлично работает.
Но столкнулась с небольшой проблемой: кнопки для перелистывания у меня должны выступать за блок .slider. Если переношу их в другое место или меняю overflow, то карусель перестает работать нужным образом. Подскажите, пожалуйста, в чем моя ошибка? Что я упускаю?
Заранее большое спасибо
Александр Мальцев
Александр Мальцев
Спасибо за отзыв.
Для того чтобы кнопки можно было вынести за пределы основной области карусели в неё необходимо просто добавить ещё одну обёртку. В этом примере показано как это можно сделать.
NADEZHDA TABANKOVA
NADEZHDA TABANKOVA
Александр, добрый день.
Спасибо большое. Все работает :)
Ivan
Ivan
Здравствуйте, Александр. Большое спасибо за Ваш скрипт — мне он очень понравился, но я никак не могу сделать так, чтобы он нормально работал в случае вывода ранее скрытого блока. Вы уже приводили пример с подобным случаем, когда слайдер изначально скрыт и открывается с помощью popup на CSS без применения скриптов, но я не смог разобраться в нем по аналогии. Буду очень благодарен, если вы поможете мне.

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

<div class="popup-wrapper">
<input type="checkbox" class="popup-checkbox" id="popupCheckboxTwo">
<div class="popup">
<div class="popup-content">
 <label for="popupCheckboxTwo" class="popup-closer">×</label>
 <img src="popup-video.jpg" style="margin-left:20px">
<DIV style="margin-left:20px;font-size:4vh; font-family:monospace">
Тут идет стандартный код слайдера + скрипт вызова (та версия, которая у Вас идет как дефолтная в тексте данной статьи)
</div></div></div> 
</div>
отображается эта конструкция по нажатию на
<label for="popupCheckboxTwo" class="popup-shower">Тут DIV с картинкой в фоне</label>
CSS самого Popup такая:
.popup-checkbox,.popup{display:none;}
.popup{position:fixed;z-index:1001;top:0;left:0;width:100%;height:100%;opacity:0;}
.popup:before{display:block;content:'';position:absolute;z-index:1;width:100%;height:100%;top:0;left:0;background-color:#000;opacity:.5;}
.popup-content{width:100%;max-width:1458px;height:1400px;position:absolute;z-index:2;top:30px;left:30px;margin:auto;background-color:#fff;border-radius:15px;padding:0px;-moz-box-sizing:border-box;box-sizing:border-box;background-image:url(popup-bg.jpg);}
.popup-shower{color:#00f;cursor:pointer;text-decoration:underline;}
.popup-shower:hover{color:#00a;text-decoration:underline;}
.popup-closer{position: fixed;top: 50px;right: 5%;color: #410a0a;font-size: 60px;display: block;width: 45px;height: 45px;line-height: 43px;text-align: center;border-radius: 50%;cursor: pointer;background-image: url(button-bg.jpg);font-weight: bold;box-shadow: 0 0 10px rgba(0,0,0,0.5);}
.popup-closer:hover{color: #9c1b1b;}
.popup-checkbox:checked+.popup{opacity:1;display:block;}

Что интересно, если открыть popup, а затем перезагрузить страницу, то слайдер работает нормально.
Ivan
Ivan
Вот тут код страницы целиком: jsfiddle.net/a6zcq594/
Александр Мальцев
Александр Мальцев
Добавьте это:
// var slider = multiItemSlider('.slider');
document.querySelector('#popupCheckboxTwo').addEventListener('change', function () {
  if (this.checked) {
    if (slider === undefined) {
      slider = multiItemSlider('.slider', {
        isCycling: true
      });
    } else {
      slider.cycle();
    }
  }
});
Ivan
Ivan
Вы имеете в виду заменить стандартный код вызова var slider = multiItemSlider('.slider') на указанный вами?
Символы комментирования, как я понимаю, надо убрать было, но у меня как в исходном варианте, так и с убранными все равно та же проблема остается, т.е. работать начинает только после перезагрузки страницы с активированным блоком :(

Может быть нюансы с тем, где именно код нужно размещать?
Александр Мальцев
Александр Мальцев
Нужно заменить. Значит не правильно вставили. Ссылка на пример, размещённый на JSFiddle.
Ivan
Ivan
Спасибо большое. Теперь работает.
Андрей
Андрей
Не получается сделать автоматическую смену слайдов как в первом примере слайда
Александр Мальцев
Александр Мальцев
Это можно решить простым скриптиком:
var currentIndexSlider = 1;
var timerId = setInterval(function(){
  if (currentIndexSlider >= 4) {
    clearTimeout(timerId);
    return;
  }
  slider.right();
  currentIndexSlider++;
}, 5000);
Ссылка на пример.
Андрей
Андрей
а цикличность как добавить?
Александр Мальцев
Александр Мальцев
Вот пример слайдера с цикличностью.
Андрей
Андрей
Спасибо большое)
Елена Савченко
Елена Савченко
Александр, доброго дня. Я новичок в веб верстке, по вашему коду для слайдера с изображениями, не получается добавить фото. Создала папки examples\images, но они так и не отображаются.
Александр Мальцев
Александр Мальцев
Привет! В этом комментарии есть пример слайдера с изображениями. Или нужен какой-то другой?
Анастасия
Анастасия
Александр, подскажите, пожалуйста, как сделать нижние кружки для слайдера, нужно чтобы в мобильной версии были кружки, а в десктопе стрелки.
Александр Мальцев
Александр Мальцев
Ну, тут нужно просто CSS подредактировать.
Как это выполнить можно посмотреть здесь.
Святослав
Святослав
Здраствуйте, использую ваш слайдер для картинок, но не знаю как сделать так, чтобы при изменении области видимости экрана все равно можно было нажимать на кнопки(т.е слайдер работает только тогда, когда он находится в области видимости на экране, а мне необходимо убрать данную фичу). Буду очень благодарен за ответ
Александр Мальцев
Александр Мальцев
Здравствуйте.
Удалил эту фичу, вот ссылка на пример.
владислав Ковалев
владислав Ковалев
Здравствуйте, очень простой хороший слайдер, только можно ли кастомизировать его и сделать прокрутку вертикальной?
владислав Ковалев
владислав Ковалев
я уже сделал, но было неплохо сделать пометку в статье, мне кажется может пригодится и еще раз спасибо за слайдер.
Александр Мальцев
Александр Мальцев
Здравствуйте. Если есть желание поделиться этим рецептом, то будем рады этому.
Сергей
Сергей
Здравствуйте. Спасибо за слайдер. Есть проблема с ссылками. В последних двух примерах ссылки не работают. Например если сделать изображение ссылкой, то она не будет работать.
Александр Мальцев
Александр Мальцев
Здравствуйте.
Спасибо! Поправил этот момент в этих примерах.
Вот пример слайдера с изображениями.
joseph
joseph
Добрый день, Александр. Несколько дней не могу победить перемещение кнопок «влево» и «вправо» при использовании данного слайдера. Если в качестве элемента вставить ссылку на изображение, открываемое в галерее Fancybox (из вашей статьи про фотогалерею), и пролистать несколько слайдов, а потом выйти из режима просмотра, то кнопка навигации уплывает и оказывается совсем не на своём месте. Подскажите, где копать?
Александр Мальцев
Александр Мальцев
Добрый день. Покажите реальный пример, например, на JSFiddle.
joseph
joseph
С моим отсутствием опыта я не смогу в JSFiddle подключить 8 файлов с JS:
jquery.min.js
popper.min.js
bootstrap.min.js
jquery.fancybox.min.js
browser.min.js
breakpoints.min.js
и так далее… + 3 файла с CSS
Как это правильно сделать?
Александр Мальцев
Александр Мальцев
Там есть поле для ввода текста со значком "+". Вставляете в это поле URL и нажимаете на этот значок. Всё ваш файл подключен. Можно подключить скрипт и стили со своего сайта. Если его нет, то найти эти файлы можно на cdnjs.com. Очень хороший сервис, стоит разобраться…
Роман Поверенный
Роман Поверенный
Добрый день, Александр. Использовал ваш последний пример со статьями (https://itchief.ru/examples/lab.php?topic=javascript&file=chiefslider-example-3), не пойму, что нужно делать чтобы добавить к нему пагинацию, т.к. код скрипта отличается от того, что на гитхаб. Мне было очень важно отображать с разной шириной разное количество слайдов, поэтому взял из-за:
_states = [
            { active: false, minWidth: 0, count: 1 },
            { active: false, minWidth: 576, count: 2 },
            { active: false, minWidth: 992, count: 3 },
            { active: false, minWidth: 1200, count: 4 },
          ]
Александр Мальцев
Александр Мальцев
Добрый. На Github расположен базовый код, а различные примеры его использования здесь. В каком виде вы хотите добавить к нему пагинацию?
Роман Поверенный
Роман Поверенный
Добрый день. Пагинация нужна кликабельная именно тогда когда разрешение экрана становится маленьким и показ идет одного слайда. Тач события есть для перелистывания пальцем, а вот доп навигатор в виде пагинации нет, но нужен в виде точек под слайдером. На сайте есть и другие более тяжелые слайдеры с подобной пагинацией, но ваш слайдер заинтересовал более всего для дальнейшего использования, из-за его «легковесия».
Роман Поверенный
Роман Поверенный
Александр Мальцев
Александр Мальцев
Понятно, что вы хотите. Подумаю, как это лучше реализовать…
Александр Мальцев
Александр Мальцев
Добрый день. Добавил в статью пример, как это можно выполнить.
Роман Поверенный
Роман Поверенный
Спасибо огромное, всё получилось как нужно.
И маленький, но не обязательный вопрос, который может пригодиться в будущем:
Возможно ли в конфиг вывести количество слайдов которое меняется за раз, к примеру отображается 3 слайда на экране, и я хочу листать тоже по 3. Было бы замечательно сделать это аналогично:
_states = [
{ active: false, minWidth: 0, count: 1 },
{ active: false, minWidth: 576, count: 2 },
{ active: false, minWidth: 992, count: 3 },
{ active: false, minWidth: 1200, count: 4 },
]
Т.е. в зависимости от экрана, но отдельной настройкой, т.к. может понадобиться листать по 2 когда видно 3.

P.S. Еще раз огромное спасибо за ваш труд!
Александр Мальцев
Александр Мальцев
Добавлю эту возможность к слайдеру.
joseph
joseph
Доброго времени суток. Спасибо, Александр, за Ваши труды и за то, что делитесь ими. Слайдер очень симпатичный, но у меня, как и у товарища Alek (31 мая 2019, 19:52) не получается добиться от него корректного открытия ссылок. Если я вставляю между тегами … ссылку в виде картинки или текста или другого контейнера div, то курсор при наведении меняется, но при нажатии ЛКМ ничего не происходит (могу перейти по ссылке только через ПКМ). Подскажите, что я делаю не правильно? Код целиком беру из примеров. С уважением.
joseph
joseph
Использовал код из Вашей ссылки от 19 марта 2019, 14:57 — с ним всё открывается. Благодарю.
Alex
Alex
Как можно сделать, чтобы слайдер по клику на кнопки вперед-назад «пролистывал» два или три слайда?
Александр Мальцев
Александр Мальцев
Это можно выполнить так:
...
// обработчик события click для кнопок "назад" и "вперед"
var _controlClick = function (e) {
  var direction = this.classList.contains('slider__control_right') ? 'right' : 'left';
  e.preventDefault();
  _transformItem(direction);
  _transformItem(direction);
  _transformItem(direction);
};
Просто вызовите функцию _transformItem(direction); столько раз сколько нужно.
Alex
Alex
Спасибо)
Максим
Максим
Александр, подскажите пожалуйста, в теме есть описание инициализации слайдера, а как сделать так, чтобы функция перестала работать? Я делаю инит при открытии модального окна, а по закрытию хочу чтобы функция останавливалась и элементы возвращались на начальные положения.
Dmytro Bazaluk
Dmytro Bazaluk
Добрый вечер. Нашёл ваш замечательный слайдер, все доступно и понятно. Но нужна функция пролистывания слайдов ‘пальцем’, как на слайдерах бутстрап, все не могу найти именно эту функцию. Подскажите направление поиска или какое-то решение.
Спасибо огромное)
Александр Мальцев
Александр Мальцев
Добрый! Для этого на страницу нужно добавить обработку для событий touchstart и toachend. Как это сделать можно посмотреть в этом примере.
Dmytro Bazaluk
Dmytro Bazaluk
Добрый день еще раз, появилась задача с интеграцией индикатора (пагинации слайдера). Подскажите пожалуйста направление внедрения данного индикатора, стрелки работают как плюс/минус ширина слайда, а вот индикатор должен переносить на указанное изображение, либо экран с изображениями. Тут я не знаю, как проще это сделать. Вот скриншот.
Спасибо большое!
Dmytro Bazaluk
Dmytro Bazaluk
Вопрос решен, кому еще нужны индикаторы, ищите на gitHub
Огромное вас спасибо
Алибек
Алибек
Здравствуйте, можете подсказать как сделать так чтобы после каждой прокрутке сайта страница не отматывалась к верху?
Александр Мальцев
Александр Мальцев
Здравствуйте! Это ошибка исправлена. Код слайдера и примеры обновлены.
nik
nik
Здравствуйте Александр
Классные слайдеры
Что бы отобразить два слайдера нужно по вашему добавить id=«slider-1» id=«slider-2»
и так же указать в скрипте
var slider1 = multiItemSlider('#slider-1');
var slider2 = multiItemSlider('#slider-2');
Но мне нужно что бы слайдер работал и менялся в зависимость от категории, что нужно изменить в скрипте или добавить?.. Работает только первый слайдер, а остальные нет.
То есть id=«slider-1» где 1 это рубрика, а как это сделать что бы указать в скрипте.
Спасибо
Александр Мальцев
Александр Мальцев
Здравствуйте! В комментариях уже приводил такой пример. Вот ссылка на него.
nik
nik
там не посредственно указывается ид, а я говорю о переменной ид категории которая выводиться. что бы скрипт автоматом понимал что ид другой и обрабатывал слайдер.
Александр Мальцев
Александр Мальцев
Без изменения кода слайдера инициализировать все слайдеры на странице можно так:
document.querySelectorAll('.slider').forEach(function(item, index){ 
  item.setAttribute('slider-id', index);
  multiItemSlider('[slider-id="'+ index +'"]');
});
nik
nik
Александр вот то что нужно. Спасибо, Вам вот теперь можно пользоваться в переменных.
Дмитрий
Дмитрий
а как сдеалать что бы окно появлялось с помощью кода javascript, типа как в примере который вы показали с бутстрапом?
Александр Мальцев
Александр Мальцев
Набросок этого решения можно посмотреть здесь.
Дмитрий
Дмитрий
Очень круто!!! Спасибо большое!!! У вас хороший ресурс, жду больше уроков!!!
Дмитрий
Дмитрий
Спасибо большое, все очень хорошо все показано.Подскажите пожалуйста(похожий вопрос уже тут был, но мне не понятно), как сделать это в динамическом модальном окне, только что бы без бутстрапа и jquery, заранее спасибо
Александр Мальцев
Александр Мальцев
Пожалуйста. Пример слайдера в модальном окне на чистом JavaScript:
itchief.ru/examples/lab.php?topic=javascript&file=chiefslider-example-10
Дмитрий
Дмитрий
Спасибо!!! Очень понятно все!!! У вас хорошие материал!!!
Дмитрий
Дмитрий
а как сдеалать что бы окно появлялось с помощью кода javascript, типа как в примере который вы показали с бутстрапом
Сергей
Сергей
Не работает на моём сайте:
Uncaught TypeError: Cannot read property 'querySelectorAll' of null

хотел отзывы в слайды засунуть, а работать отказывается:
vk.cc/8PIbRa

Можно как-то решить?
Александр Мальцев
Александр Мальцев
Вы подключаете скрипт в head, а необходимо перед закрывающим тегом body.
Александр Мальцев
Александр Мальцев
Если вы хотите поместить его в head (что не желательно), то код, находящийся в slider.js необходимо поместить внутри функции:
document.addEventListener('DOMContentLoaded', function(){ 
  // весь код помещаем сюда
}, false);
Это обеспечит выполнение кода только после загрузки DOM.
Сергей
Сергей
Заработало, спасибо!
Дарья
Дарья
Александр, добрые день! Помогите разобраться, почему при дублировании слайдера, не работает второй и последующие слайдеры? В качестве примера, я взяла первый слайдер, представленный на этой странице. Спасибо.
Александр Мальцев
Александр Мальцев
Добрый! Не знаю, наверно что-то не правильно делаете! Вот пример страницы, на которой используются 2 слайдера.
Дарья
Дарья
Спасибо большое!!! увидела свою ошибку
Дарья
Дарья
хотя, Александр, не подскажите еще вот какой вопрос, дело в том, что слайдеры заключены во вкладки, сами по себе без вкладок работают. Во вкладках работает только первый(
<!DOCTYPE html>
<html lang="ru">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <title>JavaScript - Как сделать слайдер для сайта</title>
  <style>
    /*!
     * chiefSlider (https://itchief.ru/lessons/php/feedback-form-for-website)
     * Copyright 2018 Alexander Maltsev
     * Licensed under MIT (https://github.com/itchief/feedback-form/blob/master/LICENSE)
     */

    body {
      margin: 0;
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
      height: 3000px;
    }

    .slider {
      position: relative;
      overflow: hidden;
    }

    .slider__wrapper {
      display: flex;
      transition: transform 0.6s ease;
    }

    .slider__item {
      flex: 0 0 100%;
      max-width: 100%;
    }

    .slider__control {
      position: absolute;
      top: 50%;
      display: none;
      align-items: center;
      justify-content: center;
      width: 40px;
      color: #fff;
      text-align: center;
      opacity: 0.5;
      height: 50px;
      transform: translateY(-50%);
      background: rgba(0, 0, 0, .5);
    }

    .slider__control_show {
      display: flex;
    }

    .slider__control:hover,
    .slider__control:focus {
      color: #fff;
      text-decoration: none;
      outline: 0;
      opacity: .9;
    }

    .slider__control_left {
      left: 0;
    }

    .slider__control_right {
      right: 0;
    }

    .slider__control::before {
      content: '';
      display: inline-block;
      width: 20px;
      height: 20px;
      background: transparent no-repeat center center;
      background-size: 100% 100%;
    }

    .slider__control_left::before {
      background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E");
    }

    .slider__control_right::before {
      background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E");
    }

    .slider__item>div {
      line-height: 250px;
      font-size: 100px;
      text-align: center;
    }
            .clr:after, .clr:before {
      clear: both;
      content: '';
      display: block;
      line-height: 0;
    } 
    .main-services {
        margin-top: 10px;
    }
        .tabs { 
          width: 1000px; 
          padding: 0px; 
          margin: 0 auto; 
          position: relative; 
 
        } 
        .desc{
            display:none;
            animation: scale 0.7s ease-in-out; 
            width: 180px;
            animation: scale 0.7s ease-in-out;
        width: 180px;
        text-align: justify;
        margin-top: 10px;
        border: 1px solid #DEE8F2;
        padding: 10px;
        height: 200px;
        }
        
        .section_tab { 
          display: none;  
          padding: 15px; 
          background: white; 
          position: absolute; 
          top: 0; 
          left: 180px;
          border: 1px solid #DEE8F2;
          margin-left: 30px;
        } 
        p { 
          margin: 0; 
        } 
        input { 
          display: none; 
        } 
        label { 
          display: block; 
          width: 180px; 
          padding: 15px;  
          cursor: pointer; 
        } 
        input:checked + label { 
            color: #e95210;
        background: #fff;
        border-bottom: 1px solid #e95210;
        /* text-align: center; */
        padding-bottom: 2px;
        } 
        #tab1:checked ~ .content1, #tab2:checked ~ .content2, #tab3:checked ~ .content3, #tab4:checked ~ .content4 { 
          display: block; 
        } 
        .section_tab { 
          animation: scale 0.7s ease-in-out; 
        } 
        @keyframes scale { 
          0% { 
          transform: scale(0.9); 
          opacity: 0; 
          } 
          50% { 
          transform: scale(1.005); 
          opacity: 0.5; 
          } 
          100% { 
          transform: scale(1); 
          opacity: 1; 
          } 
        }
  </style>
</head>

<body>
   <div id="services_container"> 
        <div class="tabs"> 
            <input id="tab1" type="radio" name="tabs" checked> 
            <label for="tab1">ТЕКСТ</label> 
            <div class="content1 desc">ТЕКСТ</div>
            <input id="tab2" type="radio" name="tabs"> 
            <label for="tab2">ТЕКСТ</label> 
            <div class="content2 desc">ТЕКСТ</div>
            <section class="section_tab content1">
              <div class="main-services clr">
                <div id="slider-1" class="slider">
                  <div class="slider__wrapper">
                    <div class="slider__item">
                      <div style="height: 250px; background: orange;">1</div>
                    </div>
                    <div class="slider__item">
                      <div style="height: 250px; background: green;">2</div>
                    </div>
                    <div class="slider__item">
                      <div style="height: 250px; background: violet;">3</div>
                    </div>
                    <div class="slider__item">
                      <div style="height: 250px; background: coral;">4</div>
                    </div>
                  </div>
                  <a class="slider__control slider__control_left" href="#" role="button"></a>
                  <a class="slider__control slider__control_right slider__control_show" href="#" role="button"></a>
                </div>                
              </div>
            </section>
            <section class="section_tab content2"> 
             <div class="main-services clr">
              <div id="slider-2" class="slider" style="margin-top: 20px;">
                <div class="slider__wrapper">
                  <div class="slider__item">
                    <div style="height: 250px; background: orange;">1</div>
                  </div>
                  <div class="slider__item">
                    <div style="height: 250px; background: green;">2</div>
                  </div>
                  <div class="slider__item">
                    <div style="height: 250px; background: violet;">3</div>
                  </div>
                  <div class="slider__item">
                    <div style="height: 250px; background: coral;">4</div>
                  </div>
                </div>
                <a class="slider__control slider__control_left" href="#" role="button"></a>
                <a class="slider__control slider__control_right slider__control_show" href="#" role="button"></a>
              </div>  
             </div>
            </section>
          </div>
        </div>



  <script>
    'use strict';
    var multiItemSlider = (function () {
      return function (selector, config) {
        var
          _mainElement = document.querySelector(selector), // основный элемент блока
          _sliderWrapper = _mainElement.querySelector('.slider__wrapper'), // обертка для .slider-item
          _sliderItems = _mainElement.querySelectorAll('.slider__item'), // элементы (.slider-item)
          _sliderControls = _mainElement.querySelectorAll('.slider__control'), // элементы управления
          _sliderControlLeft = _mainElement.querySelector('.slider__control_left'), // кнопка "LEFT"
          _sliderControlRight = _mainElement.querySelector('.slider__control_right'), // кнопка "RIGHT"
          _wrapperWidth = parseFloat(getComputedStyle(_sliderWrapper).width), // ширина обёртки
          _itemWidth = parseFloat(getComputedStyle(_sliderItems[0]).width), // ширина одного элемента    
          _positionLeftItem = 0, // позиция левого активного элемента
          _transform = 0, // значение транфсофрмации .slider_wrapper
          _step = _itemWidth / _wrapperWidth * 100, // величина шага (для трансформации)
          _items = []; // массив элементов
        // наполнение массива _items
        _sliderItems.forEach(function (item, index) {
          _items.push({ item: item, position: index, transform: 0 });
        });

        var position = {
          getMin: 0,
          getMax: _items.length - 1,
        }

        var _transformItem = function (direction) {
          if (direction === 'right') {
            if ((_positionLeftItem + _wrapperWidth / _itemWidth - 1) >= position.getMax) {
              return;
            }
            if (!_sliderControlLeft.classList.contains('slider__control_show')) {
              _sliderControlLeft.classList.add('slider__control_show');
            }
            if (_sliderControlRight.classList.contains('slider__control_show') && (_positionLeftItem + _wrapperWidth / _itemWidth) >= position.getMax) {
              _sliderControlRight.classList.remove('slider__control_show');
            }
            _positionLeftItem++;
            _transform -= _step;
          }
          if (direction === 'left') {
            if (_positionLeftItem <= position.getMin) {
              return;
            }
            if (!_sliderControlRight.classList.contains('slider__control_show')) {
              _sliderControlRight.classList.add('slider__control_show');
            }
            if (_sliderControlLeft.classList.contains('slider__control_show') && _positionLeftItem - 1 <= position.getMin) {
              _sliderControlLeft.classList.remove('slider__control_show');
            }
            _positionLeftItem--;
            _transform += _step;
          }
          _sliderWrapper.style.transform = 'translateX(' + _transform + '%)';
        }

        // обработчик события click для кнопок "назад" и "вперед"
        var _controlClick = function () {
          var direction = this.classList.contains('slider__control_right') ? 'right' : 'left';
          _transformItem(direction);
        };

        var _setUpListeners = function () {
          // добавление к кнопкам "назад" и "вперед" обрботчика _controlClick для событя click
          _sliderControls.forEach(function (item) {
            item.addEventListener('click', _controlClick);
          });
        }

        // инициализация
        _setUpListeners();

        return {
          right: function () { // метод right
            _transformItem('right');
          },
          left: function () { // метод left
            _transformItem('left');
          }
        }

      }
    }());

    var slider1 = multiItemSlider('#slider-1');
    var slider2 = multiItemSlider('#slider-2');

  </script>

</body>

</html>							

							
Александр Мальцев
Александр Мальцев
Так и должно быть! Когда вы активируете слайдер на элементе (в данном случае во 2 контейнере), который не отображается, скрипт не может его рассчитать, т.к. не знает ширину элемента, в которой данный слайдер помещён. А первый контейнер отображается, его ширина известна и для него расчёт выполняется правильно.
В этом случае, например, можно активировать слайдер при активировании вкладки:
var slider1, slider2;
var activateSlider = function (dataSlider) {
  if (dataSlider === '#slider-1' && slider1 === undefined) {
    slider1 = multiItemSlider(dataSlider);
  } else if (dataSlider === '#slider-2' && slider2 === undefined) {
    slider2 = multiItemSlider(dataSlider);
  }
}
document.addEventListener('change', function (e) {
  var
    element = e.target,
    dataSlider = element.getAttribute('data-slider');
  if (!element.hasAttribute('data-slider')) {
    return;
  }
  activateSlider(dataSlider);
});

var element = document.querySelector('[data-slider]:checked');
if (element) {
  activateSlider(element.getAttribute('data-slider'));
}
Пример с вкладками можно посмотреть здесь.
Дарья
Дарья
Александр, я попыталась добавить 3 вкладку, отредактировала код, в консоли ошибка синтаксическая, помогите пожалуйста(
Извините, что задергала вас.
            <input id="tab1" type="radio" name="tabs" checked data-slider="#slider-1">
		      <label for="tab1">ТЕКСТ</label>
		      <div class="content1 desc">ТЕКСТ</div>
		      <input id="tab2" type="radio" name="tabs" data-slider="#slider-2">
		      <label for="tab2">ТЕКСТ</label>
		      <div class="content2 desc">ТЕКСТ</div>
		      <input id="tab3" type="radio" name="tabs" data-slider="#slider-3">
		      <label for="tab3">ТЕКСТ</label>
		      <div class="content3 desc">ТЕКСТ</div>
    var slider1, slider2, slider3;

    var activateSlider = function (dataSlider) {
      if (dataSlider === '#slider-1' && slider1 === undefined) {
        slider1 = multiItemSlider(dataSlider);
      } else if (dataSlider === '#slider-2' && slider2 === undefined) {
        slider2 = multiItemSlider(dataSlider);
      } else (dataSlider ===  '#slider-3' && slider3 === undefined) {
      	slider3 = multiItemSlider(dataSlider);
      }
    }
Александр Мальцев
Александр Мальцев
Если вкладок может быть сколько угодно много, тогда код для активации слайдеров лучше сделать универсальным, например:
var sliders = [], i = 0;
var elements = document.querySelectorAll('input[data-slider]');
for (i; i < elements.length; i++) {
  sliders[i] = {
    slider: {},
    selector: elements[i].getAttribute('data-slider'),
    activate: false
  };
}
var activateSlider = function (dataSlider) {
  var i = 0;
  for (i; i < elements.length; i++) {
    if (sliders[i].selector === dataSlider && sliders[i].activate === false) {
      sliders[i].activate = true;
      sliders[i].slider = multiItemSlider(dataSlider);
      break;
    }
  }
}

document.addEventListener('change', function (e) {
  var element = e.target;
  if (!element.hasAttribute('data-slider')) {
    return;
  }
  activateSlider(element.getAttribute('data-slider'));
});

var element = document.querySelector('[data-slider]:checked');
if (element) {
  activateSlider(element.getAttribute('data-slider'));
}
Пример можно посмотреть здесь.
Дарья
Дарья
Александр, спасибо!
Constantin
Constantin
Александр, а что и где убрать, что бы получился не слайдер с ротацией статей, а просто статьи? Уж больно симпатично получается :)
Александр Мальцев
Александр Мальцев
Убрал лишнее, теперь его можно использовать для вывода списка статей.
Constantin
Constantin
Просто супер!!! Волшебство :)
Constantin
Constantin
Александр, здравствуйте! Беда…
<section id="rasp-det">
  <div class="container">
    <div class="slider">
      <div class="slider__wrapper">
        <div class="slider__item">
          <div class="slider__content">
            <div class="slider__content_header">
              <a href="#"> <img class="slider__content_img" src="/image/ban1200.png" alt=""></a>
              <span class="slider__content_section">09-11 ноября 2018</span>
            </div>
            <a href="#">
              <h2 class="slider__content_title">Тренер Навыковых Программ</h2>
            </a>
            <div class="slider__content_footer">
              <span class="slider__content_author">
                <class="title">Константин Сидоров</title>
              </span>
            </div>
          </div>
        </div>
      </div>
    </div>

    <div class="slider">
      <div class="slider__wrapper">
        <div class="slider__item">
          <div class="slider__content">
            <div class="slider__content_header">
              <a href="#"> <img class="slider__content_img" src="/image/ban1200.png" alt=""></a>
              <span class="slider__content_section">09-11 ноября 2018</span>
            </div>
            <a href="#">
              <h2 class="slider__content_title">НЛП-ПРАКТИК I сессия (Сургут)</h2>
            </a>
            <div class="slider__content_footer">
              <span class="slider__content_author">
                <class="title">Елена Гольдберг</title>
              </span>
            </div>
          </div>
        </div>
      </div>
    </div>

  </div>
</section>
Почему то они в ряд не располагаются, а отображаются одна под другой в одну колонку???
AV
AV
Добрый день Александр! Спасибо за ваш качественный и доступный контент! Подскажите пожалуйста как инициализировать данный слайдер в модальном окне, созданном при помощи бутстрапа?
Александр Мальцев
Александр Мальцев
Добрый! Данный код необходимо просто расположить в теле модального окна, т.е. в элементе с классом modal-body.
Инициализировать слайдер необходимо после открытия окна:
var slider;

$('#exampleModal').on('shown.bs.modal', function (e) {
  if (slider === undefined) {
    slider = multiItemSlider('.slider', {
      isCycling: true
    });
  } else {
    slider.cycle();
  }
})
$('#exampleModal').on('hidden.bs.modal', function (e) {
  slider.stop();
})
Вот готовый пример: itchief.ru/examples/lab.php?topic=bootstrap&file=b4-slider-in-modal
AV
AV
Спасибо за ответ! В данном виде все хорошо работает. Но что делать если я использую ваш вариант с динамическим созданием модальных окон itchief.ru/bootstrap/modal-dynamic-creation. В таком варианте данная инициализация не срабатывает видимо из-за конфликта id. Как быть в таком случае?
Александр Мальцев
Александр Мальцев
Т.к. модальное окно добавляется на страницу с помощью кода JavaScript, то ещё необходимо дополнительно написать код, который будет вставлять слайдер в его тело.
AV
AV
Ну я так и понял, потому что перепробовал кучу вариантов подстановки. Очень хочется запустить именно Ваш вариант, так как по структуре и дизайну предполагается использовать галерею, где по клику на изображения из плитки вызываются модальные окна со слайдером. Преимущества Вашеего варианта с модальными окнами и слайдером по отдельности очевидны. Но объединить их мне не хватает знаний — если не трудно помогите решить проблему, для запуска проекта осталось решить только эту задачу.
Александр Мальцев
Александр Мальцев
Не знаю, что у вас вызвало трудности. Просто вставляете слайдер в динамическое созданное окно, а потом его активируете. Вот пример.
Constantin
Constantin
И еще — как сделать так, чтобы влазило побольше текста?
Александр Мальцев
Александр Мальцев
Если высота задана строго, то найти в CSS свойство height и установить необходимый размер.
Constantin
Constantin
Александр, здравствуйте! А как сделать так, чтобы при щелчке мышью на любой области слайдера был переход на нужную страницу?
Александр Мальцев
Александр Мальцев
Просто сделать разметку так, как нужно.
Например, вместо div, можно использовать элемент a:
<div class="slider">
  <div class="slider__wrapper">
    <div class="slider__item">
      <a href="#" style="height: 250px; background: orange; display: block;">1</a>
    </div>
    <div class="slider__item">
      <a href="#" style="height: 250px; background: green; display: block;">2</a>
    </div>
     ...
Кроме этого ещё в данном случае необходимо стили поправить:
.slider__item>a {
  line-height: 250px;
  font-size: 100px;
  text-align: center;
  text-decoration: none;
}
Constantin
Constantin
Аха, спасибо. И еще вопрос — почему-то на ipad не работают стрелки влево-вправо. И слайды не сменяются :(
Александр Мальцев
Александр Мальцев
Какая версия iOS и браузер?
Constantin
Constantin
Safari, IOS 9.3.5
Александр Мальцев
Александр Мальцев
Он не поддерживает метод foreach, который используется в примере.
Пример слайдера, для браузеров, которые не поддерживают этот метод.
Irisska89
Irisska89
Подскажите пожалуйста, а может есть пример не зацикленного слайдера для Ie11? Или если Вам не сложно, подскажите, как этот сделать не зацикленным и без автоматической смены слайдов?
Александр Мальцев
Александр Мальцев
Вот пример не зацикленного слайдера для IE11.
Irisska89
Irisska89
Александр, спасибо Вам большое и огромное)
Irisska89
Irisska89
Александр, не могли бы Вы еще раз помочь, если вам не составит труда?
Как сделать, чтобы этот слайдер реагировал на изменение размеров окна браузера?
Александр Мальцев
Александр Мальцев
Для того чтобы всё работало просто подключите полифилл forEach на страницу. А когда поддержка IE11 будет не нужна, его уберёте.
Пример с полифиллом.
Сам HTML код полифилла:
<script crossorigin="anonymous" src="https://polyfill.io/v3/polyfill.min.js?features=default%2CArray.prototype.forEach%2CNodeList.prototype.forEach"></script>
Страница на которой можно очень просто выбирать нужные полифиллы для поддержки старых браузеров: polyfill.io/v3/url-builder
Nikita
Nikita
Здравствуйте, сделал слайдер со ссылкой по данному примеру, но ссылка не открывается при нажатии ЛКМ, только при нажатии колесиком мыши по ссылке в новом окне открывается. А по ЛКМ просто мигает цифра и не переходит никуда. В чем может быть проблема подскажите, пожалуйста?
Вернее так: это только в одном из слайдеров — если у вас на сайте в конструкторе код менять то все работает, копирую его в HTML файл не работает
Александр Мальцев
Александр Мальцев
Здравствуйте. Тут нужно смотреть код JavaScript, а именно определить какой участок кода у вас это делает. Может это из-за конфликта с какой-нибудь js библиотекой или js фрагментом вашего кода.
Alek
Alek
Здравствуйте. Ценные материалы, спасибо. И ссылка работает, но только по ней переходит после вызова контекстного меню правой кнопкой и выбора «Открыть в новой вкладке» или «Открыть в новом окне». Подскажите, пожалуйста, как доработать код, чтобы по ссылка открывалась при единождом клике левой кнопкой мыши? Код взят у Вас на сайте и html, и js. Заранее БЛАГОдарю Вам.
Александр Мальцев
Александр Мальцев
Здравствуйте! Спасибо.
В атрибуте href каждой ссылки вам необходимо указать куда она ведёт, т.е. URL.
<a href="https://itchief.ru" style="height: 250px; background: orange; display: block;">1</a>
Если вам нужно всегда открывать ссылку в новой вкладке, то к ней нужно добавить атрибут target="_blank":
<a href="https://itchief.ru" target="_blank" style="height: 250px; background: orange; display: block;">1</a>