지그재그 클론코딩(4) 배너 슬라이드 만들기

GY·2021년 6월 20일
0

Vanilla JS Project

목록 보기
8/19
post-thumbnail

결과물

이전에 만들었던 것과 같이 클릭하면 변경되는 이미지 슬라이드로 배너를 만들고 싶었다.

그런데, 기존의 방법으로도,
새로 시도한 addEventListener을 사용한 방법으로도 같은 에러가 떴다.

Uncaught TypeError

Uncaught TypeError: Cannot read property 'addEventListener' of null

이 오류가 계속 뜬다.
우선 이 에러의 의미는 무엇일까?

HTML이 모두 로드 되기 전에 자바스크립트 영역에서 HTML을 참조하는데,
addEventListener에서 HTML태그를 참조할 수 없어 null을 참조했고 에러가 발생하는 것이라고 한다.

시도한 해결방법 #1 window.onload

오류가 나는 함수를 window.onload함수 내부에 넣는다.
window.onload=function(){}함수는 웹 브라우저의 모든 요소를 로드한 이후에 호출되기 때문에,
이 에러가 해결될 수 있다.
(http://blog.naver.com/PostView.nhn?blogId=quki09&logNo=220710183742)

안된다!!!!!!!!!!!!!!!!!!!!!!!!!!

시도한 해결방법 #2 script태그

script태그를 head가 아닌 body 최하단에 넣기

아마도 비동기 처리를 제대로 못한 것 같다.
콜백과 프로미스 함수 개념도 제대로 잡혀있지 않은 것 같다.공부를 해도 아직 머릿속에서 모호하다.
다시 차근차근 돌아가 공부해보자.

시도한 해결방법 #3 callback function

(콜백함수 게시글 참고)

그래도 안된다!!!!!

그래도 안된다...

그래서, 이미지 슬라이드를 만드는 다른 방법들을 찾아 공부해보던 도중 js없이 html/css만으로 슬라이드를 구현하는 방법을 찾았다.

먼저 따라해본 뒤, 내 프로젝트에 적용해보았다.
대신 따라쓰는 코드인만큼 코드 한 줄 한 줄이 무슨 의미이고 어떤 역할인지 분명히 짚어가며 주석으로 달아보기로 했다. 언젠가 적용시킬 수 있는 기회가 있다면 다시 써보면서 내 것으로 체화시키고 싶으니까!

html/css만으로 이미지 슬라이드 만들기

스크립트 없이 슬라이드 효과 만들기

기존에 혼자서 작성했던 슬라이드 코드 외에 다른 코드로 슬라이드를 만드는 방법은 뭐가 있을까?
이전에는 다른 사람들의 코드를 보고 만들지는 않았기 때문에, 보다 다양한 방법을 보고 싶었다.

input태그 중 radio타입을 이용한 버전

radio타입 인풋태그의 특성

  • radio타입은 한번 체크하면 해제가 되지 않고, 동일한 그룹 중 하나만 체크가 가능하다.
  • 라벨을 텍스트와 인풋태그에 동일하게 적용하면, 텍스트를 클릭해도 체크가 된다.

이전에는 이전/다음 버튼과 이미지별 버튼의 동작함수를 개별적으로 만들어 코드를 작성했었다. 하지만 이런 특성을 활용하면 다음버튼을 눌렀을 때 동일하게 이미지별 버튼이 체크되어 이미지변경이 되도록 간편하게 만들 수 있다는 장점이 있을 것 같다.

white-space:nowrp;
부모요소의 틀을 뚫고 가로 한 줄로 정렬된다.

html

<div class="section">
      <input type="radio" class="slide" id="slide01" checked />
      <input type="radio" class="slide" id="slide02" />
      <input type="radio" class="slide" id="slide03" />
  <div class="slidewrap">
    <ul class="slidelist">
      <li>
        <a>
        <!-- a태그로 배너처럼 클릭해 링크 이동 가능 -->
          <label for="slide03" class="left"></label>
          <!-- label을 slide03으로 설정했기 때문에,
        이 left버튼을 누르면 같은 slide03을 id로 갖는 radio버튼이 눌린다. -->
          <img src="./img/banner1.png" />
          <label for="slide02" class="right"></label>
          <!-- label을 slide02로 설정했기 때문에,
            이 right버튼을 누르면 radio버튼의 slide02를 id로 가지는 버튼이 눌린다. -->
        </a>
      </li>
      <li>
        <a>
          <label for="slide01" class="left"></label>
          <img src="./img/banner2.png" />
          <label for="slide03" class="right"></label>
          <!-- 2번 이미지가 노출되었을 때는,
        왼쪽 버튼은 slide01, 오른쪽 버튼은 slide03의 라벨이 적용되어
    동일한 id값을 갖는 radio버튼이 눌리고, 해당 이미지로 이동한다. -->

          <!-- 배너 이미지 출처:https://www.pinterest.co.kr/pin/3377768461355481/ -->
        </a>
      </li>
      <li>
        <a>
          <label for="slide02" class="left"></label>
          <!-- label을 slide03으로 설정했기 때문에,
        이 left버튼을 누르면 같은 slide03을 id로 갖는 radio버튼이 눌린다. -->
          <img src="./img/banner3.png" />
          <label for="slide01" class="right"></label>
          <!-- label을 slide02로 설정했기 때문에,
            이 right버튼을 누르면 radio버튼의 slide02를 id로 가지는 버튼이 눌린다. -->
        </a>
      </li>
    </ul>
  </div>
</div>
### css
```jsx

/* 배너 */
/* input radio 버튼 가리기 */
.section input[id*="slide"] {
  display: none;
}

/* 슬라이드 영역 크기 조절 */
.section {
  display: flex;
  justify-content: center;
}
.section .slidewrap {
  max-width: 100vw;
  margin-bottom: 20px;
  margin-top: 13px;
  overflow: hidden;
  /* 영역보다 큰 부분은 자르기 */
}
.section .slidelist {
  white-space: nowrap;
  /* 안쪽 인라인 요소 줄바꿈을 없앰 */
  font-size: 0;
    /* 안쪽 공백 없앰 */
}
.section .slidelist > li {
  display: inline-block;
  /* 여기가 중요!!list태그로 만든 각 슬라이드 이미지들이 한 줄로 가로 정렬되도록 만든다.
   */
  vertical-align: middle;
  /* 각 이미지들의 높이가 다를 경우,가운데를 기준으로 정렬해 준다 */
  width: 100%;
  /* 슬라이드 영역(이미지가 노출되는 곳)에 딱맞도록 너비를 설정해준다. */
  /* 여기까지 하면, 노출 영역에 딱 맞도록 첫번째 이미지만 보이게 되고, 오른쪽으로 가로로 한 줄정렬되어 있는 다른 이미지는 보이지 않게 된다. */
  transition: all 0.5s;
  /* 0.5초간 서서히 움직인다. */
}
.section .slidelist > li > a {
  display: block;
  position: relative;
  /* 이건 왜지? */
}
.section .slidelist > li > a img {
  width: 100%;
    /* 이미지 크기를 반응형으로 설정 */
}

/* 좌우로 넘기는 label버튼 스타일 지정 */
.section .slidelist label {
  position: absolute;
  z-index: 1;
  top: 50%;
  transform: translateY(-50%);
  padding: 50px;
  cursor: pointer;
}
/* 이것도 다시 살펴보자. */
.section .slidelist .left {
  left: 0px;
  background: url("./img/left.png") center center / 50% no-repeat;
}
.section .slidelist .right {
  right: 0px;
  background: url("./img/right.png") center center/50% no-repeat;
}
/* input 체크될 경우 변화값이 li까지 전달될 수 있도록 하는 아주 중요한 부분!!!!!! */
.section input[id="slide01"]:checked ~ .slidewrap .slidelist > li {
  transform: translateX(0%);
}
.section input[id="slide02"]:checked ~ .slidewrap .slidelist > li {
  transform: translateX(-105%);
}
.section input[id="slide03"]:checked ~ .slidewrap .slidelist > li {
  transform: translateX(-209%);
}

클릭하면 위와 같이 다른 이미지로 넘어간다.

Review

아쉬운점

  • 첫번째에서 두번째 이미지로 넘어가고 나면, 위 이미지와 같이 양 옆에 공간이 남아 전후 이미지가 함께 조금씩 보인다. 이 부분을 해결해야 한다.
  • 배너의 크기가 애매모호하다. 배너 컨테이너 영역의 너비를 변경해 보기 좋게 변경해주면 좋을 것 같다.

배운점

  • 이미지 경로 변경하는 방법외에도 이미지 슬라이드를 만들 수 있는 방법
  • 이미지를 inline-block으로 가로 정렬해 특정 영역에만 이미지를 보일 수 있게 한 뒤, 하나씩 이동시켜주면 가능하다. transition으로 애니메이션 효과를 주면 옆으로 넘기는 효과도 줄 수 있다.
  • 이미지를 넘길 때는 transform:translateX()를 사용한다. X축으로 얼만큼 이동시켜줄것인지를 결정한다.이때 slidelist의 li태그를 함께 이동시켜준다.
profile
Why?에서 시작해 How를 찾는 과정을 좋아합니다. 그 고민과 성장의 과정을 꾸준히 기록하고자 합니다.

0개의 댓글