Коротко — у Apple на страницах используются большие «full‑bleed» слайдеры с плавной кинематикой, парллаксом текста/изображения, touch/drag с инерцией, lazy‑load, responsive картинками и аккуратной доступностью. Самый быстрый путь — взять готовую библиотеку (Swiper/Flickity/Glide/Splide) и настроить; если нужно «на чистом JS», можно сделать с помощью CSS scroll‑snap + немного JS (проще) либо реализовать drag+inertia вручную (сложнее).
Ниже дам два варианта: 1) готовый и быстрый — Swiper.js (легко настроить под вид Apple); 2) лёгкий vanilla‑вариант на CSS scroll‑snap + JS для управления и lazy‑load.
1) Быстрый вариант — Swiper.js (рекомендую)
- Плюсы: мобильная оптимизация, парллакс, loop, pagination, keyboard, mousewheel, хорошо отладить быстро.
- Установка: CDN или npm. Пример с CDN.
HTML
```html
<link rel="stylesheet" href="https://unpkg.com/swiper@9/swiper-bundle.min.css" />
<div class="swiper my-swiper">
<div class="swiper-wrapper">
<div class="swiper-slide">
<div class="slide-bg" data-swiper-parallax="-20%">
<picture>
<source srcset="img/slide1@2x.webp" type="image/webp">
<img src="img/slide1.jpg" alt="Описание слайда 1" loading="lazy">
</picture>
</div>
<div class="slide-content" data-swiper-parallax="-40%">
<h2>Заголовок слайда</h2>
<p>Короткий текст, CTA кнопка</p>
</div>
</div>
<!-- ещё .swiper-slide -->
</div>
<!-- навигация / пагинация -->
<div class="swiper-pagination"></div>
<div class="swiper-button-prev" aria-label="Previous slide"></div>
<div class="swiper-button-next" aria-label="Next slide"></div>
</div>
<script src="https://unpkg.com/swiper@9/swiper-bundle.min.js"></script>
```
CSS (базовый)
```css
.my-swiper { width:100%; height: 70vh; position:relative; overflow:visible; }
.swiper-slide { display:flex; align-items:center; justify-content:center; position:relative; overflow:hidden; }
.slide-bg img { width:100%; height:100%; object-fit:cover; display:block; }
.slide-content { position:absolute; left:6%; bottom:18%; color:#fff; max-width:40rem; }
.swiper-button-prev, .swiper-button-next { color:#fff; }
```
JS (инициализация)
```js
const swiper = new Swiper('.my-swiper', {
loop: true,
speed: 900,
parallax: true,
grabCursor: true,
centeredSlides: true,
slidesPerView: 1,
spaceBetween: 0,
autoplay: {
delay: 6000,
disableOnInteraction: false,
},
pagination: { el: '.swiper-pagination', clickable: true },
navigation: { nextEl: '.swiper-button-next', prevEl: '.swiper-button-prev' },
keyboard: { enabled: true, onlyInViewport: true },
mousewheel: { forceToAxis: true },
// если нужен эффект похожий на Apple — можно поиграть с speed и parallax
});
```
Дополнительно:
- Используйте <picture> и srcset для responsive изображений.
- Включите lazy loading (Swiper поддерживает lazy module).
- Для видео-слайдов используйте апдейты при смене слайда (остановка/воспроизведение).
- Для более «плотной» кинематики можно подключить freeMode и настроить momentum, или использовать установленную скорость и parallax.
2) Лёгкий вариант на CSS scroll‑snap + vanilla JS
Подходит если нужен «скролл‑снеп» поведение (горизонтальная прокрутка) и вы хотите минимальный JS.
HTML
```html
<div class="snap-container" id="slider">
<section class="snap-slide">
<picture> ... </picture>
<div class="content">...</div>
</section>
<!-- ещё слайды -->
</div>
<nav class="dots" id="dots"></nav>
```
CSS
```css
.snap-container {
display:flex;
overflow-x:auto;
scroll-snap-type:x mandatory;
-webkit-overflow-scrolling:touch;
scroll-behavior:smooth;
}
.snap-slide {
flex: 0 0 100%;
scroll-snap-align:start;
position:relative;
min-height:70vh;
}
.snap-slide img { width:100%; height:100%; object-fit:cover; display:block; }
```
JS (активный слайд, точки и автоплей)
```js
const container = document.getElementById('slider');
const slides = [...container.querySelectorAll('.snap-slide')];
const dots = document.getElementById('dots');
slides.forEach((s, i) => {
const btn = document.createElement('button');
btn.className = 'dot';
btn.addEventListener('click', () => {
s.scrollIntoView({behavior:'smooth', inline:'start'});
});
dots.appendChild(btn);
});
const io = new IntersectionObserver(entries => {
entries.forEach(e => {
if (e.isIntersecting) {
const idx = slides.indexOf(e.target);
document.querySelectorAll('.dot').forEach((d, i) => d.classList.toggle('active', i === idx));
}
});
}, { threshold: 0.6 });
slides.forEach(s => io.observe(s));
// autoplay
let auto = true;
let autoplayInterval = 6000;
let timer = setInterval(next, autoplayInterval);
container.addEventListener('pointerdown', () => { clearInterval(timer); auto = false; });
function next() {
if (!auto) return;
const current = document.querySelector('.dot.active');
const i = [...document.querySelectorAll('.dot')].indexOf(current);
const nextIndex = (i + 1) % slides.length;
slides[nextIndex].scrollIntoView({behavior:'smooth', inline:'start'});
}
```
Плюсы scroll-snap варианта: простота, нативная инерция, хорошая доступность; минусы: не так «гладко» подгоняется кинематика как в нативных слайдерах с физикой, сложнее зациклить (loop) без клонирования.
Практические советы и «фишки», чтобы получить вид как у Apple
- Используйте большие изображения формата WebP/AVIF, responsive srcset, lazy loading.
- Делайте парллакс: смещайте текст и фон в разной степени при скролле/передвижении слайда (через data-attributes и transform translate3d).
- Для плавности анимируйте transform (translateZ, translate3d) и opacity; избегайте анимации свойств layout (top/left/width).
- Оптимизируйте: preconnect к CDN, responsive images, compress assets, критический CSS inline, defer JS.
- Доступность: добавьте role="region" aria-label, кнопки навигации с aria-controls/aria-label, keyboard support, остановка автоплей при фокусе.
- Видео в слайдах: предзагрузка по требованию, автоплей только при mute и при видимости слайда (IntersectionObserver).
- Тестируйте на слабых устройствах — Apple придаёт большое значение производительности.
Если вы хотите — могу:
- Подготовить для вас готовый комплект (HTML/CSS/JS) под конкретную верстку (укажите макет, желаемую высоту слайдера, нужны ли видео и loop).
- Помочь настроить Swiper с точной конфигурацией под визуал, который вы покажете (можете прислать ссылку/скрин).
Какой вариант предпочитаете — готовая библиотека (быстро) или «чистый» vanilla‑код (легковесно, но чуть больше работы)?