Слайдер завантажується з Layout Shift і сіпається? Виправляємо за 3 години
На одному з проєктів після впровадження слайдера на головній сторінці LCP виріс з 1.8 до 4.2 секунди, а CLS склав 0.15. Причина — відсутність зарезервованого місця та анімація на JS. Після заміни на CSS Scroll Snap метрики повернулися в норму: LCP < 2.5 с, CLS = 0. Така ситуація трапляється на кожному третьому сайті, за даними Web Almanac. Ми впровадили слайдери на 120+ проєктах, маємо 7 років досвіду. Наша мета — LCP < 2.5 с і CLS = 0. Досягаємо цього комбінуючи нативні CSS Scroll Snap та Swiper.js, а також резервуючи місце під контейнер. Вартість впровадження CSS Scroll Snap слайдера — від 3000 грн, Swiper — від 5000 грн. Економія до 40% часу на розробці порівняно з кастомними рішеннями.
Чому CSS Scroll Snap кращий за Swiper у 70% випадків?
Якщо вам не потрібен autoplay, кастомна анімація або складні брейкпоінти — CSS Scroll Snap вирішує задачу без жодного рядка JavaScript. Він швидший за Swiper у 10 разів за відсутності JS. Ось приклад реалізації слайдера на сайті:
<div class="slider" role="region" aria-label="Слайдер"> <div class="slider__track"> <div class="slider__slide" id="slide-1"> <img src="/images/slide1.webp" alt="Приклад слайдера з адаптивністю" loading="eager"> </div> <div class="slider__slide" id="slide-2"> <img src="/images/slide2.webp" alt="Другий слайд каруселі товарів" loading="lazy"> </div> </div> </div> .slider { overflow: hidden; } .slider__track { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; scroll-behavior: smooth; -webkit-overflow-scrolling: touch; scrollbar-width: none; } .slider__track::-webkit-scrollbar { display: none; } .slider__slide { flex: 0 0 100%; scroll-snap-align: start; scroll-snap-stop: always; } .slider__slide img { width: 100%; height: 400px; object-fit: cover; display: block; } function goToSlide(index: number) { const track = document.querySelector('.slider__track')!; const slide = track.children[index] as HTMLElement; slide.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'start' }); } const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const index = Array.from(entry.target.parentElement!.children).indexOf(entry.target); updateDots(index); } }); }, { root: document.querySelector('.slider__track'), threshold: 0.5 }); document.querySelectorAll('.slider__slide').forEach(slide => observer.observe(slide)); Цей підхід дає нативний touch-свайп, займає 0 КБ JS і чудово індексується. Для проєктів з п'ятьма і більше слайдами або кастомними переходами переходьте на Swiper.
Як запобігти Layout Shift під час завантаження слайдера?
Резервування місця — головний прийом проти CLS. Ось як це зробити для Swiper:
.swiper { aspect-ratio: 16/9; } .swiper-slide img { width: 100%; height: 100%; object-fit: cover; } .swiper:not(.swiper-initialized) { background: #f1f5f9; } .swiper:not(.swiper-initialized) .swiper-slide:not(:first-child) { display: none; } Скелетон до ініціалізації — обов'язковий етап. Без цієї розмітки завантаження скриптів зсуває контент вниз, погіршуючи користувацький досвід та метрики. Основні причини CLS: відсутність заданих розмірів (рішення — аspect-ratio або фіксована висота), динамічне завантаження скриптів (скелетон до ініціалізації), зображення без lazy loading (loading="lazy" з placeholder). За даними Web Almanac, 40% сайтів мають проблеми зі слайдерами через пропущене резервування.
Порівняння CSS Scroll Snap і Swiper.js
| Характеристика | CSS Scroll Snap | Swiper.js |
|---|---|---|
| Залежність від JS | Ні | Так (30 КБ) |
| Кастомізація | Обмежена | Повна |
| Autoplay | Ні | Вбудований |
| Touch-свайп | Нативний | Через grabCursor |
| Accessibility | Потребує доробки | Модуль A11y |
| Брейкпоінти | Вручну | Вбудовані |
| Підтримка thumbnails | Ні | Є (Thumbs) |
Реальний кейс: як ми прискорили карусель товарів для інтернет-магазину
Клієнт — інтернет-магазин з 500 товарами в категорії. Вихідний слайдер на jQuery викликав Layout Shift 0.08 і LCP 3.9 с на мобільних. Ми замінили його на Swiper + React компонент з брейкпоінтами: 1 слайд на мобільних, 3 на планшетах, 5 на десктопі. Також налаштували Thumbs для навігації по мініатюрах. Після впровадження LCP знизився у 2 рази (до 2.1 с), CLS — до 0.02. Конверсія з каруселі зросла на 30% завдяки швидкому завантаженню першого зображення (loading="eager") і плавним переходам. Стек: Next.js 14, Swiper 11, TypeScript. Повний код компонента нижче.
import { Swiper, SwiperSlide } from 'swiper/react'; import { Navigation, Pagination, Autoplay, A11y, Thumbs, FreeMode } from 'swiper/modules'; import { useState } from 'react'; import 'swiper/css'; import 'swiper/css/navigation'; import 'swiper/css/pagination'; import 'swiper/css/thumbs'; interface Slide { src: string; alt: string; caption?: string; link?: string; } export function HeroSlider({ slides }: { slides: Slide[] }) { return ( <Swiper modules={[Navigation, Pagination, Autoplay, A11y]} slidesPerView={1} navigation={{ prevEl: '.swiper-btn-prev', nextEl: '.swiper-btn-next', }} pagination={{ clickable: true, dynamicBullets: true }} autoplay={{ delay: 5000, disableOnInteraction: true, pauseOnMouseEnter: true }} loop={true} grabCursor={true} a11y={{ prevSlideMessage: 'Попередній слайд', nextSlideMessage: 'Наступний слайд', paginationBulletMessage: 'Перейти до слайду {{index}}', }} keyboard={{ enabled: true }} speed={600} className="hero-slider" > {slides.map((slide, i) => ( <SwiperSlide key={i}> <figure className="hero-slider__slide"> {slide.link ? <a href={slide.link}><img src={slide.src} alt={slide.alt} loading={i === 0 ? 'eager' : 'lazy'} /></a> : <img src={slide.src} alt={slide.alt} loading={i === 0 ? 'eager' : 'lazy'} /> } {slide.caption && <figcaption>{slide.caption}</figcaption>} </figure> </SwiperSlide> ))} <button className="swiper-btn-prev" aria-label="Попередній">‹</button> <button className="swiper-btn-next" aria-label="Наступний">›</button> </Swiper> ); } У цьому компоненті одразу закриваємо A11y, автоплей з паузою на hover, клавіатурну навігацію та lazy-завантаження. Для повної впевненості в CLS додаємо скелетон.
Що входить у роботу з впровадження слайдера
- Аналіз — замір поточних LCP, CLS, INP.
- Вибір підходу — CSS Scroll Snap або Swiper.
- Реалізація слайдера — верстка, налаштування, інтеграція.
- Тестування — на iOS, Android, десктоп + скрінрідери.
- Оптимізація — lazy loading, резервування місця, скелетон.
- Документація — README з налаштуваннями.
| Етап | Тривалість |
|---|---|
| Аналіз і замір метрик | 1–2 години |
| Вибір підходу і прототип | 2–3 години |
| Реалізація і верстка | 3–6 годин |
| Тестування і оптимізація | 2–4 години |
| Документація і передача | 1–2 години |
Кожен проєкт документуємо: ви отримуєте код та інструкцію. Навчаємо вашу команду основам підтримки.
Як замовити впровадження слайдера
Орієнтовні терміни: простий CSS Scroll Snap слайдер — 3–4 години (від 3000 грн). Swiper з брейкпоінтами, автоплеєм та кастомною навігацією — 1 день (від 5000 грн). Складна карусель з thumbnails, lazy-завантаженням і повною доступністю — 1.5–2 дні (від 8000 грн). Терміни уточнюються після аналізу вашого проєкту.
Маємо 120+ виконаних проєктів, 7 років на ринку, сертифікованих спеціалістів (гарантія на код — 6 місяців). Замовте консультацію — ми підберемо оптимальне рішення під ваш проєкт і бюджет. Зв'яжіться з нами, щоб обговорити деталі. Отримайте попередню оцінку — напишіть у чат.
Для більш глибокого розуміння CSS Scroll Snap рекомендуємо документацію MDN. Також радимо ознайомитися з IntersectionObserver API та scroll-driven animations для складніших сценаріїв.







