GODRICH
#css애니메이션#버튼#로딩#전환효과#스크롤#대시보드#실전ui#디자인트렌드

CSS 텍스트 강조 애니메이션 9종 — 한 줄 복붙으로

CSS 텍스트 강조 애니메이션은 본문 속 한 단어나 문장에 형광펜·밑줄·취소선 같은 시각 효과를 얹어 읽는 사람의 시선을 그 자리에 멈추게 하는 기법입니다. 아홉 가지를 모았고, 전부 자바스크립트 없이 순수 CSS keyframes만으로 자동 반복됩니다.

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

아홉 개는 인기 순이 아니라 문장에서 강조가 필요한 상황 순서로 놓았습니다. 문서 속 핵심 문구를 칠하고(01~03), 경고나 완료를 표시하고(04~05), 링크와 안내선으로 이끌고(06~07), 마지막으로 배지와 숫자를 튀게 합니다(08~09). 항목마다 코드는 핵심만 실었고 전체 파일은 zip에 있습니다. 같은 강조를 유틸리티 클래스 쪽으로 옮기는 변환은 Tailwind 애니메이션 유틸이 보여 주고, 칭찬이 아니라 오류를 알리는 움직임이 필요할 땐 흔들리는 애니메이션이 같은 발상의 반대편입니다.

01형광펜 강조

형광펜 블록을 겹치는 순서

키워드 뒤에 노란 블록을 겹치고 왼쪽부터 차오르게 칠합니다. 여기에 같은 색의 노이즈 레이어를 위아래 지그재그로 한 겹 더 겹쳐 펜 두께가 구석마다 불규칙하게 출렁이는 스트로크로 보이게 했습니다.

형광펜 강조
새 창에서 열기

01 · 형광펜 강조 — 측정 누적면적 1.458% · 움직인 프레임 22/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

transform:scaleXmix-blend-mode2s

약관 속 핵심 문구에

약관이나 안내문에서 꼭 봐야 할 문구를 가리킬 때 씁니다.

.hl {
  position: relative;
  isolation: isolate;
  &::before {
    content: ""; position: absolute; inset: 12% -2% 6%;
    background: $color; border-radius: $r-xs;
    transform: scaleX(0); transform-origin: left center;
    mix-blend-mode: multiply; z-index: -1;
    animation: mark $duration $easing infinite;
  }
}
@keyframes mark {
  0%   { transform: scaleX(0); }
  20%  { transform: scaleX(1); }
  75%  { transform: scaleX(1); }
  100% { transform: scaleX(0); }
}

02마커 겹침

두 겹을 어긋나게 칠하기

같은 형광펜 블록을 두 겹 겹치되 서로 다른 각도와 타이밍으로 칠해 손으로 두 번 그은 듯한 두께를 만듭니다. 각 겹의 위아래 두께가 서로 다른 위상으로 요동쳐 겹침 가장자리가 죽지 않고 계속 살아 움직입니다.

마커 겹침
새 창에서 열기

02 · 마커 겹침 — 측정 누적면적 1.945% · 움직인 프레임 14/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

::before·::afterrotate + scaleX지연 0/.3s

가장 중요한 한 단어에

페이지에서 가장 중요한 한 단어에 씁니다.

.hl {
  position: relative;
  isolation: isolate;
}
.hl::before, .hl::after {
  content: ""; position: absolute; inset: 10% -2% 4%;
  transform: scaleX(0); transform-origin: left center;
  mix-blend-mode: multiply; z-index: -1;
}
.hl::before { background: $stage-yellow; rotate: -1.2deg; animation: mark $duration $easing infinite; }
.hl::after  { background: $color; opacity: .55; rotate: 1deg; animation: mark $duration $easing infinite .3s; }

03손글씨 밑줄

css 밑줄 애니메이션을 손으로 그은 것처럼

인라인 SVG 곡선 한 줄을 stroke-dashoffset으로 왼쪽부터 그려 손으로 방금 그은 밑줄처럼 보이게 합니다. 그어지는 동안 stroke-width가 3px와 4.5px 사이를 오가며 펜 압력처럼 굵어졌다 얇아집니다.

손글씨 밑줄
새 창에서 열기

03 · 손글씨 밑줄 — 측정 누적면적 0.301% · 움직인 프레임 21/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

SVG pathstroke-dashoffset600ms

인용구의 강조어에

인용구나 자기소개의 강조어에 씁니다.

.hl__path {
  fill: none; stroke: $color; stroke-width: 3; stroke-linecap: round;
  stroke-dasharray: 140; stroke-dashoffset: 140;
  animation: draw $duration $easing infinite;
}
@keyframes draw {
  0%   { stroke-dashoffset: 140; }
  35%  { stroke-dashoffset: 0; }
  80%  { stroke-dashoffset: 0; }
  100% { stroke-dashoffset: -140; }
}

04물결 밑줄

네이티브 물결선에 무엇을 더하나

네이티브 물결 밑줄에 text-underline-offset만 애니메이션해 경고 문구가 숨 쉬듯 움직이게 합니다. 물결이 오가는 사이사이 굵기도 2px에서 3px대로 흔들어 선 전체가 붓으로 누른 것처럼 불균일합니다.

물결 밑줄
새 창에서 열기

04 · 물결 밑줄 — 측정 누적면적 0.284% · 움직인 프레임 23/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

text-decoration-style:wavy@property <length>1s

필수 입력 표시에

필수 입력 표시나 맞춤법 경고에 씁니다.

@property --underline-offset {
  syntax: "<length>"; inherits: true; initial-value: 1px;
}
.hl {
  text-decoration-line: underline;
  text-decoration-style: wavy;
  text-decoration-color: $color;
  text-underline-offset: var(--underline-offset);
  animation: wave $duration linear infinite;
}
@keyframes wave {
  0%, 100% { --underline-offset: 0px; }
  50%      { --underline-offset: 5px; }
}

05취소선 긋기

글자 중간 높이를 긋는 선

글자 중간 높이의 가로선을 왼쪽부터 그어 취소선이 눈앞에서 그어지는 순간을 만듭니다. 선의 높이가 1.5px와 3px 사이를 요동쳐 한 번에 긋지 않고 두세 번 힘을 주어 긋는 느낌을 냅니다.

취소선 긋기
새 창에서 열기

05 · 취소선 긋기 — 측정 누적면적 0.204% · 움직인 프레임 19/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

transform-origin: lefttransform:scaleX500ms

할인 전 가격에

할인 전 가격이나 완료된 할 일에 씁니다.

.price__strike {
  position: absolute; left: -2%; right: -2%; top: 52%; height: 2px;
  background: $color;
  transform: scaleX(0); transform-origin: left center;
  animation: strike $duration $easing infinite;
}
@keyframes strike {
  0%   { transform: scaleX(0); }
  30%  { transform: scaleX(1); }
  80%  { transform: scaleX(1); }
  100% { transform: scaleX(0); }
}

06배경 채우기

background-size 만으로 채우기

링크 배경을 background-size만으로 왼쪽부터 채우는데, 텍스트 마우스 오버 효과로 쓰려면 같은 값을 :hover 에 걸면 됩니다. 채워지는 동안 수직 크기가 88%부터 104%까지 불규칙하게 오르내려 물감이 번지듯 두께가 살아 움직입니다.

배경 채우기
새 창에서 열기

06 · 배경 채우기 — 측정 누적면적 3.281% · 움직인 프레임 21/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

background-sizebackground-position:left2s

채운 자리가 밀리지 않는 이유

background-position을 left로 고정해 채워진 자리가 뒤로 밀리지 않습니다.

.nav {
  background: linear-gradient(90deg, $color, $color);
  background-repeat: no-repeat;
  background-position: left center;
  background-size: 0% 100%;
  animation: fill $duration $easing infinite;
}
@keyframes fill {
  0%   { background-size: 0% 100%; }
  25%  { background-size: 100% 100%; }
  75%  { background-size: 100% 100%; }
  100% { background-size: 0% 100%; }
}

07점선 자라기

점선을 scaleX 로 늘리기

점을 반복해서 그린 얇은 막대를 scaleX로 늘려 점선이 왼쪽부터 이어 붙는 것처럼 보이게 합니다. 막대의 높이가 2.5px와 4px 사이에서 주기와 같은 리듬으로 진동해 점들도 함께 굵어졌다 가늘어집니다.

점선 자라기
새 창에서 열기

07 · 점선 자라기 — 측정 누적면적 0.312% · 움직인 프레임 23/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

repeating-linear-gradienttransform:scaleX700ms

다음 단계로 이끄는 선에

단계별 안내에서 다음 단계로 이끄는 선에 씁니다.

.hl__dots {
  background-image: repeating-linear-gradient(90deg, $color 0 3px, transparent 3px 8px);
  transform: scaleX(0); transform-origin: left center;
  animation: grow $duration $easing infinite;
}
@keyframes grow {
  0%   { transform: scaleX(0); }
  40%  { transform: scaleX(1); }
  80%  { transform: scaleX(1); }
  100% { transform: scaleX(0); }
}

08색 스윕

이음새 없이 훑고 지나가기

대각선 그러데이션을 무한히 흘려보내 빛 한 줄이 이음새 없이 배지를 훑고 지나가게 합니다. 빛 줄기의 수직 두께도 좌우로 1px 안팎씩 밀려 유리가 아닌 젖은 페인트 위를 지나는 듯한 결이 납니다.

색 스윕
새 창에서 열기

08 · 색 스윕 — 측정 누적면적 3.189% · 움직인 프레임 18/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

대각선 그러데이션background-position2s·linear

linear 여야 하는 까닭

linear 이징이어야 한 바퀴가 끝나는 지점에서 튀지 않습니다.

.badge::after {
  background: linear-gradient(115deg, transparent 30%, $color 48%, transparent 66%);
  background-size: 250% 100%;
  mix-blend-mode: overlay;
  animation: sweep $duration linear infinite;
}
@keyframes sweep {
  0%   { background-position: 150% 0; }
  100% { background-position: -150% 0; }
}

09텍스트 셰도 팝

커스텀 프로퍼티로 흐림 반경 움직이기

등록한 커스텀 프로퍼티로 그림자 흐림 반경을 애니메이션해 숫자가 한 번 통통 튀며 진하게 강조됩니다. 흐림 반경의 줄어드는 폭이 촘촘히 요동쳐 번짐이 기계의 단일 감쇠가 아니라 잉크가 마르는 결로 보입니다.

텍스트 셰도 팝
새 창에서 열기

09 · 텍스트 셰도 팝 — 측정 누적면적 3.196% · 움직인 프레임 23/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

@property <length>filter:drop-shadow1s

최종가와 카운트다운에

최종가나 카운트다운 숫자에 씁니다.

@property --shadow-blur {
  syntax: "<length>"; inherits: false; initial-value: 0px;
}
.hl {
  filter: drop-shadow(0 0 var(--shadow-blur) $color);
  animation: pop $duration $easing infinite;
}
@keyframes pop {
  0%   { transform: scale(1);    --shadow-blur: 0px; }
  40%  { transform: scale(1.06); --shadow-blur: 10px; }
  70%  { transform: scale(1);    --shadow-blur: 4px; }
  100% { transform: scale(1);    --shadow-blur: 0px; }
}

어디서 깨지는가 — 함정 둘

z-index -1 은 왜 사라졌나

아홉 개 중 두 개(01 형광펜 강조, 02 마커 겹침)는 처음 만들었을 때 화면에 전혀 안 보였습니다. z-index: -1로 글자 뒤에 숨긴 형광펜 블록을 부모에 isolation: isolate 없이 두면, 포지션이 없는 조상의 배경 페인트보다도 먼저(=아래로) 그려져 완전히 가려집니다. 강조를 담은 요소에 isolation: isolate 한 줄을 더하자 형광펜이 다시 나타났고, 렌더 측정에서 누적면적 0%였던 값이 0.8% 이상으로 올라갔습니다.

은은함과 안 보임은 한 끗 차이

글자가 제 배경에 묻히는 이 실패는 화면 전체를 어두운 계기판으로 덮는 HUD 랜딩 부품에서도 똑같은 대비 계산으로 되풀이됩니다.

04 물결 밑줄도 비슷한 함정이 있었습니다. text-underline-offset을 1px에서 3px 사이로만 흔들자 프레임 사이 변화가 너무 작아 렌더 측정에서 "거의 안 움직이는 애니메이션"으로 잡혔고, 범위를 0px에서 5px로 넓히자 정상적으로 물결이 보였습니다. 값이 작을수록 은은해 보이지만, 은은함과 안 보임은 한 끗 차이입니다. 두 함정 모두 렌더 측정값을 실제로 찍어 보지 않았다면 "눈에는 그럭저럭 보이는데" 정도로 넘어갔을 문제였습니다. 이 두 번의 수정이 이미 반영된 아홉 개 파일을 담은 압축 파일의 비밀번호는 hx9yh6mr이며, 아래 버튼을 누르면 받을 수 있습니다.

접근성

움직임은 꺼도 강조는 남긴다

OS에서 모션 줄이기를 켠 사람에게는 아홉 항목 모두 prefers-reduced-motion: reduce 안에서 각기 다른 결과를 보여 줍니다. 움직임은 끄되 강조 자체는 남기는 게 원칙입니다. 01·02는 형광펜이 칠해진 채로 고정되고, 04는 물결 밑줄이 가운데 값에서 멈추며, 09는 그림자가 흐릿하게 유지된 채로 튐만 사라집니다. 03·05·07처럼 SVG·가로선·점선을 위해 별도 레이어를 추가한 항목은 aria-hidden="true"를 걸어 스크린리더가 장식만 건너뛰고 실제 문장은 그대로 읽게 했습니다. reduced-motion 미디어 쿼리가 어느 브라우저부터 되는지는 MDN 문서에 정리돼 있습니다(참고).

이어서 볼 글

형광펜·밑줄 말고 다른 강조 기법은 CSS 애니메이션 카테고리에서 더 찾을 수 있고, 사이트 운영 방식은 소개 페이지에 적어 두었습니다.

FAQ

css 텍스트 애니메이션 효과를 한 페이지에 여러 개 같이 써도 되나요?

가능하지만 한 문단에는 강조 기법 하나만 쓰는 게 좋습니다. 형광펜(01·02)과 물결 밑줄(04)을 같은 문장에 겹치면 무엇이 중요한지 오히려 흐려집니다. 취소선(05)·배지 스윕(08)처럼 맥락이 다른 요소끼리는 한 화면에 같이 있어도 자연스럽습니다.

강조되는 단어는 어떻게 정하나요?

HTML에서 강조할 부분만 span으로 감싸고 나머지는 그대로 둡니다. React 판은 zip의 react 폴더처럼 keyword나 before·after props로 문장을 나눠 넘기면 됩니다. 서버에서 받은 문자열을 그대로 그 props에 넣으면 동적인 키워드도 그대로 작동합니다.

애니메이션이 스크린리더에서도 문제없나요?

본문 글자 자체는 손대지 않고 배경·밑줄·그림자 같은 장식 레이어만 움직이므로 텍스트는 그대로 읽힙니다. 03·05·07처럼 별도 SVG·가로선·점선 레이어를 추가한 항목은 aria-hidden으로 스크린리더가 건너뛰게 했습니다. 움직임 자체가 부담스러운 사용자는 접근성 처리 덕분에 강조는 남고 애니메이션만 꺼집니다. 형광펜 쓸기 없이 밑줄 하나만 따로 움직이는 경우는 CSS 밑줄 애니메이션에 모아 두었습니다.

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

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