문자 및 단어 분할 애니메이션을 빌드하는 방법에 관한 기본적인 개요입니다.
이 게시물에서는 최소한의 접근성이 있고 여러 브라우저에서 작동하는 웹용 분할 텍스트 애니메이션과 상호작용을 해결하는 방법에 관한 생각을 공유하고자 합니다. 데모 사용해 보기
동영상을 선호한다면 이 게시물의 YouTube 버전을 참조하세요.
개요
텍스트 분할 애니메이션은 놀라울 수 있습니다. 이 게시물에서는 애니메이션의 잠재력에 대해 대략적으로만 다루겠지만 빌드를 위한 기초를 제공합니다. 순차적으로 애니메이션을 만드는 것이 목표입니다. 텍스트는 기본적으로 읽을 수 있어야 하며 애니메이션은 위에 작성되어 있어야 합니다. 텍스트 분할 모션 효과는 지나치게 화려하고 지장을 줄 수 있으므로 Google에서는 HTML을 조작하거나 사용자가 모션에 문제가 없는 경우에만 모션 스타일을 적용합니다.
워크플로와 결과의 일반적인 개요는 다음과 같습니다.
- CSS 및 JS용으로 축소된 모션 조건부 변수를 준비합니다.
- JavaScript에서 분할 텍스트 유틸리티를 준비합니다.
- 페이지 로드 시 조건부 및 유틸리티를 조정합니다.
- 문자와 단어의 CSS 전환 및 애니메이션을 작성합니다.
다음은 조건부 결과의 미리보기입니다.
![요소 패널이 열려 있고 축소된 모션이 '축소'로 설정되어 있으며 h1이 분할되지 않은 상태로 표시된 Chrome DevTools의 스크린샷](https://web.developers.google.cn/static/articles/building/split-text-animations/image/screenshot-the-chrome-de-65fd5b490f405.png?authuser=7&hl=ko)
사용자가 모션을 줄이는 것을 선호한다면 HTML 문서를 그대로 두고 애니메이션을 사용하지 않습니다. 움직임이 괜찮으면 가공되지 않은 조각을 자릅니다. 다음은 JavaScript가 텍스트를 문자별로 분할한 후의 HTML 미리보기입니다.
![요소 패널이 열려 있고 축소된 모션이 '축소'로 설정되어 있으며 h1이 분할되지 않은 상태로 표시된 Chrome DevTools의 스크린샷](https://web.developers.google.cn/static/articles/building/split-text-animations/image/screenshot-the-chrome-de-fd950f1664ff6.png?authuser=7&hl=ko)
모션 조건문 준비
편리하게 사용 가능한 @media
(prefers-reduced-motion: reduce)
미디어 쿼리는 이 프로젝트의 CSS 및 JavaScript에서 사용됩니다. 이 미디어 쿼리는 텍스트 분할 여부를 결정하기 위한
기본 조건부입니다 CSS 미디어 쿼리는 전환 및 애니메이션을 보류하는 데 사용되고, 자바스크립트 미디어 쿼리는 HTML 조작을 보류하는 데 사용됩니다.
CSS 조건부 준비
PostCSS를 사용하여 미디어 쿼리 수준 5 문법을 사용 설정했습니다. 여기에서는 미디어 쿼리 부울을 변수에 저장할 수 있습니다.
@custom-media --motionOK (prefers-reduced-motion: no-preference);
JS 조건부 준비
JavaScript에서는 브라우저가 미디어 쿼리를 확인하는 방법을 제공합니다. 저는 디스트럭처링을 사용하여 미디어 쿼리 확인에서 불리언 결과를 추출하고 이름을 바꾸었습니다.
const {matches:motionOK} = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
)
그러면 motionOK
를 테스트하고 사용자가 모션 감소를 요청하지 않은 경우에만 문서를 변경할 수 있습니다.
if (motionOK) {
// document split manipulations
}
PostCSS를 사용하여 Nesting Draft 1에서 @nest
구문을 사용 설정하여 동일한 값을 확인할 수 있습니다. 이렇게 하면 애니메이션에 관한 모든 로직과 상위 요소 및 하위 요소의 스타일 요구사항을 한곳에 저장할 수 있습니다.
letter-animation {
@media (--motionOK) {
/* animation styles */
}
}
PostCSS 맞춤 속성과 자바스크립트 부울을 사용하여 효과를 조건부로 업그레이드할 수 있습니다. 그러면 문자열을 요소로 변환하는 JavaScript에 대해 자세히 설명하는 다음 섹션으로 넘어가게 됩니다.
텍스트 분할
텍스트 문자, 단어, 행 등은 CSS 또는 JS로 개별적으로 애니메이션 처리할 수 없습니다. 효과를 얻으려면 상자가 필요합니다. 각 문자에 애니메이션을 적용하려면 각 문자가 요소여야 합니다. 각 단어에 애니메이션을 적용하려면 각 단어가 요소여야 합니다.
- 문자열을 요소로 분할하는 JavaScript 유틸리티 함수를 만듭니다.
- 유틸리티 사용 조정
문자 분할 유틸리티 함수
먼저 문자열을 받아 배열의 각 문자를 반환하는 함수부터 살펴보겠습니다.
export const byLetter = text =>
[...text].map(span)
ES6의 스프레드 문법이 이러한 작업을 신속하게 수행하는 데 큰 도움이 되었습니다.
단어 분할 유틸리티 함수
문자를 분할하는 것과 마찬가지로 이 함수는 문자열을 취하고 각 단어를 배열로 반환합니다.
export const byWord = text =>
text.split(' ').map(span)
JavaScript 문자열의 split()
메서드를 사용하면 슬라이스할 문자를 지정할 수 있습니다.
단어 간 분할을 나타내는 빈 공간을 전달했습니다.
상자 유틸리티 기능 만들기
이 효과를 사용하려면 각 문자에 상자가 필요하며 이러한 함수에서 span()
함수를 사용하여 map()
가 호출되는 것을 확인할 수 있습니다. 다음은 span()
함수입니다.
const span = (text, index) => {
const node = document.createElement('span')
node.textContent = text
node.style.setProperty('--index', index)
return node
}
--index
라는 맞춤 속성은 배열 위치로 설정하는 것이 중요합니다. 문자 애니메이션에 상자가 있는 것도 좋지만 CSS에 사용할 색인을 갖는 것은 겉보기에는 작지만 큰 영향을 미칩니다.
이러한 큰 영향에서 가장 눈에 띄는 것은 충격적인 것입니다.
지그재그 모양으로 애니메이션을 오프셋하는 방법으로 --index
를 사용할 수 있습니다.
공익사업 관련 결론
완료된 splitting.js
모듈은 다음과 같습니다.
const span = (text, index) => {
const node = document.createElement('span')
node.textContent = text
node.style.setProperty('--index', index)
return node
}
export const byLetter = text =>
[...text].map(span)
export const byWord = text =>
text.split(' ').map(span)
다음은 byLetter()
및 byWord()
함수를 가져와서 사용하는 것입니다.
분할 조정
분할 유틸리티를 사용할 준비가 되면, 이 모든 것을 통합한다는 것은 다음을 의미합니다.
- 분할할 요소 찾기
- 분할하여 텍스트를 HTML로 대체
그러면 CSS가 인계받아 요소 / 상자에 애니메이션을 적용합니다.
요소 찾기
속성과 값을 사용하여 원하는 애니메이션에 관한 정보와 텍스트를 분할하는 방법을 저장했습니다. 저는 이러한 선언적 옵션을
HTML에 넣는 것이 좋았습니다. split-by
속성은 JavaScript에서 요소를 찾고 문자 또는 단어 상자를 만드는 데 사용됩니다. letter-animation
또는 word-animation
속성은 CSS에서 요소 하위 요소를 타겟팅하고 변환 및 애니메이션을 적용하는 데 사용됩니다.
다음은 두 가지 속성을 보여주는 HTML 샘플입니다.
<h1 split-by="letter" letter-animation="breath">animated letters</h1>
<h1 split-by="word" word-animation="trampoline">hover the words</h1>
JavaScript에서 요소 찾기
속성 존재에 대한 CSS 선택자 문법을 사용하여 텍스트를 분할할 요소 목록을 수집했습니다.
const splitTargets = document.querySelectorAll('[split-by]')
CSS에서 요소 찾기
또한 CSS의 속성 현재 상태 선택기를 사용하여 모든 문자 애니메이션에 동일한 기본 스타일을 지정했습니다. 나중에 이 속성 값을 사용하여 더 구체적인 스타일을 추가하여 효과를 달성합니다.
letter-animation {
@media (--motionOK) {
/* animation styles */
}
}
제자리에서 텍스트 분할
JavaScript에서 찾은 각 분할 타겟의 경우 속성 값에 따라 텍스트를 분할하고 각 문자열을 <span>
에 매핑합니다. 그런 다음 요소의 텍스트를 우리가 만든 상자로 바꿀 수 있습니다.
splitTargets.forEach(node => {
const type = node.getAttribute('split-by')
let nodes = null
if (type === 'letter') {
nodes = byLetter(node.innerText)
}
else if (type === 'word') {
nodes = byWord(node.innerText)
}
if (nodes) {
node.firstChild.replaceWith(...nodes)
}
})
오케스트레이션 결론
index.js
완료:
import {byLetter, byWord} from './splitting.js'
const {matches:motionOK} = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
)
if (motionOK) {
const splitTargets = document.querySelectorAll('[split-by]')
splitTargets.forEach(node => {
const type = node.getAttribute('split-by')
let nodes = null
if (type === 'letter')
nodes = byLetter(node.innerText)
else if (type === 'word')
nodes = byWord(node.innerText)
if (nodes)
node.firstChild.replaceWith(...nodes)
})
}
JavaScript는 다음 영어로 읽을 수 있습니다.
- 도우미 유틸리티 함수를 가져옵니다.
- 이 사용자의 움직임이 괜찮은지, 아무 작업도 하지 않으면 확인합니다.
- 분할하려는 각 요소를 설정합니다.
- 분할 방식에 따라 분할하세요.
- 텍스트를 요소로 대체합니다.
애니메이션 및 전환 분할
위의 분할 문서 조작으로 CSS 또는 JavaScript를 통해 다양한 애니메이션과 효과를 얻을 수 있습니다. 이 문서 하단에는 분할 가능성을 높이는 데 도움이 되는 몇 가지 링크가 있습니다.
이제 이 기능으로 무엇을 할 수 있는지 보여드리겠습니다. 4가지 CSS 기반 애니메이션과 전환을 알려 드리겠습니다. 🤓
글자 분할
분할 문자 효과의 기반으로 다음 CSS가 유용하다는 것을 확인했습니다. 모든 전환 및 애니메이션을 모션 미디어 쿼리 뒤에 배치한 다음 각각의 새 하위 문자 span
에 표시 속성과 공백을 처리할 작업에 관한 스타일을 지정합니다.
[letter-animation] > span {
display: inline-block;
white-space: break-spaces;
}
공백 스타일은 공간일 뿐인 스팬이 레이아웃 엔진에 의해 축소되지 않도록 하는 데 중요합니다. 이제 스테이트풀(Stateful) 재미있는 작업을 살펴보겠습니다.
전환 분할 문자 예
이 예에서는 CSS 전환을 사용하여 텍스트 분할 효과를 적용합니다. 전환에서는 엔진에서 애니메이션을 적용할 상태가 필요합니다. 여기서는 세 가지 상태를 선택했습니다. 마우스 오버, 문장에 마우스 오버, 문자 위로 마우스를 가져갑니다.
사용자가 문장(컨테이너)에 마우스를 가져가면 마치 사용자가 하위 요소를 더 멀리 떨어뜨린 것처럼 모든 하위 요소를 축소합니다. 그런 다음 사용자가 문자에 마우스를 가져가면 글자를 앞으로 가져옵니다.
@media (--motionOK) {
[letter-animation="hover"] {
&:hover > span {
transform: scale(.75);
}
& > span {
transition: transform .3s ease;
cursor: pointer;
&:hover {
transform: scale(1.25);
}
}
}
}
문자 분할 예 애니메이션
이 예에서는 사전 정의된 @keyframe
애니메이션을 사용하여 각 문자에 무한 애니메이션을 적용하고 인라인 맞춤 속성 색인을 활용하여 지그재그 효과를 만듭니다.
@media (--motionOK) {
[letter-animation="breath"] > span {
animation:
breath 1200ms ease
calc(var(--index) * 100 * 1ms)
infinite alternate;
}
}
@keyframes breath {
from {
animation-timing-function: ease-out;
}
to {
transform: translateY(-5px) scale(1.25);
text-shadow: 0 0 25px var(--glow-color);
animation-timing-function: ease-in-out;
}
}
단어 분할
이 예에서는 Flexbox가 컨테이너 유형으로 작동하여 ch
단위를 건전한 간격 길이로 잘 활용했습니다.
word-animation {
display: inline-flex;
flex-wrap: wrap;
gap: 1ch;
}
전환 분할 단어의 예
이 전환 예에서는 마우스 오버를 다시 사용합니다. 처음에는 이 효과에서 마우스 오버할 때까지 콘텐츠가 숨겨지므로 기기에 마우스 오버 기능이 있는 경우에만 상호작용과 스타일이 적용되도록 했습니다.
@media (hover) {
[word-animation="hover"] {
overflow: hidden;
overflow: clip;
& > span {
transition: transform .3s ease;
cursor: pointer;
&:not(:hover) {
transform: translateY(50%);
}
}
}
}
단어 분할 예 애니메이션
이 애니메이션 예에서는 CSS @keyframes
를 다시 사용하여 일반 텍스트 단락에 지그재그형 무한 애니메이션을 만듭니다.
[word-animation="trampoline"] > span {
display: inline-block;
transform: translateY(100%);
animation:
trampoline 3s ease
calc(var(--index) * 150 * 1ms)
infinite alternate;
}
@keyframes trampoline {
0% {
transform: translateY(100%);
animation-timing-function: ease-out;
}
50% {
transform: translateY(0);
animation-timing-function: ease-in;
}
}
결론
이제 내가 어떻게 했는지 알았으니 어떻게 할 건가요? 🙂
접근 방식을 다양화하고 웹에서 빌드하는 모든 방법을 알아보겠습니다. Codepen을 만들거나 데모를 호스팅하고 트윗해 주시면 아래 커뮤니티 리믹스 섹션에 추가하겠습니다.
소스
더 많은 데모 및 아이디어
커뮤니티 리믹스
- CodeSandbox에 있는 gnehcwu의
<text-hover>
웹 구성요소