CSS3의 animation 속성을 사용하여 Carousel 인터페이스를 구현하는 방법을 알아봅니다. 홈페이지에서 Carousel을 사용하는 이유는 주요 콘텐츠를 순서에따라 좌우로 이동하며 보여줄 수 있습니다. 아무래도 제한된 공간에서 강조할 콘텐츠를 가장 효과적으로 보여줄 수 있죠. 사용자 경험 측면에서도 효과적입니다.


먼저 Carousel을 구현하기 위하여 생각할 부분은 아래와 같습니다.

  • i. 애니메이션은 어떻게 구현할 것인가?
  • ii. 자동으로 다음으로 넘어가는 코드는?

애니메이션을 구현하기의 경우 스크립트를 사용할 수 있으나 여기서는 가급적 스크립트 사용을 최소화 해보려고합니다. 그래서 필수적인 부분만 스크립트를 쓰고 나머지는 모두 CSS를 쓰되 특히 CSS3의 animation@keyframes 쿼리를 사용합니다.

사실 이 방법이 스크립트 방식보다 효과적이다 말하기는 어렵습니다. 자바스크립트 DOM을 효과적으로 사용하는것도 좋은 방법이므로 학습! 이런 방식으로 구현 할 수도 있다는 것이 목표입니다.
먼저 스크립트 사용을 최소화하고 싶지만 필수적인 스크립트 부분은 어디일까요? 아래의 부분은 CSS만으로 해결할 수 없습니다...

- 클릭 후 다음 또는 이전으로 전환
- 일정 시간 후 자동으로 다음으로 이동

그럼 아래부터는 예제를 만들어 더 자세하게 알아봅니다.



# CSS3를 사용헌 Carousel 예제소스 보기

먼저 구현된 CSS  및 HTML코드입니다.

@ HTML 코드
아래는 html 코드입니다.
<span>Carousel css3 animation</span>
<div id="carousel">
  <nav>
    <div class="gallery-view no1" id="gallery">
      <div class="no3 no">
        3
      </div>
      <div class="no1 no">
        1
      </div>
      <div class="no2 no">
        2
      </div>
      <div class="no3 no">
        3
      </div>
      <div class="no1 no">
         1
      </div>
    </div>
    <div class="control">
      <button onclick="toLeft();">&lt;</button>
      <button onclick="toRight();">&gt;</button>
    </div>
  </nav>
</div>


@ CSS code
다음은 CSS 코드입니다.
#carousel .gallery-view {
  border: 2px solid #000;
  width: 108px;
  height: 54px;
  margin: 0 auto 5px;
  white-space: nowrap;
  letter-spacing: -4px;
}
#carousel .gallery-view .no {
  box-sizing: border-box;
  text-align: center;
  padding: 14px;
  position: relative;
  left: -100px;
  width: 100px;
  height: 50px;
  display: inline-block;
  background: #ffd6c3;
  letter-spacing: 0;
}
/* Animation */
#carousel .gallery-view.no1 .no {
  left: -100px;
  animation: no3 0.5s linear 1;
}
#carousel .gallery-view.no2 .no {
  left: -200px;
  animation: no1 0.5s linear 1;
}
#carousel .gallery-view.no3 .no {
  left: -300px;
  animation: no2 0.5s linear 1;
}
#carousel .gallery-view.no1.lt .no {
  animation: no1lt 0.5s linear 1;
}
#carousel .gallery-view.no2.lt .no {
  animation: no2lt 0.5s linear 1;
}
#carousel .gallery-view.no3.lt .no {
  animation: no3lt 0.5s linear 1;
}

@keyframes no1 {
  0%   {left: -100px;}
  50%  {left: -150px;}
  100% {left: -200px;}
}
@keyframes no2 {
  0%   {left: -200px;}
  50%  {left: -250px;}
  100% {left: -300px;}
}
@keyframes no3 {
  0%   {left: -300px;}
  50%  {left: -350px;}
  100% {left: -400px;}
}
@keyframes no1lt {
  0%   {left: -200px;}
  50%  {left: -150px;}
  100% {left: -100px;}
}
@keyframes no2lt {
  0%   {left: -300px;}
  50%  {left: -250px;}
  100% {left: -200px;}
}
@keyframes no3lt {
  0%   {left: -100px;}
  50%  {left: -50px;}
  100% {left: 0px;}
}

다음으로 필수적인 스크립트는 아래와 같습니다
참고로 아래코드는 전역변수의 사용이 많습니다. 아무래도 전역변수 사용은 피하는 것이 좋겠죠? 적절하게 변경하는 것이 좋아보입니다.
toRight = function() {
  galleryEle = document.querySelector('#gallery');
  galleryEle.classList.remove('lt');
  if (galleryEle.classList.contains('no1')) {
    galleryEle.classList.remove('no1');
    galleryEle.classList.add('no2');
  }
  else if (galleryEle.classList.contains('no2')) {
    galleryEle.classList.remove('no2');
    galleryEle.classList.add('no3');
  }
  else if (galleryEle.classList.contains('no3')) {
    galleryEle.classList.remove('no3');
    galleryEle.classList.add('no1');
  }
  timer = 0;
};

toLeft = function() {
  galleryEle = document.querySelector('#gallery');
  if (galleryEle.classList.contains('no1')) {
    galleryEle.classList.remove('no1');
    galleryEle.classList.add('no3');
    galleryEle.classList.add('lt');
  }
  else if (galleryEle.classList.contains('no2')) {
    galleryEle.classList.remove('no2');
    galleryEle.classList.add('no1');
    galleryEle.classList.add('lt');
  }
  else if (galleryEle.classList.contains('no3')) {
    galleryEle.classList.remove('no3');
    galleryEle.classList.add('no2');
    galleryEle.classList.add('lt');
  }
  timer = 0;
};

setTimeout(function() {
  timer = 0;
  (function aniBinder() {
    setTimeout(function() {
      timer = timer || 1;
      if (timer === 5) {
        galleryEle = document.querySelector('#gallery');
        galleryEle.classList.remove('lt');
        if (galleryEle.classList.contains('no1')) {
          galleryEle.classList.remove('no1');
          galleryEle.classList.add('no2');
         }
         else if (galleryEle.classList.contains('no2')) {
            galleryEle.classList.remove('no2');
            galleryEle.classList.add('no3');
         }
         else if (galleryEle.classList.contains('no3')) {
           galleryEle.classList.remove('no3');            
           galleryEle.classList.add('no1');
         }
         timer = 0;
        }   
        ++timer;
        aniBinder();
    }, 1000);
  })();
}, 2000);
아래는 직접 해당 애니메이션을 실행한 모습입니다. 이처럼 다양한 animation을 css3에서 만들어 구현할 수 있으니 해당 속성에 대하여 활용하면 좋을 것 입니다.


! carousel 예제코드 실제로 동작해보기
위 예제를 구현하면 아래와 같이 나타나게 됩니다.
<span>Carousel css3 animation</span>
<div id="carousel">
<nav>
<div class="gallery-view no1" id="gallery">
<div class="no3 no">
3
</div>
<div class="no1 no">
1
</div>
<div class="no2 no">
2
</div>
<div class="no3 no">
3
</div>
<div class="no1 no">
1
</div>
</div>
<div class="control">
<button onclick="toLeft();"><</button>
<button onclick="toRight();">></button>
</div>
</nav>
</div>
<style>
#carousel .gallery-view {
border: 2px solid #000;
width: 108px;
height: 54px;
margin: 0 auto 5px;
white-space: nowrap;
letter-spacing: -4px;
}
#carousel .gallery-view .no {
box-sizing: border-box;
text-align: center;
padding: 14px;
position: relative;
left: -100px;
width: 100px;
height: 50px;
display: inline-block;
background: #ffd6c3;
letter-spacing: 0;
}
/* Animation */
#carousel .gallery-view.no1 .no {
left: -100px;
animation: no3 0.5s linear 1;
}
#carousel .gallery-view.no2 .no {
left: -200px;
animation: no1 0.5s linear 1;
}
#carousel .gallery-view.no3 .no {
left: -300px;
animation: no2 0.5s linear 1;
}
#carousel .gallery-view.no1.lt .no {
animation: no1lt 0.5s linear 1;
}
#carousel .gallery-view.no2.lt .no {
animation: no2lt 0.5s linear 1;
}
#carousel .gallery-view.no3.lt .no {
animation: no3lt 0.5s linear 1;
}

@keyframes no1 {
0% {left: -100px;}
50% {left: -150px;}
100% {left: -200px;}
}
@keyframes no2 {
0% {left: -200px;}
50% {left: -250px;}
100% {left: -300px;}
}
@keyframes no3 {
0% {left: -300px;}
50% {left: -350px;}
100% {left: -400px;}
}
@keyframes no1lt {
0% {left: -200px;}
50% {left: -150px;}
100% {left: -100px;}
}
@keyframes no2lt {
0% {left: -300px;}
50% {left: -250px;}
100% {left: -200px;}
}
@keyframes no3lt {
0% {left: -100px;}
50% {left: -50px;}
100% {left: 0px;}
}
</style>
<script>
toRight = function() {
galleryEle = document.querySelector('#gallery');
galleryEle.classList.remove('lt');
if (galleryEle.classList.contains('no1')) {
galleryEle.classList.remove('no1');
galleryEle.classList.add('no2');
}
else if (galleryEle.classList.contains('no2')) {
galleryEle.classList.remove('no2');
galleryEle.classList.add('no3');
}
else if (galleryEle.classList.contains('no3')) {
galleryEle.classList.remove('no3');
galleryEle.classList.add('no1');
}
timer = 0;
};
toLeft = function() {
galleryEle = document.querySelector('#gallery');
if (galleryEle.classList.contains('no1')) {
galleryEle.classList.remove('no1');
galleryEle.classList.add('no3');
galleryEle.classList.add('lt');
}
else if (galleryEle.classList.contains('no2')) {
galleryEle.classList.remove('no2');
galleryEle.classList.add('no1');
galleryEle.classList.add('lt');
}
else if (galleryEle.classList.contains('no3')) {
galleryEle.classList.remove('no3');
galleryEle.classList.add('no2');
galleryEle.classList.add('lt');
}
timer = 0;
};

setTimeout(function() {
timer = 0;
(function aniBinder() {
setTimeout(function() {
timer = timer || 1;
if (timer === 5) {
galleryEle = document.querySelector('#gallery');
galleryEle.classList.remove('lt');
if (galleryEle.classList.contains('no1')) {
galleryEle.classList.remove('no1');
galleryEle.classList.add('no2');
}
else if (galleryEle.classList.contains('no2')) {
galleryEle.classList.remove('no2');
galleryEle.classList.add('no3');
}
else if (galleryEle.classList.contains('no3')) {
galleryEle.classList.remove('no3');
galleryEle.classList.add('no1');
}
timer = 0;
}
++timer;
aniBinder();
}, 1000);
})();
}, 2000);
</script>