[SeSAC Front-end] JS 슬라이드 네비게이션

Harimad·2022년 11월 14일
0

js

목록 보기
10/14
post-thumbnail

0. 들어가며

이번 장에서는 바닐라 자바스크립트로 슬라이드 네비게이션을 구현해 보겠습니다.
버튼을 눌렀을 때 슬라이드가 왼쪽, 오른쪽으로 이동하도록 만들어 보겠습니다.

이번 장에서 다음과 같은 개념을 볼 수 있습니다.

  • CSS flex
  • CSS position: relative, absolute
  • CSS calc()
  • CSS transition
  • CSS selector
  • JS DOM selector
  • JS DOM eventListener
  • JS Event
  • 슬라이드 페이지네이션(pagination)

1. 슬라이드 네비게이션 (오직 버튼만 이용)

1-1. HTML code

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Vanilla JS Slide Navigation</title>
	<link rel="stylesheet" href="style.css">
</head>

<body>
	<div class="slide">
		<div class="slide-box">1</div>
		<div class="slide-box">2</div>
		<div class="slide-box">3</div>
		<div class="slide-box">4</div>
		<div class="slide-box">5</div>
		<div class="slide-btn slide-btn-left ">👈</div>
		<div class="slide-btn slide-btn-right ">👉</div>
	</div>

	<script src="main.js"></script>
</body>

</html>

1-2. CSS code

.slide {
  display: flex;
  flex-wrap: nowrap;
  overflow: hidden; /*컨테이너안의 내용이 해당 컨테이너 크기(너비, 높이)를 넘어가면, 보이지 않기 위함 */
  position: relative; /*자식 태그인 slide-btn에게 position absolute 적용하기 위함*/
  width: 100%;
}

.slide-box {
  /* 가운데 정렬 */
  display: flex;
  justify-content: center;
  align-items: center;

  /* 👉or👈 버튼 클릭시 left offeset 값을 적용시키기 위함 */
  position: relative;
  left: 0px;

  /* 사이즈 */
  width: 100%;
  height: 300px;

  /* flex item의 flex-shrink 기본값이 1이다. 즉, 컨테이너 크기에 맞게 줄어듬. */
  /* 슬라이드 구현을 위해 줄어들지 않도록 0 줌 */
  flex-shrink: 0;

  transition: left 0.2s;
}

.slide-btn {
  /* 가운데 정렬 */
  display: flex;
  justify-content: center;
  align-items: center;

  position: absolute;

  top: calc(50% - 16px); /* 버튼 중앙 위치*/

  width: 2rem;
  height: 2rem;

  border-radius: 100%;
  background: rgba(200, 200, 200, 0.7);
  cursor: pointer;
  user-select: none;
}

.slide-btn-left {
  left: 10px;
}

.slide-btn-right {
  right: 10px;
}

.slide-box {
  font-size: 2rem;
  color: ivory;
}
.slide-box:first-child {
  background-color: red;
}
.slide-box:nth-child(2) {
  background-color: orange;
}
.slide-box:nth-child(3) {
  background-color: yellow;
}
.slide-box:nth-child(4) {
  background-color: green;
}
.slide-box:nth-child(5) {
  background-color: blue;
}

1-3. JavaScript code

const $slide = document.querySelector('.slide')
const $leftBtn = document.querySelector('.slide-btn-left')
const $rightBtn = document.querySelector('.slide-btn-right')
const $slideItems = document.querySelectorAll('.slide-box')

let slideWidth = $slide.clientWidth // 슬라이드 너비
let slideNums = $slideItems.length // 슬라이드 개수
let currentSlide = 1 // 현재 슬라이드 번호

const rightBtnEvent = () => {
  currentSlide++ // 슬라이드 번호 +1

  if (currentSlide <= slideNums) {
    const offset = slideWidth * (currentSlide - 1) // 슬라이드 이동을 위한 offset 계산

    // 각 슬라이드의 left에 offset 적용 (-offset을 줘서 왼쪽으로 이동)
    $slideItems.forEach(item => {
      item.setAttribute('style', `left: ${-offset}px`)
    })
  } else {
    currentSlide--
  }
}

const leftBtnEvent = () => {
  currentSlide-- // 슬라이드 번호 -1

  if (currentSlide > 0) {
    const offset = slideWidth * (currentSlide - 1)
    $slideItems.forEach(item => {
      item.setAttribute('style', `left: ${-offset}px`)
    })
  } else {
    currentSlide++
  }
}

// '👉' 버튼 이벤트 추가
$rightBtn.addEventListener('click', rightBtnEvent)

// '👈' 버튼 이벤트 추가
$leftBtn.addEventListener('click', leftBtnEvent)

// 브라우저 화면 너비가 변경될 때도 slideWidth값 최신화
window.addEventListener('resize', () => {
  slideWidth = $slide.clientWidth // 슬라이드 너비
})

1-4. Live Demo 1 👈



2. 슬라이드 페이지네이션(pagination) 구현 (page Element 추가)

  • 위의 HTML, CSS, JavaSCript 코드에서 추가로 코드를 넣습니다.

2-1. +HTML code

  • slide 클래스 안에 아래의 코드를 넣습니다.
  • slide_pagination 클래스 태그 안에 li를 JS에서 만들 예정입니다.
<div class="slide_pagination"></div>

2-2. +CSS code

  • slide_pagination 클래스와 그 아래의 li 태그에 스타일을 적용합니다.
ul,
li {
  list-style: none;
  padding: 0;
  margin: 0;
}
.slide_pagination {
  display: flex;
  gap: 5px;
  position: absolute;
  bottom: 0;
  /* 가운데로 위치 */
  left: 50%;
  transform: translateX(-50%);
}

.slide_pagination > li {
  color: #7f7fffff;
  cursor: pointer;
  font-size: 2rem;
}
.slide_pagination > li.active {
  color: #ffb5ff;
}

2-3. JavaScript code

  • 클래스가 slide_pagination인 DOM 태그를 가져옵니다.
  • 페이지네이션을 구현하기 위해 슬라이드 개수 만큼 li태그를 생성합니다.
  • 생성된 li태그의 DOM 태그를 가져옵니다.
  • 반복문을 돌리면서 생성된 li태그에 클릭 이벤트를 줍니다.
    • 슬라이드 이동을 위해서 offset 계싼을 해줍니다.
    • 클릭 이벤트가 발생하면 모든 슬라이드 태그에 style의 left속성에 -offset값을 줍니다.
const $slide = document.querySelector('.slide')
const $leftBtn = document.querySelector('.slide-btn-left')
const $rightBtn = document.querySelector('.slide-btn-right')
const $slideItems = document.querySelectorAll('.slide-box')
const $pagination = document.querySelector('.slide_pagination')

let slideWidth = $slide.clientWidth // 슬라이드 너비
let slideNums = $slideItems.length // 슬라이드 개수
let currentSlide = 1 // 현재 슬라이드 번호

// 페이지네이션 생성
for (let i = 0; i < slideNums; i++) {
  if (i === 0) {
    $pagination.innerHTML += `<li class="active">•</li>`
  } else {
    $pagination.innerHTML += `<li>•</li>`
  }
}
const $paginationItems = document.querySelectorAll('.slide_pagination > li')
console.log($paginationItems)

// 슬라이드 이동 할 때 현재 활성화된 pagination 변경
const activePagination = () => {
  $paginationItems.forEach(item => item.classList.remove('active'))
  $paginationItems[currentSlide - 1].classList.add('active')
}

const rightBtnEvent = () => {
  currentSlide++ // 슬라이드 번호 +1

  if (currentSlide <= slideNums) {
    const offset = slideWidth * (currentSlide - 1) // 슬라이드 이동을 위한 offset 계산

    // 각 슬라이드의 left에 offset 적용 (-offset을 줘서 왼쪽으로 이동)
    $slideItems.forEach(item => {
      item.setAttribute('style', `left: ${-offset}px`)
    })
    activePagination()
  } else {
    currentSlide--
  }
}

const leftBtnEvent = () => {
  currentSlide-- // 슬라이드 번호 -1

  if (currentSlide > 0) {
    const offset = slideWidth * (currentSlide - 1)
    $slideItems.forEach(item => {
      item.setAttribute('style', `left: ${-offset}px`)
    })
    // 슬라이드 이동 할 때 현재 활성화된 pagination 변경
    activePagination()
  } else {
    currentSlide++
  }

}

// '👉' 버튼 이벤트 추가
$rightBtn.addEventListener('click', rightBtnEvent)

// '👈' 버튼 이벤트 추가
$leftBtn.addEventListener('click', leftBtnEvent)

// 브라우저 화면 너비가 변경될 때도 slideWidth값 최신화
window.addEventListener('resize', () => {
  slideWidth = $slide.clientWidth // 슬라이드 너비
})

// 페이지네이션 클릭 할 때 해당 슬라이드로 이동
for (let i = 0; i < slideNums; i++) {
  // 각 페이지네이션 마다 클릭 이벤트 추가
  $paginationItems[i].addEventListener('click', () => {
    currentSlide = i + 1 // curSlide의 시작 위치가 1이기 때문
    const offset = slideWidth * (currentSlide - 1) // 슬라이드 이동을 위한 offset 계산
    console.log(slideWidth, currentSlide, slideWidth * (currentSlide - 1))
    // 각 슬라이드 아이템의 left에 offset 적용
    $slideItems.forEach(item => {
      item.setAttribute('style', `left: ${-offset}px`)
    })
    // 슬라이드 이동 할 때 현재 활성화된 pagination 변경
    activePagination()
  })
}

2-4. Live Demo2 👈



나가면서

  • 지금까지 버튼만을 이용해서 슬라이드 네비게이션을 구현했습니다.
  • 참고사항에 드래그를 이용해서 스와이프를 구현하거나, 자동 슬라이드, 무한 슬라이드 구현도 참고할 수 있습니다.
  • 만약에 직접구현하는 방식 보다 라이브러리를 사용해 보고싶다면 Swiper를 확인해보시길 추천드립니다.
  • 부트스트랩의 Carousel을 이용해 보는 것도 좋습니다.

참고


'새싹DT 기업연계형 프론트엔드 실무 프로젝트 과정 5주차 블로그 포스팅'

profile
Here and Now. 🧗‍♂️

0개의 댓글