본문 바로가기

UI 디자인 애니메이션 연구소

어디가 끝이지? 끝없이 흘러가는 마키 UI 애니메이션

반응형

이전 애니메이션 | 스크롤링 헤드라인

 

스크롤링 헤드라인 이라 불리는 뉴스티커 UI, 원리부터 구현 까지

이전 애니메이션 HTML, CSS 로 불타는 입력창(Input) 만들기미리보기해당 포스트를 따라오시면, 아래와 같은 애니메이션을 구현하실 수 있게 됩니다. HTMLHTML 구조는 별게 없습니다. label 의 경우 인

duklook.tistory.com


결과물 미리보기

단지 HTML 과 CSS 몇 스푼만 던져주면 구현해볼 수 있는 마키 UI, 같이 구현해 봅시다.

여러 줄기로 꼬아보았는데, 실제 결과물은 2개 로 줄었습니다.

 

 


이번에 구현해볼 친구는?

오늘 인프런의 INFCON 을 소개하는 렌딩 페이지에서 아래와 같이 무한으로 흐르는 UI 를 볼 수 있었습니다. 왠지 구현해보면 재밌을 것 같아서, 이 친구가 동작하는 원리를 파악하고 직접 구현해보는 시간을 가져볼까 합니다.

마키 혹은 무한 스크롤 텍스트라 불리는 이 친구

컴베이어 벨트 처럼 무한으로 동작하는 이 친구는 마키 혹은 무한 스크롤 텍스트 라고 불리는 UI 입니다. 해당 UI 가 사용되는 목적은 보통 사용자들의 이목을 집중 시켜 중요한 정보를 지속적으로 표시하기 위해서 사용되는데요. 인프런에서도 인프콘 행사가 열리는 날짜를 부각시키기 위해서 #0078a7 계열의 색상을 사용하여 구현한 것을 볼 수 있습니다.

 

 

시작 전에 살펴보는 동작 원리

 

파란색 막대기는 각 콘텐츠 내용을 담고 있는 요소(.marquee) 입니다. 이 요소를 4개 묶어서 감싸고 있는 요소가 .container 요소가 되구요.

 

해당 컨테이너의 초기 위치는 마키 요소 2개 사용자의 화면에 보이게 됩니다. @keyframe 을 통해서 우측 좌측(0% -> -200%) 으로 움직이게 되는데, 초기의 마키 요소 2개가 아닌 숨겨져 있던 마키 요소 2개가 보이는 시점이 translate(-200%) 이 되는 지점 입니다. 즉, 해당 위치가 되면, 애니메이션이 종료되고, 다시 초기 위치로 리셋됩니다.

 

이를 계속 반복되면 사용자는 끊임없이 반복되는 UI 를 볼 수 있게 되는 겁니다. 

 

HTML

아래와 같은 구조가 되도록 마크업을 작성해줍니다. 텍스트는 여러분이 원하는 것으로 바꾸셔도 됩니다. 뭐든 여러 방식을 시도해 봅시다. 참고로 style="--deg:30" 과 같이 되어 있는 것은 css 변수를 추가한 것입니다. 이는 나중에 var(--deg) 형식으로 사용할 수 있습니다. 

<div class="container" style="--deg:15">
  <div class="marquee">
    <span>코딩라이프 </span>
    <span>2024.06.29 </span>
    <span>커밍순!!! </span>
  </div>
  <div class="marquee">
    <span>코딩라이프 </span>
    <span>2024.06.29 </span>
    <span>커밍순!!! </span>
  </div>
  <div class="marquee">
    <span>코딩라이프 </span>
    <span>2024.06.29 </span>
    <span>커밍순!!! </span>
  </div>
  <div class="marquee">
    <span>코딩라이프 </span>
    <span>2024.06.29 </span>
    <span>커밍순!!! </span>
  </div>
</div>

<div class="container" style="--deg:-15">
  <div class="marquee">
    <span>코딩라이프 </span>
    <span>2024.06.29 </span>
    <span>커밍순!!! </span>
  </div>
  <div class="marquee">
    <span>코딩라이프 </span>
    <span>2024.06.29 </span>
    <span>커밍순!!! </span>
  </div>
  <div class="marquee">
    <span>코딩라이프 </span>
    <span>2024.06.29 </span>
    <span>커밍순!!! </span>
  </div>
  <div class="marquee">
    <span>코딩라이프 </span>
    <span>2024.06.29 </span>
    <span>커밍순!!! </span>
  </div>
</div>

 

CSS

다음은 CSS 입니다. 큰 틀만 보면 컨테이너 요소와 그 컨테이너 요소 내부에 있는 각 콘텐츠 요소들 그리고 이들을 움직이는 키프레임을 설정하는 것이 전부입니다.

전체 코드(주석 설명)

각 요소에 지정된 속성들의 역할은 주석으로 설명을 적어두었습니다. 이 중 몇 개의 중요한 설정만 따로 뽑아서 부연 설명 형식으로 언급 하겠습니다.

@font-face {
  font-family: "양진체";
  src: url("https://fastly.jsdelivr.net/gh/supernovice-lab/font@0.9/yangjin.woff")
    format("woff");
  font-weight: normal;
  font-style: normal;
}

/* 브라우저에 적용된 기본 여백을 제거하고, 콘텐츠 영역을 계산시 여백을 포함하도록 해줍니다. */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* body 태그가 차지하는 영역을 뷰포트 100%에 맞추도록 해주고, 자식요소가 body 태그 바깥을
 나가더라도 스크롤바가 생기지 않도록 해줍니다.
*/
body {
  width: 100%;
  height: 100vh;
  background: #333;
  overflow: hidden; /* 스크롤 바 생성 방지 */
}

/* .marquee 를 감싸고 있는 컨테이너 요소: 마키UI의 최대 높이를 설정하고, 각 UI 를 가로 정렬합니다.  */
.container {
  --rotate: calc(var(--deg) * 1deg); /* --deg:30 인 경우 1deg * 30 = 30deg 가 됩니다.  */
  display: flex;
  border: 1px solid black;
  margin-top: 10rem;
  height: 105px;
  transform: rotate(var(--rotate));
}

/* 컨테이너 요소를 마우스 호버 하면 모든 marquee 에 적용된 애니메이션 적용을 중지합니다. */
.container:hover {
  .marquee {
    animation-play-state: paused;
  }
}

/* marquee 내부에 구성하고 있는 모든 span 요소들을 가로로 정렬합니다. */
.marquee {
  box-shadow: 0 20px 0 rgba(0, 0, 0, 0.9);
  padding: 15px 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: white;
  width: 100%;
  transform: translateX(0%);
  animation: marquee 10s linear infinite; /* 10초 동안 진행되는 애니메이션을 일정한 간격으로 무한반복 */
  
  /* 마키 내부에 나열된 콘텐츠 내용입니다.*/
  span {
    font-family: "양진체";
    text-align: center;
    font-size: 2.7em;
    padding: 10px;
    width: 300px;
    display: inline-block; /* 인라인 태그를 block 속성 적용이 가능한 인라인 태그로 변경*/
  }
}

/* 애니메이션을 적용합니다.*/
@keyframes marquee {
  0% {
    transform: translateX(0%);
  }
  100% {
    transform: translateX(-200%);
  }
}

 

부연 설명 | .container 요소의 calc 와 var,  변수

여기서 일부만 뜯어보겠습니다. 앞서 .container 요소를 보면 아래와 같이 --rotate 변수를 선언하여 calc(var(--deg) * 1deg) 라는 값을 할당해준 것을 볼 수 있습니다. 그리고 이를 transform:rotate(var(--rotate)) 와 같이 전달하여 각각의 마키 UI에 각도 변화를 주고 있습니다. 

 

이는 앞서 HTML 을 작성하는 과정 중 container 요소의 style 태그에 --deg:30, --deg:60 ,... 등과 같이 전달해 주는 부분하고 연결 됩니다. 즉, --deg:30과 --deg:60 에서 지정한 30과 60이라는 값이 CSS 내에서 --deg 내에 들어간다고 보시면 됩니다.

 

calc 는 CSS 에서 수학적인 처리를 하는 함수로서 즉, 계산기 같은 친구(이름 철자 부터도 계산기)입니다. --deg 로 전달된 값과 1deg 를 곱해주면 예시로 따지면 30deg, 60deg 가 각각 반환되는데, 이는 각 .container  클래스가 부여된 요소의 각도를  변경해주는데 사용되고 있습니다. 즉, --rotate: calc(var(--deg * 1deg)) 는 --rotate:calc(30 * 1deg) 가 되고, 이는 다시 --rotate:30deg 가 되어  transform:rotate(--rotate) 에 전달됩니다. 다시 말해, transform:rotate(30deg) 이 결과로 남게 됩니다.

 

결론적으로 transform:rotate(var(--rotate)); 에서는 var(--rotate) 의 자리에 30deg, 60deg 가 남게 되고, 이를 roate 함수가 처리하여 각도의 변환을 아래 이미지와 같이 주고 있다고 정리할 수 있습니다.

.container 요소에 15deg, 60deg, 30deg 가 rotate 속성에 적용된 모습

 

 

구현 결과

전체 코드를 시연하면 아래와 같습니다. 고생하셨습니다.

 

See the Pen Untitled by youngwan2 (@youngwan2) on CodePen.

반응형