Решение проблемы с исчезновением пагинации Swiper при фокусе на ссылках
Проблема
При навигации по странице с помощью клавиши Tab, когда фокус попадает на ссылку внутри слайда Swiper, пагинация (буллеты/номера страниц) может исчезать. Это происходит потому, что Swiper по умолчанию скрывает некоторые элементы управления при отсутствии явного взаимодействия со слайдером.
Подробное решение
1. Настройка параметров Swiper
Добавьте следующие параметры в конфигурацию вашего Swiper:
const swiper = new Swiper('.swiper', { // Основные параметры slidesPerView: 1, spaceBetween: 30, // Критически важные настройки для решения проблемы watchOverflow: true, observer: true, observeParents: true, observeSlideChildren: true, // Пагинация pagination: { el: '.swiper-pagination', clickable: true, renderBullet: function (index, className) { return '<span class="' + className + '">' + (index + 1) + '</span>'; }, }, // Дополнительные настройки для улучшения доступности a11y: { enabled: true, prevSlideMessage: 'Previous slide', nextSlideMessage: 'Next slide', paginationBulletMessage: 'Go to slide {{index}}', }, // Автоматическое скрытие элементов управления (отключаем или настраиваем) autoHeight: false, });
2. CSS решение для принудительного отображения пагинации
Добавьте в ваш CSS:
.swiper-pagination { opacity: 1 !important; visibility: visible !important; transition: opacity 0.3s ease; } /* Сохраняем пагинацию видимой при фокусе на элементах внутри слайда */ .swiper-slide:focus-within .swiper-pagination { opacity: 1 !important; visibility: visible !important; } /* Альтернативный подход - всегда показывать пагинацию */ .swiper-container .swiper-pagination { display: flex !important; }
3. JavaScript решение с обработчиками событий
const swiper = new Swiper('.swiper', { // ... остальная конфигурация }); // Обработчики для поддержания видимости пагинации const pagination = document.querySelector('.swiper-pagination'); const links = document.querySelectorAll('.swiper-slide a'); // При фокусе на ссылке показываем пагинацию links.forEach(link => { link.addEventListener('focus', () => { pagination.style.opacity = '1'; pagination.style.visibility = 'visible'; }); link.addEventListener('blur', () => { // Опционально: скрываем пагинацию после потери фокуса // pagination.style.opacity = '0'; // pagination.style.visibility = 'hidden'; }); }); // Дополнительно: обновляем Swiper при изменениях swiper.update();
4. Полное решение с кастомными классами
class AccessibleSwiper { constructor(selector) { this.swiper = new Swiper(selector, { pagination: { el: '.swiper-pagination', clickable: true, }, // ... другие настройки }); this.initAccessibility(); } initAccessibility() { const slides = this.swiper.slides; slides.forEach((slide, index) => { const focusableElements = slide.querySelectorAll('a, button, input, [tabindex]'); focusableElements.forEach(element => { element.addEventListener('focus', () => { this.swiper.pagination.el.classList.add('pagination-visible'); this.swiper.pagination.el.style.opacity = '1'; }); element.addEventListener('blur', () => { this.swiper.pagination.el.classList.remove('pagination-visible'); }); }); }); } } // Использование const accessibleSwiper = new AccessibleSwiper('.swiper-container');
5. Дополнительные CSS стили для доступности
/* Базовые стили для пагинации */ .swiper-pagination { position: absolute; bottom: 10px; width: 100%; display: flex; justify-content: center; z-index: 10; } /* Состояние при фокусе */ .swiper-pagination:focus, .swiper-pagination-bullet:focus { outline: 2px solid #007bff; outline-offset: 2px; } /* Класс для принудительного отображения */ .pagination-visible { opacity: 1 !important; visibility: visible !important; } /* Улучшение видимости для accessibility */ .swiper-pagination-bullet { width: 12px; height: 12px; margin: 0 6px; background: #000; opacity: 0.5; } .swiper-pagination-bullet-active { opacity: 1; background: #007bff; }
6. Альтернативное решение с MutationObserver
const swiper = new Swiper('.swiper', { // ... конфигурация }); // Наблюдаем за изменениями в пагинации const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.type === 'attributes' && mutation.attributeName === 'style' && mutation.target.classList.contains('swiper-pagination')) { const style = window.getComputedStyle(mutation.target); if (style.opacity === '0' || style.visibility === 'hidden') { mutation.target.style.opacity = '1'; mutation.target.style.visibility = 'visible'; } } }); }); observer.observe(document.querySelector('.swiper-pagination'), { attributes: true, attributeFilter: ['style'] });
Рекомендации по реализации:
- Начните с CSS решения - это самое простое и эффективное
- Протестируйте с различными устройствами и браузерами
- Убедитесь, что решение не нарушает другие функции Swiper
- Добавьте плавные переходы для лучшего пользовательского опыта
- Протестируйте доступность с помощью инструментов like Lighthouse
Важные моменты:
- Всегда обновляйте Swiper после динамических изменений:
swiper.update()
- Тестируйте с реальными пользователями, особенно с теми, кто использует клавиатуру для навигации
- Учитывайте производительность при использовании MutationObserver
Это комплексное решение должно решить проблему с исчезновением пагинации при фокусе на ссылках внутри слайдов Swiper.