Podstawowe omówienie tworzenia animacji dzielonych liter i słów.
W tym poście chcę podzielić się przemyśleniami na temat sposobów rozwiązywania problemów z animacjami i interakcjami z podzielonym tekstem w internecie, które są minimalne, dostępne i działają w różnych przeglądarkach. Wypróbuj wersję demonstracyjną.
Jeśli wolisz film, obejrzyj tę wersję posta w YouTube:
Przegląd
Animacje z podziałem tekstu mogą być niesamowite. W tym poście zaledwie zarysujemy potencjał animacji, ale będzie to dobry punkt wyjścia. Celem jest animowanie progresywne. Tekst powinien być domyślnie czytelny, a animacja powinna być na nim oparta. Efekty ruchu w przypadku tekstu dzielonego mogą być ekstrawaganckie i potencjalnie przeszkadzać, dlatego będziemy manipulować kodem HTML lub stosować style ruchu tylko wtedy, gdy użytkownik wyrazi na to zgodę.
Ogólny przegląd procesu i wyników:
- Przygotuj zmienne warunkowe dotyczące ograniczonego ruchu na potrzeby CSS i JS.
- Przygotuj narzędzia do dzielenia tekstu w JavaScript.
- Orchestrate the conditionals and utilities on page load.
- Napisz przejścia i animacje CSS dla liter i słów (to jest super!).
Oto podgląd wyników warunkowych, które chcemy uzyskać:

Jeśli użytkownik woli ograniczone animacje, pozostawiamy dokument HTML bez zmian i nie stosujemy animacji. Jeśli ruch jest w porządku, dzielimy go na części. Oto podgląd kodu HTML po tym, jak JavaScript podzieli tekst na litery.

Przygotowywanie warunków ruchu
W tym projekcie zapytanie o multimedia dostępne @media
(prefers-reduced-motion: reduce)
będzie używane w CSS i JavaScript. To zapytanie o media jest naszym podstawowym warunkiem decydującym o podziale tekstu. Zapytanie o media CSS będzie używane do wstrzymywania przejść i animacji, a zapytanie o media JavaScript – do wstrzymywania manipulacji HTML.
Przygotowywanie warunku usługi porównywania cen
Użyłem PostCSS, aby włączyć składnię Media Queries Level 5, w której mogę przechowywać wartość logiczną zapytania o multimedia w zmiennej:
@custom-media --motionOK (prefers-reduced-motion: no-preference);
Przygotowywanie warunku JS
W JavaScript przeglądarka udostępnia sposób sprawdzania zapytań o media. Użyłem destrukturyzacji, aby wyodrębnić i zmienić nazwę wyniku logicznego ze sprawdzenia zapytania o media:
const {matches:motionOK} = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
)
Mogę wtedy sprawdzić, czy użytkownik nie poprosił o ograniczenie ruchu, i zmienić dokument tylko wtedy, gdy nie poprosił.motionOK
if (motionOK) {
// document split manipulations
}
Tę samą wartość mogę sprawdzić za pomocą PostCSS, aby włączyć składnię @nest
z wersji 1 projektu Nesting. Dzięki temu cała logika animacji i wymagania dotyczące stylu elementów nadrzędnych i podrzędnych są przechowywane w jednym miejscu:
letter-animation {
@media (--motionOK) {
/* animation styles */
}
}
Dzięki niestandardowej właściwości PostCSS i wartości logicznej JavaScriptu możemy warunkowo ulepszyć efekt. W następnej sekcji omówię kod JavaScriptu, który służy do przekształcania ciągów znaków w elementy.
Dzielenie tekstu
Liter, słów, wierszy itp. tekstu nie można animować indywidualnie za pomocą CSS ani JS. Aby uzyskać ten efekt, potrzebujemy pudełek. Jeśli chcemy animować każdą literę, każda z nich musi być elementem. Jeśli chcemy animować każde słowo, każde z nich musi być elementem.
- Tworzenie funkcji narzędziowych JavaScript do dzielenia ciągów znaków na elementy
- Koordynowanie korzystania z tych narzędzi
Funkcja narzędzia do dzielenia liter
Na początek możesz użyć funkcji, która przyjmuje ciąg znaków i zwraca każdą literę w tablicy.
export const byLetter = text =>
[...text].map(span)
Składnia spread z ES6 bardzo ułatwiła to zadanie.
Funkcja narzędzia do dzielenia słów
Podobnie jak w przypadku dzielenia liter, ta funkcja pobiera ciąg znaków i zwraca każde słowo w tablicy.
export const byWord = text =>
text.split(' ').map(span)
Metoda
split()
w przypadku ciągów JavaScriptu umożliwia określenie, w których miejscach należy podzielić ciąg.
Przeszedłem przez pustą przestrzeń, która wskazuje na podział między słowami.
Making boxes utility function
Efekt wymaga pól dla każdej litery, a w tych funkcjach widzimy, że funkcja
map()
jest wywoływana z funkcją span()
. Oto funkcja span()
.
const span = (text, index) => {
const node = document.createElement('span')
node.textContent = text
node.style.setProperty('--index', index)
return node
}
Warto zauważyć, że ustawiana jest właściwość niestandardowa o nazwie --index
z pozycją w tablicy. Pola animacji liter są świetne, ale indeks do użycia w CSS to pozornie niewielki dodatek, który ma duży wpływ na efekt.
Najbardziej zauważalny w tym dużym wpływie jest wstrząs.
Będziemy mogli użyć --index
, aby przesunąć animacje i uzyskać efekt kaskadowy.
Podsumowanie dotyczące narzędzi
Moduł splitting.js
po ukończeniu:
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)
Następnie zaimportuj i użyj funkcji byLetter()
i byWord()
.
Administrowanie podziałem
Gdy narzędzia do dzielenia są gotowe do użycia, połączenie ich wszystkich oznacza:
- Wyszukiwanie elementów do podziału
- dzielenie i zastępowanie tekstu kodem HTML,
Następnie CSS przejmuje kontrolę i animuje elementy lub pola.
Znajdowanie elementów
Do przechowywania informacji o żądanej animacji i sposobie dzielenia tekstu użyłem atrybutów i wartości. Podobało mi się umieszczanie tych opcji deklaratywnych w HTML-u. Atrybut split-by
jest używany w JavaScript do wyszukiwania elementów i tworzenia pól dla liter lub słów. Atrybut letter-animation
lub word-animation
jest używany w CSS do kierowania na elementy podrzędne i stosowania przekształceń oraz animacji.
Oto przykładowy kod HTML, który pokazuje te 2 atrybuty:
<h1 split-by="letter" letter-animation="breath">animated letters</h1>
<h1 split-by="word" word-animation="trampoline">hover the words</h1>
Znajdowanie elementów za pomocą JavaScriptu
Użyłem składni selektora CSS dla obecności atrybutu, aby zebrać listę elementów, których tekst ma zostać podzielony:
const splitTargets = document.querySelectorAll('[split-by]')
Znajdowanie elementów w CSS
Użyłem też selektora obecności atrybutu w CSS, aby nadać wszystkim animacjom liter te same style podstawowe. Później użyjemy wartości atrybutu, aby dodać bardziej szczegółowe style i uzyskać efekt.
letter-animation {
@media (--motionOK) {
/* animation styles */
}
}
Dzielenie tekstu w miejscu
W przypadku każdego podzielonego elementu docelowego znalezionego w JavaScript podzielimy jego tekst na podstawie wartości atrybutu i przypiszemy każdy ciąg znaków do <span>
. Możemy wtedy zastąpić tekst elementu utworzonymi przez nas polami:
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)
}
})
Podsumowanie administracji
index.js
w trakcie realizacji:
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)
})
}
Kod JavaScript można odczytać w ten sposób:
- Zaimportuj niektóre funkcje pomocnicze.
- Sprawdź, czy ruch jest w porządku dla tego użytkownika. Jeśli nie, nie rób nic.
- W przypadku każdego elementu, który chcesz podzielić.
- Podziel je zgodnie z ich preferencjami.
- Zastąp tekst elementami.
Dzielenie animacji i przejść
Powyższe podzielenie dokumentu otwiera wiele możliwości animacji i efektów za pomocą CSS lub JavaScriptu. Na dole tego artykułu znajdziesz kilka linków, które pomogą Ci w podjęciu decyzji o podziale.
Czas pokazać, co potrafisz! Podzielę się 4 animacjami i przejściami opartymi na CSS. 🤓
Dzielenie liter
Jako podstawę efektów dzielenia liter przydatny okazał się ten kod CSS: Wszystkie przejścia i animacje umieściłem za zapytaniem o multimedia w ruchu, a następnie każda nowa litera podrzędna span
otrzymała właściwość display oraz styl określający, co zrobić z białymi znakami:
[letter-animation] > span {
display: inline-block;
white-space: break-spaces;
}
Styl białych znaków jest ważny, aby zakresy, które zawierają tylko spację, nie były zwijane przez silnik układu. Teraz przejdźmy do ciekawych funkcji z zachowywaniem stanu.
Przykład przejścia z podziałem liter
W tym przykładzie do efektu dzielenia tekstu użyto przejść CSS. W przypadku przejść potrzebujemy stanów, między którymi silnik będzie animować, więc wybrałem 3 stany: brak najechanej pozycji, najechana pozycja w zdaniu i najechana pozycja na literze.
Gdy użytkownik najedzie kursorem na zdanie, czyli kontener, zmniejszam wszystkie elementy podrzędne, tak jakby użytkownik odsunął je dalej. Gdy użytkownik najedzie kursorem na literę, wysuwam ją do przodu.
@media (--motionOK) {
[letter-animation="hover"] {
&:hover > span {
transform: scale(.75);
}
& > span {
transition: transform .3s ease;
cursor: pointer;
&:hover {
transform: scale(1.25);
}
}
}
}
Przykład animacji rozdzielonych liter
W tym przykładzie użyto predefiniowanej @keyframe
animacji, aby animować każdą literę w nieskończoność, oraz indeksu niestandardowej właściwości wbudowanej do utworzenia efektu rozłożenia w czasie.
@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;
}
}
Podziel na słowa
W tych przykładach Flexbox działał jako typ kontenera, który dobrze wykorzystywał jednostkę ch
jako odpowiednią długość odstępu.
word-animation {
display: inline-flex;
flex-wrap: wrap;
gap: 1ch;
}
Przykład dzielenia słów podczas przejścia
W tym przykładzie przejścia ponownie używam najazdu. Efekt początkowo ukrywa treść, dopóki nie najedzie się na nią kursorem, więc zadbałem o to, aby interakcja i style były stosowane tylko wtedy, gdy urządzenie ma możliwość najechania kursorem.
@media (hover) {
[word-animation="hover"] {
overflow: hidden;
overflow: clip;
& > span {
transition: transform .3s ease;
cursor: pointer;
&:not(:hover) {
transform: translateY(50%);
}
}
}
}
Przykład animowania podzielonych słów
W tym przykładzie animacji ponownie używam CSS @keyframes
, aby utworzyć animację z przesunięciem w czasie, która powtarza się w nieskończoność, na zwykłym akapicie tekstu.
[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;
}
}
Podsumowanie
Teraz, gdy wiesz, jak to zrobiłem, jak Ty byś to zrobił? 🙂
Urozmaićmy nasze podejście i poznajmy wszystkie sposoby tworzenia treści w internecie. Utwórz Codepen lub hostuj własną wersję demonstracyjną, wyślij mi ją w tweecie, a ja dodam ją do sekcji Remixy społeczności poniżej.
Źródło
Więcej wersji demonstracyjnych i inspiracji
Remiksy społeczności
<text-hover>
komponent internetowy autorstwa gnehcwu na platformie CodeSandbox