본문 바로가기
기술의기록

CSS만으로 텍스트 로딩 애니메이션 만들기 - @property로 그라디언트 마법 부리기

by Jeremy Winchester 2025. 9. 25.
반응형

웹사이트에서 사용자의 시선을 사로잡는 텍스트 로딩 애니메이션을 본 적이 있으신가요? 색깔이 왼쪽에서 오른쪽으로 천천히 채워지면서 글자가 살아나는 그 멋진 효과 말이에요.

예전에는 복잡한 자바스크립트 없이는 불가능하다고 여겨졌던 이런 애니메이션이, 이제는 순수 CSS만으로도 완벽하게 구현할 수 있게 되었습니다! 바로 CSS의 새로운 기능인 @property를 활용하면 되거든요. 😊

오늘은 이 혁신적인 기술을 사용해서 자바스크립트 없이 텍스트 채우기 애니메이션을 만드는 방법을 단계별로 알아보겠습니다.

🤔 왜 기존 방법은 작동하지 않을까?

먼저 많은 분들이 시도해보셨을 일반적인 방법을 살펴보겠습니다.

.loading-text {
   background: linear-gradient(90deg, yellow 0%, grey 0%);
   color: transparent;
   background-clip: text;
}

@keyframes fill-text {
   to {
      background: linear-gradient(90deg, yellow 100%, grey 100%);
   }
}

언뜻 보면 완벽한 것 같지만, 실제로 실행해보면 애니메이션이 전혀 작동하지 않습니다. 왜 그럴까요?

핵심 문제: CSS는 그라디언트를 직접 애니메이션할 수 없습니다. 브라우저가 linear-gradient(90deg, yellow 0%, grey 0%)에서 linear-gradient(90deg, yellow 100%, grey 100%)로의 변화를 어떻게 처리해야 하는지 모르기 때문이에요.

🚀 @property가 가져온 혁신

그런데 이제 상황이 완전히 바뀌었습니다! CSS @property 규칙이 모든 주요 브라우저에서 지원되면서(2024년 7월부터 Baseline 지원), 이전에는 불가능했던 애니메이션들이 가능해졌거든요.

@property란 무엇인가요?

@property는 CSS 커스텀 프로퍼티(CSS 변수)에 타입을 부여할 수 있게 해주는 기능입니다. 쉽게 말해, 브라우저에게 "이 변수는 퍼센트 값이야"라고 알려주는 거죠.

@property --loading-percent {
   syntax: "<percentage>";
   inherits: false;
   initial-value: 0%;
}

이렇게 정의하면 브라우저는 --loading-percent 변수를 퍼센트 값으로 인식하고, 이 값의 변화를 부드럽게 애니메이션할 수 있게 됩니다.

✨ 완벽한 텍스트 채우기 애니메이션 만들기

이제 실제로 작동하는 코드를 만들어보겠습니다!

1단계: HTML 구조 만들기

<div class="container">
  <h1 class="loading-text">로딩중입니다...</h1>
</div>

2단계: @property로 커스텀 변수 등록하기

@property --loading-percent {
   syntax: "<percentage>";
   inherits: false;
   initial-value: 0%;
}

이 코드의 의미를 하나씩 살펴보면:

  • syntax: "<percentage>": 이 변수는 퍼센트 값이라고 정의
  • inherits: false: 자식 요소가 이 값을 상속받지 않음
  • initial-value: 0%: 초기값은 0%로 설정

3단계: 텍스트 스타일링과 그라디언트 적용

.loading-text {
   font-size: 3rem;
   font-weight: bold;
   background: linear-gradient(
      90deg, 
      #ff6b6b var(--loading-percent), 
      #666666 var(--loading-percent)
   );
   background-clip: text;
   -webkit-background-clip: text;
   color: transparent;
   animation: fill-text 3s ease-in-out infinite;
}

여기서 핵심은 고정된 퍼센트 값 대신 var(--loading-percent) 변수를 사용한 것입니다!

4단계: 애니메이션 키프레임 정의

@keyframes fill-text {
   from {
      --loading-percent: 0%;
   }
   to {
      --loading-percent: 100%;
   }
}

이제 그라디언트의 위치값 자체를 애니메이션하는 게 아니라, 커스텀 프로퍼티의 값을 애니메이션합니다.

🎭 다양한 효과 응용하기

무지개 그라디언트 로딩

@property --rainbow-progress {
   syntax: "<percentage>";
   inherits: false;
   initial-value: 0%;
}

.rainbow-text {
   background: linear-gradient(
      90deg,
      #ff0080 var(--rainbow-progress),
      #ff8c00 var(--rainbow-progress),
      #40e0d0 var(--rainbow-progress),
      #999999 var(--rainbow-progress)
   );
   background-clip: text;
   -webkit-background-clip: text;
   color: transparent;
   animation: rainbow-fill 2s ease-out forwards;
}

@keyframes rainbow-fill {
   to { --rainbow-progress: 100%; }
}

펄스 효과가 있는 로딩

@property --pulse-progress {
   syntax: "<percentage>";
   inherits: false;
   initial-value: 0%;
}

.pulse-text {
   background: linear-gradient(
      90deg,
      #4facfe var(--pulse-progress),
      rgba(79, 172, 254, 0.3) var(--pulse-progress)
   );
   background-clip: text;
   -webkit-background-clip: text;
   color: transparent;
   animation: pulse-fill 2s ease-in-out infinite alternate;
}

@keyframes pulse-fill {
   0% { --pulse-progress: 0%; }
   100% { --pulse-progress: 100%; }
}

🌟 실전 활용 팁

성능 최적화

애니메이션 성능을 위해 다음 속성들을 추가해보세요:

.loading-text {
   /* 기존 스타일... */
   will-change: background-position;
   transform: translateZ(0); /* 하드웨어 가속 활성화 */
}

접근성 고려하기

사용자의 모션 설정을 존중하는 것도 중요합니다:

@media (prefers-reduced-motion: reduce) {
   .loading-text {
      animation: none;
   }
}

반응형 디자인

다양한 화면 크기에 대응하기:

.loading-text {
   font-size: clamp(1.5rem, 5vw, 3rem);
   text-align: center;
   padding: 1rem;
}

@media (max-width: 768px) {
   .loading-text {
      font-size: 2rem;
   }
}

🔧 브라우저 호환성과 폴백

@property는 현재 93% 이상의 브라우저에서 지원되지만, 구형 브라우저를 위한 폴백도 준비해두는 것이 좋습니다:

/* 폴백용 기본 애니메이션 */
@keyframes fallback-blink {
   0%, 50% { opacity: 0.5; }
   51%, 100% { opacity: 1; }
}

.loading-text {
   /* @property를 지원하지 않는 브라우저용 */
   animation: fallback-blink 1s infinite;
}

/* @property를 지원하는 브라우저에서만 적용 */
@supports (background: linear-gradient(90deg, red var(--test, 0%))) {
   .loading-text {
      animation: fill-text 3s ease-in-out infinite;
   }
}

💡 추가 응용 아이디어

1. 글자별 지연 효과

.word {
   display: inline-block;
   animation-delay: calc(var(--index) * 0.1s);
}

2. 타이핑 효과와 결합

@property --typing-progress {
   syntax: "<percentage>";
   inherits: false;
   initial-value: 0%;
}

.typing-fill {
   background: linear-gradient(90deg, 
      #2196f3 var(--typing-progress), 
      transparent var(--typing-progress)
   );
   background-clip: text;
   -webkit-background-clip: text;
   color: transparent;
   animation: type-and-fill 4s steps(20) forwards;
}

3. 스크롤 기반 애니메이션

CSS Scroll-Driven Animations와 함께 사용하면 스크롤에 따라 텍스트가 채워지는 효과도 가능합니다:

.scroll-fill {
   animation: fill-on-scroll auto linear;
   animation-timeline: scroll(root);
   animation-range: entry 0% cover 100%;
}

🎨 디자인 시스템에 적용하기

이런 애니메이션을 디자인 시스템에 체계적으로 적용하려면:

/* 기본 애니메이션 변수들 */
@property --fill-primary { syntax: "<percentage>"; inherits: false; initial-value: 0%; }
@property --fill-secondary { syntax: "<percentage>"; inherits: false; initial-value: 0%; }
@property --fill-accent { syntax: "<percentage>"; inherits: false; initial-value: 0%; }

/* 유틸리티 클래스들 */
.text-fill-primary {
   background: linear-gradient(90deg, var(--color-primary) var(--fill-primary), var(--color-neutral) var(--fill-primary));
   background-clip: text;
   -webkit-background-clip: text;
   color: transparent;
}

.animate-fill-slow { animation: fill-text 3s ease-in-out; }
.animate-fill-fast { animation: fill-text 1s ease-in-out; }
.animate-fill-infinite { animation: fill-text 2s ease-in-out infinite; }

🚦 주의사항과 베스트 프랙티스

성능 고려사항

  • 과도한 애니메이션 지양: 한 페이지에 너무 많은 텍스트 애니메이션이 있으면 성능에 영향을 줄 수 있습니다
  • 적절한 duration 설정: 너무 빠르거나 느린 애니메이션은 사용자 경험을 해칠 수 있어요
  • 필요할 때만 실행: will-change 속성을 적절히 활용하되, 애니메이션이 끝나면 제거하세요

접근성 준수

/* 움직임을 선호하지 않는 사용자를 위한 설정 */
@media (prefers-reduced-motion: reduce) {
   * {
      animation-duration: 0.01s !important;
      animation-iteration-count: 1 !important;
   }
}

🎯 마무리

CSS @property를 활용한 텍스트 채우기 애니메이션은 정말 혁신적인 기술입니다. 자바스크립트 없이도 이렇게 멋진 효과를 만들 수 있다니, 웹 개발의 미래가 정말 밝아 보이네요! ✨

이 기술을 활용하면:

  • 더 나은 성능: JavaScript보다 CSS 애니메이션이 더 부드럽고 효율적
  • 간단한 구현: 복잡한 스크립트 없이도 고급 효과 구현 가능
  • 미래 지향적: 모든 주요 브라우저에서 지원되는 표준 기술

 

반응형