Как создать адаптивный слайдер для сайта?

В этой статье рассмотрим процесс создания легкого, простого и адаптивного слайдера для сайта с помощью CSS и JavaScript.
Исходные коды и подключение слайдера к сайту
Проект слайдера расположен на GitHub по этому адресу. Данный слайдер распространяется под лицензией MIT. Его можно использовать бесплатно как в личных проектах, так и в коммерческих. Поблагодарить автора и поддержать дальнейшее развитие слайдера можно на этой страничке.
Основные характеристики слайдера:
- адаптивный;
- лёгкий (без jQuery);
- простой (с минимальным набором функций);
- наличие механизма автоматического смена слайдов через определенные промежутки времени;
- универсальный (можно использовать для текстовой информации, изображений, отзывов, товаров и др.).
Подключение слайдера к странице осуществляется посредством выполнения следующих действий:
- вставить в необходимое место html код слайдера;
- подключить файл со стилями или добавить их в существующий файл; также стили можно вставить прямо на страницу;
- подключить js-скрипт слайдера или вставить его в существующий файл; также код можно добавить прямо на страницу.
Демо слайдера расположено на этой странице.

Инициализация и настройка слайдера
Инициализация карусели осуществляется посредством вызова функции slideShow
и указания ей в качестве первого аргумента селектора, определяющего слайдер в документе:
// инициализация элемента .slider в качестве карусели slideShow('.slider');
Кроме селектора функции slideShow
можно передать дополнительные параметры, все они указываются в формате объекта посредством 2 параметра:
// инициализация элемента .slider в качестве карусели и настройка её с помощью дополнительных параметров slideShow('.slider', { isAutoplay: false, // false (по умолчанию) или true directionAutoplay: 'next', // 'next' (по умолчанию) или 'prev' delayAutoplay: 5000, // 5000 (по умолчанию) или любое другое число isPauseOnHover: true // true (по умолчанию) или false });
Назначение ключей:
isAutoplay
– определяет, необходимо ли инициализировать слайдер с автоматической сменой элементов (по умолчанию этот ключ имеет значениеfalse
);directionAutoplay
– определяет направление для механизма автоматической смены слайдов (по умолчанию 'next'); для изменения направления установите 'prev';delayAutoplay
– задержка в миллисекундах перед процессом автоматической сменой одного слайда на другой (по умолчанию 5000 мс);isPauseOnHover
– определяет необходимо ли останавливать автоматическую смену слайдов при нахождении курсора в зоне слайдера (по умолчаниюtrue
)
Например, если вам нужно инициализировать слайдер и включить у него автоматическую смену слайдов, то используйте следующую конструкцию:
// инициализация элемента .slider в качестве карусели и настройка её с помощью дополнительных параметров slideShow('.slider', { isAutoplay: true });
Кроме этого, вы можете управлять слайдом с помощью методов. Для этого вам нужно сохранить в переменную результат выполнения функции slideShow
:
// инициализация элемента .slider в качестве карусели и настройка её с помощью дополнительных параметров var sliderOne = slideShow('.slider');
После этого вы можете использовать его методы. Например, для того чтобы программно выполнить переход на следующий слайд необходимо просто вызвать метод show
:
// выполняет переход на следующий слайд sliderOne.next();
Список методов слайдера:
stop
– останавливает автоматическую смену слайдов;next
– выполняет переход на следующий слайд;prev
– выполняет переход на предыдущий слайд;cycle
– включает автоматическую смену слайдов.
Примеры использования слайдера для ротации различной информации
Применение слайдера для ротации изображений:

Использования слайдера для ротации текстовой информации:

Пример использования слайдера для отображения отзывов:

Применение слайдера для ротации товаров:

Описание исходных кодов слайдера и принципа его работы
Исходные коды слайдера состоят из:
- html кода;
- CSS кода (стилей);
- JavaScript кода (скрипта).
HTML структура слайдера:
<div class="slider"> <div class="slider__wrapper"> <div class="slider__items"> <div class="slider__item"> ... </div> <div class="slider__item"> ... </div> <div class="slider__item"> ... </div> <div class="slider__item"> ... </div> </div> </div> <a class="slider__control slider__control_prev" href="#" role="button"></a> <a class="slider__control slider__control_next" href="#" role="button"></a> </div>
В этой разметке основным контейнером, содержащим остальной код слайдера, является элемент div
с классом slider
. Внутри него находятся три элемента: обёртка для слайдов .slider__wrapper
, кнопки для перехода к предыдущему и следующему слайду .slider__control
. Кроме этого после вызова функции слайдера в этот блок ещё динамически добавляется элемент с индикаторами .slider__indicators
.
Обёртка для слайдов .slider__wrapper
содержит в себе элемент .slider__items
, а он в свою очередь элементы .slider__item
. Такая конструкция позволит при необходимости расположить индикаторы и элементы управления как внутри слайдов, так и за их пределами.
В этом примере слайдер состоит из 4 элементов .slider__item
. Эти элементы визуально представляют собой слайды.
Блок с индикаторами .slider__indicators
выполнен в виде нумерованного списка. Он состоит из элементов li
с атрибутом data-slide-to
. Количество элементов в списке определяется числом слайдов. Данный атрибут используется для определения индекса слайда, на которой нужно перейти при нажатии на данный индикатор. В слайдере активный индикатор отмечается с помощью добавления к нему класса active
.
Кнопки «назад» и «вперед» размечены с помощью элемента a
. Кнопка для перехода к предыдущему слайду имеет классы slider__control
и slider__control_prev
, а к следующему – slider__control
и slider__control_next
.

Стили слайдера:
/* стили основного контейнера слайдера */ .slider { position: relative; overflow: hidden; max-width: 600px; margin-left: auto; margin-right: auto; } /* стили для обёртки, в которой заключены слайды */ .slider__wrapper { position: relative; overflow: hidden; } /* стили для контейнера слайдов */ .slider__items { display: flex; transition: transform 0.7s 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, 0.5); } .slider__control_show { display: flex; } .slider__control:hover, .slider__control:focus { color: #fff; text-decoration: none; outline: 0; opacity: 0.9; } .slider__control_prev { left: 0; } .slider__control_next { 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_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"); } .slider__control_next::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__indicators { position: absolute; right: 0; bottom: 10px; left: 0; z-index: 15; display: flex; justify-content: center; padding-left: 0; margin-right: 15%; margin-left: 15%; list-style: none; margin-top: 0; margin-bottom: 0; } .slider__indicators li { box-sizing: content-box; flex: 0 1 auto; width: 30px; height: 4px; margin-right: 3px; margin-left: 3px; text-indent: -999px; cursor: pointer; background-color: rgba(255, 255, 255, 0.5); background-clip: padding-box; border-top: 10px solid transparent; border-bottom: 10px solid transparent; } .slider__indicators li.active { background-color: #fff; }
В слайдере в некоторый момент времени пользователю всегда показывается только один слайд. Осуществляется это посредством скрытия всех элементов (слайдов) располагающихся за пределами области внутри .slider__wrapper
. В CSS это осуществляется посредством установки .slider__wrapper
свойства overflow
со значением hidden
.
.slider__wrapper { overflow: hidden; }

Переход от одного слайда к другому осуществляется посредством CSS трансформаций. Для этого к .slider__items
посредством кода JavaScript добавляется CSS свойство transform
, значение которого содержит функцию translateX
с определённым значением. Например, если данной функции указать в качестве значения -100%, то браузер осуществит переход к следующему слайду, а если наоборот, 100% - то к предыдущему.

Время и скорость, с которой будет осуществляться трансформация определяется с помощью CSS свойства transition:
.slider__items { transition: transform 0.7s ease; }
Логика работы слайдера:
'use strict'; var slideShow = (function () { return function (selector, config) { var _slider = document.querySelector(selector), // основный элемент блока _sliderContainer = _slider.querySelector('.slider__items'), // контейнер для .slider-item _sliderItems = _slider.querySelectorAll('.slider__item'), // коллекция .slider-item _sliderControls = _slider.querySelectorAll('.slider__control'), // элементы управления _currentPosition = 0, // позиция левого активного элемента _transformValue = 0, // значение трансформации .slider_wrapper _transformStep = 100, // величина шага (для трансформации) _itemsArray = [], // массив элементов _timerId, _indicatorItems, _indicatorIndex = 0, _indicatorIndexMax = _sliderItems.length - 1, _stepTouch = 50, _config = { isAutoplay: false, // автоматическая смена слайдов directionAutoplay: 'next', // направление смены слайдов delayAutoplay: 5000, // интервал между автоматической сменой слайдов isPauseOnHover: true // устанавливать ли паузу при поднесении курсора к слайдеру }; // настройка конфигурации слайдера в зависимости от полученных ключей for (var key in config) { if (key in _config) { _config[key] = config[key]; } } // наполнение массива _itemsArray for (var i = 0, length = _sliderItems.length; i < length; i++) { _itemsArray.push({ item: _sliderItems[i], position: i, transform: 0 }); } // переменная position содержит методы с помощью которой можно получить минимальный и максимальный индекс элемента, а также соответствующему этому индексу позицию var position = { getItemIndex: function (mode) { var index = 0; for (var i = 0, length = _itemsArray.length; i < length; i++) { if ((_itemsArray[i].position < _itemsArray[index].position && mode === 'min') || (_itemsArray[i].position > _itemsArray[index].position && mode === 'max')) { index = i; } } return index; }, getItemPosition: function (mode) { return _itemsArray[position.getItemIndex(mode)].position; } }; // функция, выполняющая смену слайда в указанном направлении var _move = function (direction) { var nextItem, currentIndicator = _indicatorIndex;; if (direction === 'next') { _currentPosition++; if (_currentPosition > position.getItemPosition('max')) { nextItem = position.getItemIndex('min'); _itemsArray[nextItem].position = position.getItemPosition('max') + 1; _itemsArray[nextItem].transform += _itemsArray.length * 100; _itemsArray[nextItem].item.style.transform = 'translateX(' + _itemsArray[nextItem].transform + '%)'; } _transformValue -= _transformStep; _indicatorIndex = _indicatorIndex + 1; if (_indicatorIndex > _indicatorIndexMax) { _indicatorIndex = 0; } } else { _currentPosition--; if (_currentPosition < position.getItemPosition('min')) { nextItem = position.getItemIndex('max'); _itemsArray[nextItem].position = position.getItemPosition('min') - 1; _itemsArray[nextItem].transform -= _itemsArray.length * 100; _itemsArray[nextItem].item.style.transform = 'translateX(' + _itemsArray[nextItem].transform + '%)'; } _transformValue += _transformStep; _indicatorIndex = _indicatorIndex - 1; if (_indicatorIndex < 0) { _indicatorIndex = _indicatorIndexMax; } } _sliderContainer.style.transform = 'translateX(' + _transformValue + '%)'; _indicatorItems[currentIndicator].classList.remove('active'); _indicatorItems[_indicatorIndex].classList.add('active'); }; // функция, осуществляющая переход к слайду по его порядковому номеру var _moveTo = function (index) { var i = 0, direction = (index > _indicatorIndex) ? 'next' : 'prev'; while (index !== _indicatorIndex && i <= _indicatorIndexMax) { _move(direction); i++; } }; // функция для запуска автоматической смены слайдов через промежутки времени var _startAutoplay = function () { if (!_config.isAutoplay) { return; } _stopAutoplay(); _timerId = setInterval(function () { _move(_config.directionAutoplay); }, _config.delayAutoplay); }; // функция, отключающая автоматическую смену слайдов var _stopAutoplay = function () { clearInterval(_timerId); }; // функция, добавляющая индикаторы к слайдеру var _addIndicators = function () { var indicatorsContainer = document.createElement('ol'); indicatorsContainer.classList.add('slider__indicators'); for (var i = 0, length = _sliderItems.length; i < length; i++) { var sliderIndicatorsItem = document.createElement('li'); if (i === 0) { sliderIndicatorsItem.classList.add('active'); } sliderIndicatorsItem.setAttribute("data-slide-to", i); indicatorsContainer.appendChild(sliderIndicatorsItem); } _slider.appendChild(indicatorsContainer); _indicatorItems = _slider.querySelectorAll('.slider__indicators > li') }; var _isTouchDevice = function () { return !!('ontouchstart' in window || navigator.maxTouchPoints); }; // функция, осуществляющая установку обработчиков для событий var _setUpListeners = function () { var _startX = 0; if (_isTouchDevice()) { _slider.addEventListener('touchstart', function (e) { _startX = e.changedTouches[0].clientX; _startAutoplay(); }); _slider.addEventListener('touchend', function (e) { var _endX = e.changedTouches[0].clientX, _deltaX = _endX - _startX; if (_deltaX > _stepTouch) { _move('prev'); } else if (_deltaX < -_stepTouch) { _move('next'); } _startAutoplay(); }); } else { for (var i = 0, length = _sliderControls.length; i < length; i++) { _sliderControls[i].classList.add('slider__control_show'); } } _slider.addEventListener('click', function (e) { if (e.target.classList.contains('slider__control')) { e.preventDefault(); _move(e.target.classList.contains('slider__control_next') ? 'next' : 'prev'); _startAutoplay(); } else if (e.target.getAttribute('data-slide-to')) { e.preventDefault(); _moveTo(parseInt(e.target.getAttribute('data-slide-to'))); _startAutoplay(); } }); document.addEventListener('visibilitychange', function () { if (document.visibilityState === "hidden") { _stopAutoplay(); } else { _startAutoplay(); } }, false); if (_config.isPauseOnHover && _config.isAutoplay) { _slider.addEventListener('mouseenter', function () { _stopAutoplay(); }); _slider.addEventListener('mouseleave', function () { _startAutoplay(); }); } }; // добавляем индикаторы к слайдеру _addIndicators(); // устанавливаем обработчики для событий _setUpListeners(); // запускаем автоматическую смену слайдов, если установлен соответствующий ключ _startAutoplay(); return { // метод слайдера для перехода к следующему слайду next: function () { _move('next'); }, // метод слайдера для перехода к предыдущему слайду left: function () { _move('prev'); }, // метод отключающий автоматическую смену слайдов stop: function () { _config.isAutoplay = false; _stopAutoplay(); }, // метод запускающий автоматическую смену слайдов cycle: function () { _config.isAutoplay = true; _startAutoplay(); } } } }()); slideShow('.slider', { isAutoplay: true });
Код слайдера написан на «чистом» JavaScript, без использования библиотеки jQuery. Программный код структурирован и организован в виде «модуля».
Основные функции, выполняющие всю логику, используемые внутри модуля slideShow
:
_startAutoplay
– функция для запуска автоматической смены слайдов через определённые промежутки времени определяемым параметромdelayAutoplay
(по умолчанию 5 секунд);_stopAutoplay
– функция, отключающая автоматическую смену слайдов;_move
– функция, выполняющая смену слайда в указанном направлении;_slideTo
– функция, осуществляющая переход к слайду по его порядковому номеру; она используется при обработке события «click» на индикаторах;_addIndicators
– функция, добавляющая индикаторы к слайдеру;_setupListener
– функция, осуществляющая установку обработчиков для событий для слайдера.
Данные функции организуют логику работу слайдера. Они доступны как было уже отмечено выше только внутри модуля, к ним нельзя обратиться вне его.
Что делать если слайдер не работает
Если слайдер не работает, то одной из причин может быть то, что у вас скрипт подключен выше самого HTML кода слайдера. В этом случае JavaScript код слайдера необходимо обернуть в эту конструкцию (чтобы он отрабатывал после загрузки DOM страницы):
document.addEventListener('DOMContentLoaded', function(){ // здесь необходимо разместить код слайдера var slideShow = (function () { // ... }()); slideShow('.slider', { isAutoplay: true }); });
У меня такой вопрос: есть php-код, который выводит информацию из xml-файла на сайт. Среди выводимых элементов — изображения, которые и надо листать слайдером. Вот эта часть кода:
После вывода первого элемента из файла и всех относящихся к нему изображений, слайдер перестаёт работать. Т.е., на последующих элементах и их изображениях слайдера не видно.
Можно ли как-то сделать так, чтобы слайдер работал для каждого элемента?
есть ли возможность сделать слайдер адаптивным по высоте относительно контента в нем? то есть если блок текста, например, в одном из слайдов выше чем высота слайдера, чтобы он увеличивался и обратно уменьшался при переключении.
спасибо
Так (открыть пример)?
Замените её на следующую:
После этого инициализацию слайдера можно будет выполнять как посредством передачи функции slideShow селектора, так и DOM-элемента:
Подскажите пожалуйста, можно для мабайла грузить одно разрешение баннеров а для десктора другое? что бы гугл не ругался.
Заранее благодарен.
Прошу подсказать как правильно расположить баннер в слайдер.
Правая часть слайдера остается пустой как будто длины баннера не хватает.
Заранее благодарю.
Отцентровать этот слайдер можно, например, так (открыть пример):
multiItemSlider('#slider-1', {
isAutoplay: true
});
multiItemSlider('#slider-2', {
isAutoplay: true
});
Пытался добавлять этот код в ф-цию _setUpListeners, но безуспешно(
if (_isTouchDevice()) {
_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');
4
}
});
} else {
_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');
}
});
}
Попробуйте <img> установить блочное отображение:
Вы наш добрый Ангел!***))) Все работает! Как всегда полезный и обьяснен до мелочей чудо-урок!
кстати, все ваши видео на Ютуб также шикарны, я ваш верный подписчик, Спасибо!!!
Спасибо большое!
Только не могу вынести кнопки прокрутки слайдов за основной блок, не ломая всю остальную конструкцию. Подскажите пожалуйста, есть ли какое то решение данной проблемы?
Но теперь, при переключении слайдов с transform 0.6s края фоновых картинок не скрываются за закруглением границ.
var slideShow = (function () {
});
Сайт видит файл подключенный, но ничего не работает в плане скрипта, что делать?
Допустим на главной слайдер с картинками, а в личном кабинете хочу сделать слайдер текстовый.
После этого к стилям к которые нужно применить к первому слайдеру добавить «.slider-1», а ко второму – «.slider-2»:
Пример слайдера, к которому добавлено дополнительное управление с помощью стрелок клавиатуры.
Установил слайдер и возник небольшой вопрос — если использовать индикаторы и описание слайдера, то они соответственно накладываются друг на друга. Можно ли переместить описание слайдеров под сам слайдер?
Можно сделать и так. Но, если хотите расположить описания над изображениями, то можно просто к описаниям добавить padding, чтобы они не накладывались на индикаторы. Как это выполнить можно посмотреть в этом примере.
Тогда можно было бы оставить описание, а индикаторы расположить под слайдером. Тут имею в виду визуально за пределами области слайдера, например как в этом примере стрелки влево/вправо. Пробовал так сделать, но видимо что-то не так делал, т.к. индикаторы все равно располагались поверх слайдера.
И еще возник вопрос по использованию двух слайдов через flex: 0 0 50%. Они располагаются вплотную друг к другу, не подскажете как можно добавить отступ между картинками?
При использовании двух слайдов (через flex: 0 0 50%) сам слайдер находится в элементе <div class="slider__item">...</div>. Чтобы добавить какие-то отступы вы просто делаете нужную в нём разметку. Например, создаёте в нём элемент (дополнительную обёртку) и устанавливаете ему нужные padding. Остальной контент слайда помещаете уже в него. В результате у вас слайд будет иметь нужные отступы.
Если делал общую обертку, то в полной версии(при flex: 0 0 50%) блоки с переключателями влево/вправо смещался за пределы слайдеров на значение padding.
И самая главная проблема, которую сначала даже не заметил, в полной версии сайта при прокрутке, когда имеющиеся слайды заканчиваются, он не возвращает на первый а продолжает листать показывая пустые блоки и так до бесконечности. При этом в мобильной версии все работает как надо, не подскажете в чем может быть причина?
И еще вопрос, в данных примерах не работает переход между слайдами свайпом, можно это как-то добавить в эту версию слайдера?
Ваш слайдер лучший из всех, спасибо вам огромное.
В данный момент разрабатываю сайт как раз использую ваш слайдер.
Появилась необходимость добавить к тексту на каждом слайде анимацию (animate.css), и вот тут как раз очень нужна ваша помощь.
Использовать сторонние разработки WOW или AOS и похожих решений не хочется.
Да и невозможно, наверное, с данным слайдером.
Изучил ваш код JS я не могу найти как можно реализовать добавление и удаление классов.
Добавить вообще не проблема, а вот удалить при смене слайда не понимаю, как, так как слайд каждый не является активным в данный момент времени.
Знаний в JS у меня недостаточно, поэтому и не могу найти решения.
Подскажите пожалуйста, как можно добавлять и удалять классы CSS для каждого слайда, повторно используя уже написанные вами функции.
Наверное, вы уже это делали на данном слайдере в своих работах.
Или вообще, как это реализовать.
Заранее большое вам спасибо!
Я смотрю на функцию
// функция, добавляющая индикаторы к слайдеру
_addIndicators
Здесь мы определяем конкретный слайд и добавляем class 'active'
Александр подскажите пожалуйста как можно, подобным способом добавлять и удалять классы анимации, в текст на слайдах.
В местах, где к индикаторам добавляется класс «active» добавьте ещё строчки, выполняющее это действие по отношению к слайдам:
Вы волшебник!!!
Всё идеально работает!!!
Анимацию сделал на всех слайдах…
Идеально!!!
Это лучший слайдер, что есть в инете.
Скорее всего какие-то другие стили вашего проекта переопределяют их.
HTML + PHP код который сейчас (по сути стандартная структура слайдера + указание типа записи и цикл вывода)
CSS и JS не изменялся.
Прошу помочь, ещё раз благодарю!
PS. Думаю стоит внести изменения в статье, ну и в код.
Но я столкнулся с проблемой, у меня не получается вставить этот слайдер во flex контейнер, в своем шаблоне, как мне решить этот вопрос?
АЛЕКСАНДР, СПАСИБО
ВОПРОС
слайдер плавно листает, если стрелки нажимать
но резко меняет фото автоматически
как сделать автоматику плавной?
Статья и все примеры на странице обновлены, сейчас слайдеры имеют плавную анимацию.
Если строку удалить — анимация и все все все, работает шикарно.
Но вот с ним — нет.
Есть ли возможность у Вас помочь, разобраться
Делал так, менял префикс везде. Анимация все ровно сбоит.
И выносил отдельно js и стили, и вносил их в head, и пробовал при помощи включаемой области на битрикс, все уже перепробовал… все ровно не работает…
Слайдер без зацикливания можно посмотреть в этом примере.
Показывает первый слайд и всё. Нажатие на кнопки навигации ничего не даёт.
Можно это поправить?
Спасибо.
В этом случае для включения поддержки необходимых старых браузеров удобно использовать полифиллы. Как это сделать посмотрите в этом комментарии.
Вам необходимо просто вызывать функцию slideShow отдельно для каждого слайдера:
Демку, где на одной странице используется несколько каруселей можно посмотреть здесь.
Есть вопрос, а как сделать так, что, если кликается по активному slider__indicators — у, ничего никуда не перемещалось?
Добавил: