본문 바로가기
> 클론코딩/분석 및 활용

[CSS] Play and Pause in Infinite Slider with CSS Only (1)

by 자몽주스 2024. 7. 23.
728x90

Play and Pause in Infinite Slider with CSS Only (youtube.com)

HTML
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <main>
      <div
        class="slider"
        style="--width: 100px; --height: 50px; --quantity: 10"
      >
        <div class="list">
          <div class="item" style="--position: 1">
            <img src="images/slider1_1.png" alt="" />
          </div>
          <div class="item" style="--position: 2">
            <img src="images/slider1_2.png" alt="" />
          </div>
          <div class="item" style="--position: 3">
            <img src="images/slider1_3.png" alt="" />
          </div>
          <div class="item" style="--position: 4">
            <img src="images/slider1_4.png" alt="" />
          </div>
          <div class="item" style="--position: 5">
            <img src="images/slider1_5.png" alt="" />
          </div>
          <div class="item" style="--position: 6">
            <img src="images/slider1_6.png" alt="" />
          </div>
          <div class="item" style="--position: 7">
            <img src="images/slider1_7.png" alt="" />
          </div>
          <div class="item" style="--position: 8">
            <img src="images/slider1_8.png" alt="" />
          </div>
          <div class="item" style="--position: 9">
            <img src="images/slider1_9.png" alt="" />
          </div>
          <div class="item" style="--position: 10">
            <img src="images/slider1_10.png" alt="" />
          </div>
        </div>
      </div>

      <div
        class="slider"
        reverse="true"
        style="--width: 200px; --height: 200px; --quantity: 9"
      >
        <div class="list">
          <div class="item" style="--position: 1">
            <img src="images/slider2_1.png" alt="" />
          </div>
          <div class="item" style="--position: 2">
            <img src="images/slider2_2.png" alt="" />
          </div>
          <div class="item" style="--position: 3">
            <img src="images/slider2_3.png" alt="" />
          </div>
          <div class="item" style="--position: 4">
            <img src="images/slider2_4.png" alt="" />
          </div>
          <div class="item" style="--position: 5">
            <img src="images/slider2_5.png" alt="" />
          </div>
          <div class="item" style="--position: 6">
            <img src="images/slider2_6.png" alt="" />
          </div>
          <div class="item" style="--position: 7">
            <img src="images/slider2_7.png" alt="" />
          </div>
          <div class="item" style="--position: 8">
            <img src="images/slider2_8.png" alt="" />
          </div>
          <div class="item" style="--position: 9">
            <img src="images/slider2_9.png" alt="" />
          </div>
        </div>
      </div>
    </main>
  </body>
</html>

HTML
        <div class="list">
            .item*10>img[src="images/slider1_$.png"]
        </div>
  .item*10>img[src="images/slider1_$.png"] 이거 의미 >>
.item*10
: 클래스가 item인 요소를 10개 생성합니다.

>
: 자식 요소를 지정하는 데 사용됩니다.

img[src="images/slider1_$.png"]
: 각 item 요소 내에 src 속성이 
images/slider1_$.png인 img 태그를 추가합니다. 
여기서 $는 인덱스를 나타내며, 각 item 요소마다 숫자가 증가합니다 (즉, 1부터 10까지).​

이렇게 html 작성해주고 css 로 넘어가준다.

의미

  1. <div class="slider">:
    • 이 코드는 HTML의 <div> 요소를 나타내며, 이 요소는 slider라는 클래스 이름을 가집니다.
    • 클래스는 CSS에서 스타일을 지정할 때 사용됩니다.
  2. style="--width: 100px; --height: 50px; --quantity: 10":
    • 이 부분은 인라인 스타일을 설정하는 것을 의미합니다.
    • 일반적인 스타일 속성 외에도 여기서는 CSS 변수를 정의하고 있습니다.
    • * "인라인 스타일"이라는 표현은 HTML 요소의 style 속성에 직접 스타일을 설정한다는 의미
    • 여기서 설정한 스타일은 일반적인 CSS 속성이 아니라, CSS 변수를 정의하고 있습니다.

CSS 변수

  • CSS 변수 --로 시작하며, 여기서는 --width, --height, --quantity 세 가지 변수가 정의되어 있습니다.
    • --width: 100px: 변수 --width는 100px의 값을 가집니다.
    • --height: 50px: 변수 --height는 50px의 값을 가집니다.
    • --quantity: 10: 변수 --quantity는 10의 값을 가집니다.

예제

다음은 CSS 변수들이 실제로 어떻게 사용될 수 있는지에 대한 예입니다:

.slider {
  width: var(--width);
  height: var(--height);
  background-color: lightblue; /* 시각적으로 확인하기 위해 배경색 추가 */
}

.slider::before {
  content: "Quantity: " var(--quantity);
}

설명

  • width: var(--width);:
    • slider 클래스가 있는 요소의 너비를 --width 변수의 값으로 설정합니다. 여기서는 100px이 됩니다.
  • height: var(--height);:
    • slider 클래스가 있는 요소의 높이를 --height 변수의 값으로 설정합니다. 여기서는 50px이 됩니다.
  • content: "Quantity: " var(--quantity);:
    • slider 클래스가 있는 요소의 가상 요소(::before)의 콘텐츠로
    • Quantity: 텍스트와 --quantity 변수의 값을 설정합니다. 여기서는 Quantity: 10이 됩니다.

CSS 건들여주기

잘 보일 수 있도록 빨간색으로 테두리 쳐줌

그리고 아까 html 에서 선언한 변수 사용해줌.

그리고 이미지 일렬 나열 하기 위해 flex 사용해줌.

그리고 아까 지정해 준 변수아이템에 적용시켜주기. 

그럼 이렇게 겹쳐지게 됨. 

아이템 속 이미지100% 너비 부여하기.

 

img 태그에 width: 100%를 주는 이유:

이미지가 부모 요소인 .item의 너비를 가득 채우도록 하기 위함

 

width: 100%를 설정하면 다음과 같은 효과가 있습니다:

  1. 이미지 크기 조정: 이미지가 부모 요소의 너비를 가득 채우도록 조정됩니다.
  2. 이로 인해 이미지가 부모 요소 안에서 정렬되어 깔끔하게 보입니다.
  3. 정렬 유지: 이미지가 부모 요소의 크기에 맞춰지므로, 이미지 간의 간격이 일정하게 유지되고,
  4. 슬라이더의 아이템들이 올바르게 정렬됩니다.

변수에 지정한 너비는 100px 이지만

저 이미지 너비는 100px 이 아니다.

이유: 클래스 목록의 크기가 충분치 않기 때문.

이미지 사이즈를 100px 이 되도록 맞추기.

.slider {
  width: 100%;
  border: 1px solid red;
  height: var(--height);
}
.slider .list {
  display: flex;
  width: 100%;
  min-width: calc(var(--width) * var(--quantity));
}
.slider .list .item {
  width: var(--width);
  height: var(--height);
}

.slider .list .item img {
  width: 100%;
}

.slider .list {
  display: flex;
  width: 100%;
  min-width: calc(var(--width) * var(--quantity));
}

수정하신 CSS에서 width: 100% min-width: calc(var(--width) * var(--quantity))를 추가한 것이

이미지가 부모 요소의 너비와 정확히 맞게 된 이유는 다음과 같습니다:

width: 100%는 .list 요소가 부모 요소 .slider의 너비를 가득 채우도록 설정합니다.
min-width: calc(var(--width) * var(--quantity))는 
.list 요소의 최소 너비를 각 아이템의 너비(--width)와 
아이템의 개수(--quantity)를 곱한 값으로 설정합니다. 
이 경우, --width가 100px이고 --quantity가 10이므로 최소 너비는 1000px가 됩니다.

.list 요소가 display: flex;로 설정되어 있으므로, 플렉스 컨테이너가 됩니다.
각 .item 요소는 플렉스 아이템이 되며, 지정된 너비 (--width, 즉 100px)에 맞춰 배치됩니다.
.slider .list .item img {
  width: 100%;
}
각 .item 요소의 너비가 100px로 설정되어 있으므로, 
img 요소의 width: 100%는 이미지가 
부모 요소인 .item의 너비를 가득 채우도록 합니다.

 

이 두 가지 설정을 통해 각 .item 요소 정확히 100px의 너비를 가지게 되고,

그 안의 이미지는 부모 요소의 너비를 100%로 채우게 됩니다.

따라서 이미지가 100px 너비로 정확히 맞게 됩니다.

정리

  • min-width: calc(var(--width) * var(--quantity)).list 요소최소 너비를 설정하여,
  • 전체 슬라이더의 너비가 모든 아이템을 포함할 수 있도록 합니다.
  • width: 100%는 .list 요소가 부모 요소의 너비를 가득 채우도록 설정합니다.
  • display: flex;는 .list 요소의 자식 요소들이 플렉스 컨테이너 내에서 지정된 너비대로 배치되도록 합니다.
  • width: 100%는 각 이미지가 부모 요소의 너비를 가득 채우도록 합니다.

.slider .list {
  display: flex;
  width: 100%;
  min-width: calc(var(--width) * var(--quantity));
}
list 에다가 width: 100% 준 이유 / 최소 너비 준 이유 / 아이템 개수만큼 곱해준 이유 

 

  • width: 100%:
    • .list 요소가 부모 요소인 .slider의 너비를 가득 채우도록 합니다.
    • 이 설정은 .slider가 화면 크기에 맞게 확장되었을 때 .list도 동일하게 확장되도록 보장합니다.
  • min-width: calc(var(--width) * var(--quantity)):
    • .list 요소의 최소 너비를 설정합니다. var(--width)는 각 아이템의 너비(100px),
    • var(--quantity)는 아이템의 개수(10개)를 나타냅니다.
    • 이 값을 곱하여 .list의 최소 너비를 1000px로 설정합니다.
    • 이렇게 하면 .list의 너비가 최소한 모든 아이템이 나란히 배치될 수 있는 공간을 확보하게 됩니다.

각 설정의 필요성

왜 width: 100%가 필요한가?

  • width: 100%는 .list가 부모 요소인 .slider의 너비를 가득 채우게 합니다.
  • 예를 들어, .slider가 화면 너비를 차지하게 된다면, .list도 화면 너비를 따라 확장됩니다.
  • 이렇게 하면 슬라이더가 반응형으로 동작할 수 있습니다.
  • 즉, 화면 크기가 바뀌더라도 .list의 너비가 항상 부모 요소를 채우게 됩니다.

왜 min-width: calc(var(--width) * var(--quantity))가 필요한가?

  • 최소 너비를 설정하는 이유는 플렉스 컨테이너가 자식 요소들을 한 줄에 배치하기 위해
  • 충분한 공간을 확보하기 위해서입니다.
  • var(--width) * var(--quantity)모든 아이템이 한 줄에 나란히 배치될 수 있는 최소 너비를 계산한 것입니다.
  • 예를 들어, 각 아이템의 너비가 100px이고 아이템이 10개라면,
  • 모든 아이템이 나란히 배치되려면 최소 1000px의 공간이 필요합니다.
  • 이 설정을 통해 .list는 최소한 1000px의 너비를 가지게 되며,
  • 이 너비보다 작은 경우에도 모든 아이템이 한 줄에 나란히 배치되도록 합니다.

시각적으로 설명

  1. .slider는 전체 슬라이더 컨테이너입니다.
  2. .list는 슬라이더 안의 아이템들을 포함하는 플렉스 컨테이너입니다.
  3. width: 100%는 .list가 .slider의 너비를 가득 채우도록 합니다.
  4. min-width: calc(var(--width) * var(--quantity))는
  5. .list 최소한 모든 아이템을 한 줄에 배치할 수 있는 너비를 가지도록 합니다.
    • 각 아이템의 너비가 100px이고, 10개의 아이템이 있다면 최소 1000px이 필요합니다.
    • 따라서, .list의 최소 너비는 1000px로 설정됩니다.
  6. 이 설정으로 인해 모든 아이템이 한 줄에 나란히 배치되며, 이미지도 정확히 부모 요소의 크기에 맞춰지게 됩니다.

예시로 설명

상황 설명

  • 우리는 슬라이더에 10개의 이미지(아이템)를 나란히 배치하려고 합니다.
  • 각 이미지의 너비는 100px입니다.

문제점

만약 슬라이더의 컨테이너(.list)가 아이템을 모두 수용할 만큼 충분히 넓지 않으면,

아이템들이 한 줄에 나란히 배치되지 못하고 두 줄 이상으로 나뉘거나 겹칠 수 있습니다.

최소 너비 설정의 필요성

모든 아이템이 한 줄에 나란히 배치되기 위해서는

.list의 너비가 최소한 10개의 아이템을 모두 포함할 수 있어야 합니다.

계산 과정

  • 각 아이템의 너비: 100px
  • 아이템의 개수: 10개

따라서, .list가 최소한의 너비를 가지려면:

min-width: 100px * 10 = 1000px

 

이렇게 하면, .list의 최소 너비가 1000px로 설정되어

모든 아이템이 한 줄에 나란히 배치될 수 있는 공간을 확보하게 됩니다.

시각적으로 이해하기

  1. 한 줄에 나란히 배치:
    • 아이템이 10개 있고, 각 아이템의 너비가 100px입니다.
    • 이 아이템들이 한 줄에 나란히 배치되려면 최소한 1000px의 너비가 필요합니다.
    • 만약 .list의 너비가 1000px보다 작다면, 모든 아이템이 한 줄에 들어갈 수 없게 됩니다.
  2. 최소 너비 설정:
    • min-width: 1000px으로 설정하면 .list의 너비가 1000px 이상이 되어야 합니다.
    • 따라서, 모든 아이템이 한 줄에 나란히 배치될 수 있습니다.
.slider .list {
  display: flex; /* 플렉스 컨테이너로 설정 */
  width: 100%; /* 부모 요소의 너비를 가득 채움 */
  min-width: calc(var(--width) * var(--quantity)); /* 최소 너비 설정 */
}
  • display: flex;는 아이템들을 한 줄에 나란히 배치하려고 합니다.
  • width: 100%;.list부모 요소(.slider)의 너비를 가득 채우도록 합니다.
  • min-width: calc(var(--width) * var(--quantity));최소 너비를 설정하여
  • 모든 아이템이 한 줄에 배치될 수 있도록 보장합니다.

요약

  • 아이템 개수만큼 곱해주는 이유는 모든 아이템이 한 줄에 나란히 배치될 수 있는
  • 최소한의 공간을 확보하기 위해서입니다.
  • 최소 너비를 설정하지 않으면, 아이템들이 한 줄에 들어가지 못해 레이아웃이 깨질 수 있습니다.
  • 따라서, 아이템의 개수와 각 아이템의 너비를 곱한 값을 최소 너비로 설정하여 아이템들이 한 줄에 깔끔하게 나열되도록 합니다.

.slider {
  width: 100%;
  border: 1px solid red;
  height: var(--height);
}
.slider .list {
  display: flex;
  width: 100%;
  min-width: calc(var(--width) * var(--quantity));
  position: relative;
}
.slider .list .item {
  width: var(--width);
  height: var(--height);
  position: absolute;
}

.slider .list .item img {
  width: 100%;
}

position relative 하고 

position absolute 추가

position: relative;와 position: absolute;의 역할

  1. position: relative; (부모 요소에 적용)
    • .list 요소에 position: relative;를 적용하면, 이 요소가 기준 위치가 됩니다.
    • relative 속성은 요소의 위치를 문서 흐름에 따라 배치하면서,
    • 자식 요소들이 absolute 위치를 사용할 때 기준점이 됩니다.
  2. position: absolute; (자식 요소에 적용)
    • .item 요소에 position: absolute;를 적용하면,
    • 이 요소는 일반 문서 흐름에서 벗어나 자유롭게 위치를 설정할 수 있습니다.
    • absolute 속성은 가장 가까운 relative, absolute, fixed,
    • 또는 sticky 위치 지정된 부모 요소를 기준으로 위치가 설정됩니다.

추가된 코드의 의도

1. 모든 아이템을 같은 위치에 겹치게 배치

position: absolute;를 사용하면 모든 .item 요소가 부모 요소인 .list 내에서 같은 위치에 겹치게 배치됩니다.

이렇게 하면 슬라이더의 아이템들이 겹치게 되어 특정한 위치에서

하나씩 보여주거나 애니메이션 효과를 통해 전환할 수 있습니다.

2. 슬라이더의 동작 준비

슬라이더 기능을 구현하기 위한 기초 작업으로, 아이템들을 절대 위치로 배치하여

슬라이드 애니메이션이나 전환 효과를 적용할 수 있는 기반을 마련합니다.

이를 통해 자바스크립트를 이용해 특정 시점에 하나의 아이템만 보여주거나,

슬라이드 애니메이션을 구현할 수 있습니다


position 속성을 추가하여 클래스 목록을 기준으로

슬라이더 아이템들을 쉽게 이동시킬 수 있는 방법을 다시 설명해드리겠습니다.

 

이는 슬라이더 아이템들을 절대 위치로 설정하여 겹치게 만든 후,

특정 클래스를 사용하여 어떤 아이템을 보여줄지 제어하는 방법입니다.

핵심 개념

  1. 절대 위치 (position: absolute;):
    • 모든 슬라이더 아이템을 절대 위치로 설정하여 동일한 위치에 겹치게 만듭니다.
    • 이렇게 하면 각 아이템이 동일한 위치에 쌓여서 배치됩니다.
    • 이때, 어떤 아이템을 보일지 결정하는 것이 중요합니다.
    • 이를 위해 opacity 속성과 특정 클래스를 사용합니다.
  2. 상대 위치 (position: relative;):
    • 부모 요소.listposition: relative;로 설정하여,
    • 자식 요소들이 이를 기준으로 절대 위치를 가질 수 있도록 합니다.

. 왼쪽 100% 주기.

왼쪽 100% 주기.

이미지들이 안보이게 됨.

애니메이션 item 에다가 지정해주기

left: 100%;의 효과

CSS에서 left: 100%;는 요소를 부모 요소의 왼쪽에서 100%만큼 오른쪽으로 이동시키는 것입니다.

이 경우, 부모 요소의 너비가 기준이 되므로 요소는 부모 요소의 너비만큼 오른쪽으로 이동하게 됩니다.

부모 요소의 왼쪽 기준으로 100%만큼 오른쪽으로 이동시키는 것이기 때문에,

결과적으로 요소는 부모 요소의 오른쪽 밖에 위치하게 됩니다.

left: 100%;를 추가한 이유

left: 100%;를 추가하는 이유는 애니메이션을 통해 요소들을 화면 밖에서 시작하여

화면 안으로 이동시키는 효과를 주기 위함일 수 있습니다.

즉, 슬라이더 아이템이 오른쪽에서 왼쪽으로 움직이는 애니메이션을 만들기 위한 준비 단계일 수 있습니다.


 

.slider {
  width: 100%;
  border: 1px solid red;
  height: var(--height);
}
.slider .list {
  display: flex;
  width: 100%;
  min-width: calc(var(--width) * var(--quantity));
  position: relative;
}
.slider .list .item {
  width: var(--width);
  height: var(--height);
  position: absolute;
  left: 100%;
  animation: autoRun 10s linear infinite;
}

.slider .list .item img {
  width: 100%;
}

@keyframes autoRun {
  from {
    left: 100%;
  }
  to {
    left: calc(var(--width) * -1);
  }
}

애니메이션의 목표

애니메이션의 목표는 슬라이더 아이템들이 부모 요소인 .list의 오른쪽 밖에서 출발해

왼쪽 밖으로 이동하도록 하는 것입니다.

이를 통해 슬라이더 아이템들이 화면을 가로질러 지나가는 효과를 줍니다.

애니메이션의 동작 원리

  1. from { left: 100%; }:
    • 애니메이션의 시작점입니다.
    • 각 슬라이더 아이템이 부모 요소의 오른쪽 경계 밖에 위치합니다.
    • left: 100%;는 아이템이 부모 요소의 너비만큼 오른쪽으로 이동한 위치를 의미합니다.
    • 즉, 화면에 보이지 않습니다.
  2. to { left: calc(var(--width) * -1); }:
    • 애니메이션의 끝점입니다.
    • 각 슬라이더 아이템이 부모 요소의 왼쪽 경계 밖으로 이동합니다.
    • left: calc(var(--width) * -1);는 아이템의 너비만큼 왼쪽으로 이동한 위치를 의미합니다.
    • 예를 들어, 아이템의 너비가 100px이면 left: -100px가 됩니다. 따라서 아이템은 화면에서 사라집니다.

애니메이션의 전체 흐름

  1. 시작점 (from):
    • 슬라이더 아이템은 left: 100%;에서 시작합니다.
    • 이 위치는 부모 요소의 오른쪽 경계 밖이므로, 화면에 보이지 않습니다.
  2. 끝점 (to):
    • 애니메이션이 진행됨에 따라 슬라이더 아이템은 오른쪽에서 왼쪽으로 이동합니다.
    • 끝점에서 아이템은 left: calc(var(--width) * -1);에 도달합니다.
    • 이는 아이템의 너비만큼 왼쪽으로 이동한 위치로,
    • 부모 요소의 왼쪽 경계 밖이므로 화면에서 사라집니다.
  3. 애니메이션 반복:
    • animation: autoRun 10s linear infinite;
    • 설정에 따라 애니메이션은 10초 동안 부드럽게(linear) 반복(infinite)됩니다.
    • 한 아이템이 왼쪽 경계 밖으로 사라지면 다시 오른쪽 경계 밖에서 나타나 이동을 시작합니다.

 

 

이미 item 에다가 left : 100% 를 부여했는데, 키프레임 에다가도 초기에 left:100% 를 부여한 이유

왜 두 번 설정하는가?

초기 위치 설정 (left: 100%)

  • 처음 페이지가 로드될 때 아이템을 오른쪽 화면 밖에 위치시킵니다.
  • 이를 통해 아이템이 애니메이션 없이 처음부터 화면에 보이지 않도록 합니다.

애니메이션 시작점 (from { left: 100%; })

  • 애니메이션이 시작될 때 아이템이 오른쪽 화면 밖에서 출발하게 합니다.
  • 이는 초기 위치 설정과 동일하게 맞춰 자연스럽게 애니메이션이 시작됩니다.

아이템이 처음 로드될 때와 애니메이션이 시작될 때 모두 동일한 위치에서 시작하여

자연스럽게 애니메이션이 진행됩니다.

 

요약하자면, left: 100%를 두 번 설정하는 이유는

초기 위치 설정과 애니메이션 시작점을 일치시켜

애니메이션이 부드럽고 자연스럽게 시작되도록 하기 위함입니다.


아이템 겹치지 않게 하기

애니메이션 실행시간 지정 : 10s

아이탬 개수 : 10개

 

대신 각각의 변수 이용해보기

.slider {
  width: 100%;
  border: 1px solid red;
  height: var(--height);
}
.slider .list {
  display: flex;
  width: 100%;
  min-width: calc(var(--width) * var(--quantity));
  position: relative;
}
.slider .list .item {
  width: var(--width);
  height: var(--height);
  position: absolute;
  left: 100%;
  animation: autoRun 10s linear infinite;
  animation-delay: calc((10s / var(--quantity)) * (var(--position)-1));
}

.slider .list .item img {
  width: 100%;
}

@keyframes autoRun {
  from {
    left: 100%;
  }
  to {
    left: calc(var(--width) * -1);
  }
}

다른 예시인 내가 아이템 7 개를 설정할 경우

수량도 10 에서 7 로 바꿔줌 


overflow 설정해주기 

본론으로 돌아옴.

.slider {
  width: 100%;
  border: 1px solid red;
  height: var(--height);
  overflow: hidden;
}
.slider .list {
  display: flex;
  width: 100%;
  min-width: calc(var(--width) * var(--quantity));
  position: relative;
}
.slider .list .item {
  width: var(--width);
  height: var(--height);
  position: absolute;
  left: 100%;
  animation: autoRun 10s linear infinite;
  animation-delay: calc((10s / var(--quantity)) * (var(--position) - 1));
}

.slider .list .item img {
  width: 100%;
}

@keyframes autoRun {
  from {
    left: 100%;
  }
  to {
    left: calc(var(--width) * -1);
  }
}

 

728x90