GODRICH

CSS 배경 애니메이션 9종 — 한 줄 복붙으로

CSS 배경 애니메이션은 히어로 섹션이나 카드 뒤에서 이미지 파일 없이 그라데이션·격자·점·노이즈 같은 패턴을 계속 움직이게 만드는 기법입니다. 아홉 개를 모았는데, 그중 하나는 커서를 따라가는 스포트라이트라 마우스가 없는 이 격자 안에서는 궤도를 자동으로 돕니다.

자동 재생 · 눌러서 해당 항목으로 · 전부 한 zip

아홉 개는 화려한 순서가 아니라 배경이 무대에서 맡는 역할 순서로 놓았습니다. 색 자체가 주인공인 것(01~03), 구조를 그려 보여주는 것(04), 형태가 계속 바뀌는 것(05), 질감을 더하는 것(06~07), 방향성을 주는 것(08), 마지막으로 사용자 입력에 반응하는 것(09)입니다. 전부 background-size를 실제보다 키우거나 요소를 작게 잘라 transform·opacity·background-position만 움직이며, border-radiuswidth를 프레임마다 다시 계산하지 않습니다. 항목마다 코드는 핵심 조각만 실었고, 전체 파일은 zip에 있습니다.

01그라디언트 흐름

배경을 화면보다 두 배 크게 깔고 background-position만 오가게 하면 정지된 그라디언트가 물 흐르듯 움직입니다. 별도 요소 없이 무대 배경 자체가 피사체입니다.

background-position200% 200%ease-in-out
.stage::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: linear-gradient(120deg, $stage-ink, $color, $subject-cream, $stage-ink);
  background-size: 220% 220%;
  animation: flow $duration $easing infinite;
}
@keyframes flow {
  0%   { background-position: 0% 50%; }
  50%  { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}

02메시 그라디언트 드리프트

색이 다른 radial-gradient 얼룩 세 개를 겹치고 각자 다른 시작 지연으로 transform: translate를 돌리면, 얼룩들이 서로 교차하며 유기적으로 섞이는 메시 그라디언트가 됩니다. 최근 SaaS 랜딩에서 자주 보이는 배경입니다.

radial-gradient 레이어transform: translate비동기 주기
.blob { position: absolute; width: 42%; aspect-ratio: 1; border-radius: 50%; filter: blur(12px); opacity: .9; }
.b1 { background: radial-gradient($color, transparent 65%); animation: drift1 $duration $easing infinite; }
.b2 { background: radial-gradient($subject-cream, transparent 65%); animation: drift2 $duration $easing infinite; animation-delay: -.6s; }
.b3 { background: radial-gradient($stage-ink, transparent 65%); opacity: .65; animation: drift3 $duration $easing infinite; animation-delay: -1.2s; }
@keyframes drift1 { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(48px, 32px); } }
@keyframes drift2 { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(-42px, -26px); } }
@keyframes drift3 { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(24px, -38px); } }

03오로라 블러

filter: blur로 흐린 색 덩어리 두세 개를 반투명하게 겹치고 transform(이동·회전)으로만 돌리면 오로라가 겹쳐 흐르는 듯한 배경이 됩니다. 다크 모드 히어로에 자주 쓰입니다.

filter: blur반투명 레이어transform 회전
.aurora { position: absolute; width: 38%; aspect-ratio: 1; border-radius: 50%; filter: blur(3px); }
.a1 { background: radial-gradient($subject-cream 0%, $subject-cream 25%, transparent 55%);
      animation: spin1 $duration linear infinite; }
@keyframes spin1 {
  0%   { transform: translate(0, 0) rotate(0deg); }
  50%  { transform: translate(56px, 38px) rotate(180deg); }
  100% { transform: translate(0, 0) rotate(360deg); }
}

04움직이는 격자

가로선·세로선 linear-gradient 두 개를 한 배경에 겹쳐 격자를 그리고 background-position을 x·y 같은 값으로 함께 옮기면, 격자가 대각선으로 끝없이 흐르는 것처럼 보입니다. 기술 문서나 대시보드 배경에 씁니다.

repeating-linear-gradientbackground-position대각선 이동
.stage::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(to right, rgba($color, .35) 1px, transparent 1px),
    linear-gradient(to bottom, rgba($color, .35) 1px, transparent 1px);
  background-size: 32px 32px, 32px 32px;
  animation: gridmove $duration linear infinite;
}
@keyframes gridmove {
  from { background-position: 0 0, 0 0; }
  to   { background-position: 32px 32px, 32px 32px; }
}

05블롭 모핑

모양이 다른 블롭 세 개를 겹쳐 놓고 opacitytransform(scale·rotate)만 번갈아 움직이면, border-radius를 매 프레임 다시 계산하지 않고도 하나의 덩어리가 계속 모양을 바꾸는 것처럼 보입니다.

레이어 크로스페이드transform: scale·rotateopacity
.blob { position: absolute; width: 52%; aspect-ratio: 1; background: $color; }
.m1 { border-radius: 42% 58% 63% 37% / 41% 44% 56% 59%; animation: morph1 $duration $easing infinite; }
.m2 { border-radius: 63% 37% 41% 59% / 55% 48% 52% 45%; opacity: 0; animation: morph2 $duration $easing infinite; }
@keyframes morph1 {
  0%   { opacity: 1; transform: scale(1) rotate(0deg); }
  38%  { opacity: 0; transform: scale(.94) rotate(8deg); }
  100% { opacity: 1; transform: scale(1) rotate(0deg); }
}

06노이즈 그레인

아주 작은(3px) repeating-conic-gradient 타일을 반복시키고 background-positionsteps(40) 이징으로 매 프레임 건너뛰면, 부드러운 보간 없이 필름 그레인처럼 지글거립니다. 프리미엄 카드 배경의 질감으로 씁니다.

repeating-conic-gradientsteps()background-position
.stage::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: repeating-conic-gradient(from 0deg, rgba($color, .55) 0deg 90deg, transparent 90deg 180deg);
  background-size: 3px 3px;
  opacity: .35;
  animation: grain $duration steps(40) infinite;
}
@keyframes grain {
  from { background-position: 0 0; }
  to   { background-position: 117px 69px; }
}

07도트 패턴 흐름

radial-gradient로 찍은 작은 점을 20px 간격으로 타일링하고 background-position을 대각선으로 천천히 옮기면, 점들이 끊김 없이 흐르는 것처럼 보입니다. 슬라이드나 카드 그리드 뒷배경에 어울립니다.

radial-gradient 도트background-size 타일대각선 흐름
.stage::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(circle, rgba($color, .6) 1.5px, transparent 1.5px);
  background-size: 20px 20px;
  animation: dotdrift $duration linear infinite;
}
@keyframes dotdrift {
  from { background-position: 0 0; }
  to   { background-position: 20px 20px; }
}

08사선 스트라이프 이동

repeating-linear-gradient(90deg, 색 0 18px, transparent 18px 36px)로 세로 줄무늬를 그린 뒤 레이어 전체를 transform: rotate(45deg)로 기울이고, background-position은 회전 전 좌표계에서 가로로만 옮기면 대각선 줄무늬가 행진하듯 흐릅니다. 세일 배너에 흔한 패턴입니다.

repeating-linear-gradient45degbackground-position
.stage::before {
  content: "";
  position: absolute;
  inset: -150% -150%;
  transform: rotate(45deg);
  background-image: repeating-linear-gradient(90deg, rgba($color, .18) 0 18px, transparent 18px 36px);
  animation: stripemove $duration linear infinite;
}
@keyframes stripemove {
  from { background-position: 0 0; }
  to   { background-position: 36px 0; }
}

09커서 스포트라이트 배경

블러 처리한 작은 원 하나가 transform: translate로 궤도를 그리며 움직이는 스포트라이트입니다. 이 격자 안에서는 자동으로 돌지만, 실제 페이지에서는 같은 좌표를 pointermove에서 받아 커서를 따라갑니다.

radial-gradient 스포트라이트transform: translatepointermove 대응
if (matchMedia('(pointer: fine)').matches) {
  var stage = document.querySelector('.stage');
  var spot = document.querySelector('.spot');
  stage.addEventListener('pointermove', function (e) {
    var r = stage.getBoundingClientRect();
    spot.classList.remove('is-demo');
    spot.style.transform = 'translate(' + (e.clientX - r.left - r.width / 2) + 'px,' +
      (e.clientY - r.top - r.height / 2) + 'px)';
  });
}

어디서 깨지는가 — 함정 하나

09를 제외한 여덟 개가 전부 transform·opacity·background-position만 움직이는 데는 이유가 있습니다. 배경은 화면의 넓은 면적을 차지하기 때문에, widthborder-radius를 매 프레임 다시 계산하면 브라우저가 그 넓은 영역을 통째로 다시 그려야 합니다. MDN의 애니메이션 성능 문서가 합성 단계에서 처리되는 속성만 권하는 이유입니다. 08 사선 스트라이프를 처음 만들 때 background-position을 대각선(x·y 같은 값)으로 옮겼더니 화면이 한 프레임도 안 바뀌었습니다 — 45도로 이미 기울인 무늬 위에서 대각선 이동은 줄무늬와 나란한 방향이라 이동 자체가 눈에 보이지 않았던 겁니다. 세로로 그린 다음 레이어를 통째로 회전시키는 순서로 바꾸니 해결됐습니다.

함정은 아니지만 덧붙일 것이 하나 더 있습니다. 이 아홉 개 파일을 압축한 zip의 비밀번호는 bc82wnvk이고, 그 안에는 이번에 걸린 수치까지 정리해 뒀습니다. 실제로 04 격자와 08 스트라이프는 배경 전체가 매 프레임 바뀌어 화면의 99% 이상이 움직였고, 02 메시 그라데이션은 얼룩이 덜 겹치는 프레임이 많아 절반 정도만 바뀌었습니다. 뒤 값이 낮다고 이상한 건 아니고, 애초에 그 정도만 움직이도록 설계한 겁니다.

접근성

운영체제의 "동작 줄이기" 설정을 켜 둔 사람에게는 아홉 개 배경 모두 prefers-reduced-motion: reduce 조건에서 다르게 반응합니다. 배경은 장식이라 움직임만 끄고 색이나 패턴 자체는 마지막 프레임으로 고정해 화면이 비어 보이지 않게 합니다. 05 블롭 모핑은 첫 번째 모양만 남기고 나머지 두 겹은 투명 상태로 고정하며, 09 스포트라이트는 궤도 시작 지점에서 멈춥니다. 이 값을 브라우저마다 어떻게 읽는지는 MDN의 prefers-reduced-motion 문서에 정리돼 있습니다.

@media (prefers-reduced-motion: reduce) {
  .stage::before,
  .blob,
  .aurora,
  .spot.is-demo { animation: none; }
}

배경이 넓은 면적을 덮는 만큼 그 위에 얹는 글자의 대비도 함께 봐야 합니다. 09처럼 스포트라이트가 밝기를 바꾸는 배경이라면 텍스트 색을 스포트라이트 색과 별개로 고정해 대비가 흔들리지 않게 해야 합니다.

배경 말고 버튼·드롭다운처럼 화면 앞쪽이 움직이는 사례는 CSS 애니메이션 모음에서 골라볼 수 있고, 이 사이트가 어떤 기준으로 데모를 고르는지는 소개 페이지에 적어 뒀습니다.

FAQ

CSS 배경 애니메이션이 페이지 성능에 부담을 주나요?

transform·opacity·background-position만 쓰면 합성 단계에서 처리되어 부담이 크지 않습니다. 다만 배경은 화면 전체를 덮는 경우가 많아 filter: blur를 스테이지 전체에 걸면 다른 항목보다 비용이 커집니다. 그래서 02·03처럼 블러가 필요한 항목은 작은 요소 몇 개에만 걸고 무대 전체엔 걸지 않았습니다.

09 스포트라이트가 이 페이지에서는 왜 자동으로 도나요?

격자 안 데모는 마우스를 올리지 않아도 움직여야 렌더·측정이 가능해서 .is-demo 클래스로 자동 궤도를 강제했습니다. zip을 받아 실제 페이지에 붙이면 pointer: fine 기기에서 pointermove 좌표가 그 자리를 대신해 스포트라이트가 커서를 따라갑니다.

아홉 개를 한 페이지에 다 써도 되나요?

기술적으로는 가능하지만 한 화면에는 하나만 쓰는 걸 권합니다. 배경 두 개가 동시에 움직이면 어느 쪽이 신호인지 알 수 없고, 그 위에 얹은 글자도 읽기 어려워집니다. 06 노이즈 그레인처럼 질감을 더하는 것과 01 그라디언트 흐름처럼 색 자체가 주인공인 것을 같이 쓰는 조합도 피하는 게 좋습니다.

압축 비밀번호를 입력하세요

비밀번호는 이 글 본문 안에 있습니다. 읽다 보면 나옵니다.