Создание карусели с помощью CSS Scroll Snap и JavaScript

Это руководство поможет вам создать адаптивную карусель с помощью свойства CSS scroll-snap и очень небольшого количества JavaScript для навигации. Вы можете использовать ее для демонстрации товаров, в качестве галереи или для своих отзывов — как в примере, приведенном в этом руководстве. Итак, вот что мы будем создавать.

На самом деле это просто горизонтальный слайдер, но когда вы прокручиваете его, он «перещелкивается» (автоматически регулирует положение контейнера прокрутки), чтобы обеспечить отображение всего элемента, ведя себя как карусель. Вы также можете использовать стрелки для отображения следующего и предыдущего элементов, для этого потребуется JavaScript. Чтобы продолжить, вам потребуется иметь базовые знания HTML, CSS и JavaScript. В процессе изучения этого руководства вы узнаете о свойствах привязки прокрутки CSS. Давайте начнем.

Настройка

Создайте пустой HTML-документ и назовите его index.html. Добавьте базовый скелет HTML. Если вы используете Visual Studio Code, все, что вам нужно сделать, это ввести «!» и нажать Enter. Вы получите следующее.

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Document</title>
</head>
<body>
   
</body>
</html>

В этой демонстрации используется шрифт Noto Sans. Давайте встроим этот шрифт из Google Fonts. Добавьте приведенную ссылку на CDN под тегом title, чтобы встроить обычный и курсивный стили этого шрифта.

<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,400;0,700;1,400&display=swap" rel="stylesheet">

Создайте таблицу стилей и назовите ее style.css. Свяжите таблицу стилей с HTML-документом под ссылкой на CDN Google fonts, используя

<link rel="stylesheet" href="style.css">

Для использования в этой демонстрации я загрузил три портретных изображения с Pexels и обрезал их под квадрат. Вы же можете добавить свои собственные. Назовите их testimonial1.jpg, testimonial2.jpg и testimonial3.jpg.

Создание базового скроллера

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

HTML

Добавьте эту разметку в тег body в ранее созданном HTML-файле:

<div class="testimonials">
   <div class="scroller">
       <div class="item">
           Item 1
       </div>
       <div class="item">
           Item 2
       </div>
       <div class="item">
           Item 3
       </div>
   </div>
</div>

Здесь div testimonials действует как оболочка, внутри которой располагается горизонтальный scroller, а затем три элемента div.

CSS

В файле style.css начнем с некоторых общих стилей для всех элементов.

	* {
   margin: 0;
   padding: 0;
   box-sizing: border-box;
}
Добавьте приведенные ниже  стили к элементу body.
	body {
   font-family: 'Noto Sans', sans-serif;
   font-size: 1em;
   color: #4A5568;
}

Ограничьте ширину оболочки testimonials примерно до 800 пикселей и отцентрируйте ее.

.testimonials {
   max-width: 800px;
   margin: auto;
}

Добавьте следующие базовые стили, чтобы увидеть, как работает скроллер.

.scroller {
   overflow-x: scroll;
   display: flex;
}
.item {
   min-width: 100%;
   min-height: 200px; /* To start with */
   background-color: #EDF2F7; /* For demo */
}

При этом вы можете увидеть продемонстрированную ниже ​​секцию горизонтальной прокрутки.

CSS

Привязка прокрутки

С помощью привязки прокрутки CSS можно принудительно установить положение прокрутки (плавное перемещение в заданное положение), как только пользователь прекратит прокрутку. Это работает за счет применения двух основных свойств — scroll-snap-typeи scroll-snap-align.

Свойство scroll-snap-type применяется к родительскому контейнеру (в нашем случае это div scroller). Оно принимает два аргумента — направление привязки (x | y | both) и поведение привязки (mandatory | proximity). Нам нужно использовать x для направления, потому что мы создаем горизонтальную прокрутку. Что касается поведения, mandatory означает, что браузер должен привязываться к позиции, но proximity менее строг. Мы будем использовать mandatory.

Свойство scroll-snap-align применяется к дочерним элементам. Оно определяет точку привязки. Свойство принимает один или два аргумента для направлений x и / или y (none | start | end | center). В нашем случае это свойство может иметь любое значение кроме none, потому что наши элементы составляют 100% ширины родительского контейнера.

Добавьте приведенные ниже свойства для блоков scroller и item.

.scroller {
   /* Здесь существующие стили */
   scroll-snap-type: x mandatory;
}
.item {
   /* Здесь существующие стили */
   scroll-snap-align: center;
}

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

Добавление контента

Давайте добавим элементам контент.

HTML

<div class="item">
   <img src="testimonial1.jpg" alt="Elise">
   <div class="card">
       <p>
           Eu rebum molestie per. No nostrud imperdiet abhorreant qui, hinc incorrupte vix ad. Vel id aliquip oblique. Primis feugait sit an, brute illud convenire duo ea. Graece tempor eripuit sed in.
       </p>
       <span>Elise</span>
   </div>
</div>
<div class="item">
   <img src="testimonial2.jpg" alt="John">
   <div class="card">
       <p>
           Vitae pericula maluisset ut mei, pro eleifend gubergren eu. Et his brute graeci. Affert ponderum ei vel, dolorum accumsan ea has. Sea oblique salutatus ei, simul lucilius pri et. Errem melius temporibus ut eos
       </p>
       <span>John</span>
   </div>
</div>
<div class="item">
   <img src="testimonial3.jpg" alt="Imani">
   <div class="card">
       <p>
           Ne est virtute indoctum, quaeque vituperata cum ut. Te nisl quaeque pri. Vix ex autem latine, mel ne nobis scaevola, ei est dolor utinam commune. Pri unum doctus in, cu primis pertinax eos.
       </p>
       <span>Imani</span>
   </div>
</div>

CSS

Пора добавить стили.

.testimonials {
   /* Здесь существующие стили */
   padding: 15px;
   text-align: center;
}
.item {
   /* Здесь существующие стили */
   background-color: white; /* Change the value to white */
   margin-bottom: 10px;
   padding: 0 50px;
}
.item img {
   margin: 15px auto -60px;
   width: 120px;
   height: 120px;
   border: solid 4px #ffffff;
   border-radius: 60px;
   box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
   z-index: 2;
}
.card {
   background-color: rgb(237, 242, 247);
   padding: 80px 40px 40px;
   border-radius: 10px;
   box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
   z-index: 1;
}
.card p {
   font-style: italic;
   line-height: 1.6;
}
.card span {
   display: block;
   margin-top: 20px;
   color: teal;
   font-weight: bold;
   letter-spacing: 0.05em;
   text-transform: uppercase;
}

Наша карусель стилизована. Единственное, чего не хватает — это функционал навигации.

Добавление навигации

В этой демонстрации для кнопок навигации я добавил простые стрелки с символами < и >. Вы также можете использовать иконки или изображения.

HTML

Добавьте приведенные ниже две строки сразу после div scroller, но внутри div testimonial:

<span class="btn prev">&lt;</span>
<span class="btn next">&gt;</span>

CSS

Добавьте приведенный ниже код в таблицу стилей для позиционирования и стилизации кнопок навигации.

.testimonials {
   /* Здесь существующие стили */
   position: relative;
}
.testimonials .btn {
   position: absolute;
   top: 50%;
   margin-top: 20px;
   height: 30px;
   width: 30px;
   border-radius: 15px;
   background-color: rgba(95, 106, 117, 0.3);
   z-index: 1;
   line-height: 30px;
   text-align: center;
   color: white;
   font-weight: bold;
}
.testimonials .btn:hover{
   background-color: rgba(95, 106, 117, 0.5);
   cursor: pointer;
}
.testimonials .btn.next {
   right: 15px;
}
.testimonials .btn.prev {
   left: 15px;
}

JavaScript

Нам нужен JavaScript, чтобы кнопки работали. Добавьте приведенный ниже скрипт перед закрывающим тегом body.

<script>
   const testimonials = document.querySelector('.testimonials');
   const scroller = testimonials.querySelector('.scroller');
   const nextBtn = testimonials.querySelector('.btn.next');
   const prevBtn = testimonials.querySelector('.btn.prev');
   const itemWidth = testimonials.querySelector('.item').clientWidth;
  
   nextBtn.addEventListener('click', scrollToNextItem);
   prevBtn.addEventListener('click', scrollToPrevItem);
  
   function scrollToNextItem() {
       scroller.scrollBy({left: itemWidth, top: 0, behavior: 'smooth'});
   }
   function scrollToPrevItem() {
       scroller.scrollBy({left: -itemWidth, top: 0, behavior: 'smooth'});
   }
</script>

В этом коде мы добавили к кнопкам prev и next обработчик события «нажатие кнопки». Функционал перехода к предыдущему или следующему элементу достигается с помощью метода scrollBy. Ознакомьтесь с синтаксисом и примерами метода element.scrollBy.

Параметр дает behavior: ‘smooth’ эффект плавного скольжения. Обратите внимание на то, что этот эффект не поддерживается в IE 11 и некоторых устаревших версиях других браузеров.

Создаем цикл

При желании можно зациклить карусель — нажатие кнопки «Далее» для последнего элемента заставляет карусель запускаться с начала и аналогичное поведение для кнопки «Предыдущий» — изменив методы в скрипте на приведенные ниже:

function scrollToNextItem() {
   if(scroller.scrollLeft < (scroller.scrollWidth - itemWidth))
       // Позиция прокрутки расположена не в начале последнего элемента
       scroller.scrollBy({left: itemWidth, top: 0, behavior:'smooth'});
   else
       // Достигнут последний элемент. Возвращаемся к первому элементу, установив для позиции прокрутки 0
       scroller.scrollTo({left: 0, top: 0, behavior:'smooth'});
}
function scrollToPrevItem() {
   if(scroller.scrollLeft != 0)
       // Позиция прокрутки расположена не в начале последнего элемента
       scroller.scrollBy({left: -itemWidth, top: 0, behavior:'smooth'});
   else
       // Это первый элемент. Переходим к последнему элементу, установив для позиции прокрутки ширину скроллера
        scroller.scrollTo({left: scroller.scrollWidth, top: 0, behavior:'smooth'});
}

Делаем карусель полностью адаптивной

То, что у нас есть сейчас, уже адаптивно. За исключением того, что для ширины окна браузера меньше, чем 480px, карточка становится слишком узкой и длинной. Итак, давайте уменьшим отступ для элемента и карточки для этой ширины с помощью медиа-запросов.

Добавьте в таблицу стилей приведенный ниже код:

@media screen и (max-width: 480px) {
.item {
padding: 0 30px;
}
.card {
padding: 80px 30px 30px;
}
}

Вот и все! Вы успешно создали адаптивную карусель для раздела отзывов с минимальным количеством JavaScript, а также узнали о новых свойствах CSS scroll-snap. Вы можете изменить эту карусель в соответствии со своими потребностями. Попробуйте использовать ее для изображений различной ширины и посмотрите, как она себя ведет.

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

СКАЧАТЬ ИСХОДНЫЙ КОД

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

Пожалуйста, опубликуйте ваши комментарии по текущей теме статьи. За комментарии, подписки, лайки, отклики, дизлайки низкий вам поклон!

Вадим Дворниковавтор-переводчик статьи «Create a Carousel using CSS Scroll Snap and JavaScript»