본문으로 건너뛰기

Swiper 슬라이드 인덱스 리셋 방법

·3 min read

Swiper(v11) 슬라이더에서 특정 동작 이후에 인덱스를 0으로 되돌려야 했다. 가장 자연스러운 선택은 slideTo(0)이었는데, 의도와 다른 부작용이 따라붙었다.

slideTo(0)이 끌어들인 페이지 스크롤

swiper.slideTo(0);

이 호출로 인덱스는 0으로 갔다. 그런데 슬라이더가 뷰포트 밖에 있을 때 페이지가 슬라이더 위치까지 스크롤되는 현상이 같이 일어났다.

처음에는 slideTo 자체가 페이지 스크롤을 일으키는 줄 알았다. 소스를 따라가 보니 slideTo 함수 본체에는 window.scroll()·focus()·scrollIntoView() 같은 호출이 없었다. wrapper 요소의 scrollLeft·scrollTop만 조작한다.

원인은 다른 데 있었다. Swiper의 a11y 모듈이 슬라이드 변경 시 새 active 슬라이드 안의 포커스 가능 요소에 focus()를 옮기는데, 브라우저가 focused element를 자동으로 뷰포트에 노출하는 표준 동작이 같이 트리거된 결과였다. v11에는 이 자동 포커스 이동을 끄는 옵션이 없어서, slideTo 경로 자체를 피해야 했다.

setTranslate + updateActiveIndex로 우회

스크롤 부작용 없이 인덱스만 0으로 맞추고 싶었다. 트랜스폼 위치를 직접 0으로 되돌리고 active index 상태를 따로 갱신하는 방식으로 우회했다.

swiper.setTranslate(0);
swiper.updateActiveIndex(0);

이 조합은 슬라이더에 포커스를 옮기지 않으므로 페이지 스크롤이 따라오지 않는다. 다만 updateActiveIndex는 Swiper 공식 API 문서의 Methods 섹션에 노출돼 있지 않은 내부 업데이트 메서드다. 동작은 했지만, 메이저 버전이 올라가면 시그니처가 바뀔 수 있다는 점은 같이 적어뒀다.

두 경로의 차이

페이지 스크롤이 따라붙지 않으면서 슬라이더 인덱스만 0으로 초기화됐다. 둘 다 "인덱스를 0으로 만든다"는 결과는 같다. 차이는 부수효과에 있었다. slideTo 경로는 a11y의 자동 포커스 이동을 끌어들이는 반면, setTranslate + updateActiveIndex 경로는 시각 상태만 되돌리고 포커스를 건드리지 않는다.