+
+
+
+
+
diff --git a/recipes/slider/index.md b/recipes/slider/index.md
new file mode 100644
index 0000000000..d4eab804da
--- /dev/null
+++ b/recipes/slider/index.md
@@ -0,0 +1,748 @@
+---
+title: "Слайдер"
+description: "Пишем доступный слайдер на HTML, CSS и JavaScript."
+authors:
+ - annabaraulina
+contributors:
+ - tatianafokina
+ - skorobaeus
+keywords:
+ - баннеры
+ - перелистывающиеся баннеры
+ - css-слайдер
+related:
+ - a11y/aria-labelledby
+ - html/button
+ - recipes/popup
+tags:
+ - article
+---
+
+## Задача
+
+Слайдер или слайд-шоу — распространённый дизайнерский паттерн на сайтах, особенно на лендингах. Слайдер состоит из нескольких слайдов, обычно с изображениями или с видео-контентом. Между слайдами можно переключаться, также бывают варианты с автоматической прокруткой и кнопками для управления анимацией.
+
+
+
+Слайдер — неоднозначный элемент. С одной стороны, он экономит место на странице, вмещает больше контента за счёт прокрутки, а ещё привлекает внимание. С другой — его сложно сделать удобным и доступным для всех пользователей.
+
+В этом рецепте расскажем, как создать доступный слайдер, в котором подумаем про дизайн и учтём семантику.
+
+## Готовое решение
+
+Для начала создадим HTML-разметку со всеми нужными элементами — общим контейнером, кнопками для переключения слайдов и самими слайдами с картинками и заголовками.
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Паттерн «Лето»
+
+
+
+
Паттерн «Цветочное поле»
+
+
+
+
Паттерн «Лиловый»
+
+
+
+
Паттерн «Алый»
+
+
+
+```
+
+Для стилизации слайдера используем такие [CSS-правила](/css/css-rule/):
+
+```css
+.controls {
+ margin-block-end: 20px;
+}
+
+.button {
+ cursor: pointer;
+ user-select: none;
+}
+
+.button-radio {
+ background-color: transparent;
+ margin: 0;
+ padding: 0;
+ inline-size: 15px;
+ block-size: 15px;
+ border-radius: 50%;
+ border: 1px solid #FFFFFF;
+}
+
+.button-radio + .button-radio {
+ margin-inline-start: 12px;
+}
+
+.button-radio.active {
+ background-color: #C56FFF;
+ pointer-events: none;
+}
+
+.button-radio:focus-visible {
+ outline: 3px solid white;
+ outline-offset: -1px;
+}
+
+.button-prev,
+.button-next {
+ position: absolute;
+ inset-block-start: 50%;
+ transform: translateY(-50%);
+ border: none;
+ inline-size: 30px;
+ block-size: 42px;
+ background-color: transparent;
+ background-image: url(./images/arrow.svg);
+ background-repeat: no-repeat;
+ background-size: contain;
+}
+
+.button-prev[aria-disabled="true"],
+.button-next[aria-disabled="true"] {
+ opacity: 0.5;
+ pointer-events: none;
+}
+
+.button-prev {
+ inset-inline-start: -50px;
+}
+
+.button-next {
+ inset-inline-end: -50px;
+ transform: translateY(-50%) rotateY(180deg);
+ transform-origin: center;
+}
+
+.slide-img {
+ display: block;
+ inline-size: 100%;
+ block-size: 225px;
+ max-block-size: 225px;
+ object-fit: cover;
+}
+
+.slider {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ max-inline-size: 600px;
+ inline-size: 100%;
+ position: relative;
+}
+
+.slides {
+ inline-size: 100%;
+}
+
+.slide {
+ display: none;
+ text-align: center;
+}
+
+.slide--active {
+ display: block;
+}
+
+@media (max-width: 768px) {
+ .slider {
+ max-inline-size: 260px;
+ }
+
+ .slide-img {
+ block-size: 400px;
+ }
+
+ .button-prev {
+ inset-inline-start: -40px;
+ }
+
+ .button-next {
+ inset-inline-end: -40px;
+ }
+}
+```
+
+Для прокрутки и перемещения по слайдам с помощью кнопок и клавиатурных клавиш со стрелками используем JavaScript:
+
+```javascript
+document.addEventListener('DOMContentLoaded', function () {
+ const slider = document.querySelector('.slider')
+ const slides = slider.querySelectorAll('.slide')
+ const activeSlides = 'slide--active'
+ const slideCount = slides.length
+ const controlButtons = slider.querySelectorAll('.button-radio')
+ const prevButton = slider.querySelector('.button-prev')
+ const nextButton = slider.querySelector('.button-next')
+ const activeButton = 'active'
+ const inactiveButton = 'aria-disabled'
+ const currentButton = 'aria-current'
+ let currentSlide = 0
+
+ function updateSlider() {
+ slides.forEach((slide, index) => {
+ if(index === currentSlide) {
+ slide.classList.add(activeSlides)
+ } else {
+ slide.classList.remove(activeSlides)
+ }
+ })
+
+ controlButtons.forEach((button, index) => {
+ if (index === currentSlide) {
+ button.classList.add(activeButton)
+ button.setAttribute(currentButton, true)
+ } else {
+ button.classList.remove(activeButton)
+ button.removeAttribute(currentButton, true)
+ }
+
+ prevButton.setAttribute(inactiveButton, currentSlide === 0)
+ nextButton.setAttribute(inactiveButton, currentSlide === slideCount - 1)
+ })
+ }
+
+ controlButtons.forEach((button, index) => {
+ button.addEventListener('click', () => {
+ if (index < slideCount) {
+ currentSlide = index
+ updateSlider()
+ }
+ })
+ })
+
+ prevButton.addEventListener('click', () => {
+ if (currentSlide > 0) {
+ currentSlide--
+ updateSlider()
+ }
+ })
+
+ nextButton.addEventListener('click', () => {
+ if (currentSlide < slideCount - 1) {
+ currentSlide++
+ updateSlider()
+ }
+ })
+
+ slider.addEventListener('keydown', function (event) {
+ if (event.key === 'ArrowLeft' && currentSlide > 0) {
+ currentSlide--
+ updateSlider()
+ } else if (event.key === 'ArrowRight' && currentSlide < slideCount - 1) {
+ currentSlide++
+ updateSlider()
+ }
+ })
+
+ updateSlider()
+})
+```
+
+
+
+## Разбор решения
+
+### Дизайн
+
+С точки зрения дизайна важно учесть особенности восприятия пользователей, которые чувствительны к движущемуся контенту. Это проблема для людей с когнитивными, моторными или зрительными особенностями.
+
+Слайдер должен быть под полным контролем пользователей, поэтому мы не будем добавлять автопрокрутку.
+
+### HTML
+
+Вместо автоматической прокрутки добавляем кнопки для последовательного переключения слайдов. Важно, чтобы интерактивные элементы контрастировали с фоном слайдера. Так как тип кнопок по умолчанию `submit`, установим руками другой тип `button`. Мы не отправляем данные на сервер, и нам не нужна перезагрузка страницы.
+
+```html
+
+```
+
+Не ограничивайтесь одними стрелками для предыдущего и следующего слайда и предоставляйте пользователю альтернативный способ навигации. С помощью специальных кнопок, которые называют _точками прогресса (progress dots)_, также показываем пользователю текущее положение в группе слайдов.
+
+```html
+
+
+
+```
+
+Расположение элементов в [DOM](/js/dom/) (Document Object Model) влияет на порядок, в котором пользователи клавиатуры перемещаются по странице. По этой причине располагаем элементы навигации перед слайдером, а не после него. В этом случае пользователю не нужно будет возвращаться назад, чтобы прокрутить слайды:
+
+```html
+
+
+
+
+
+
+
+```
+
+Содержимое слайдов группируем в одном [`
`](/html/div/).
+
+```html
+
+
+
+```
+
+### Семантика и ARIA-разметка
+
+В первую очередь используем семантические теги [`