Una panoramica di base su come creare animazioni di lettere e parole divise.
In questo post voglio condividere alcune idee su come risolvere le animazioni e le interazioni di testo diviso per il web in modo minimale, accessibile e funzionante su tutti i browser. Prova la demo.
Se preferisci i video, ecco una versione di questo post su YouTube:
Panoramica
Le animazioni di testo suddiviso possono essere straordinarie. In questo post, tratteremo solo una piccola parte del potenziale dell'animazione, ma forniremo una base su cui costruire. L'obiettivo è animare in modo progressivo. Il testo deve essere leggibile per impostazione predefinita, con l'animazione creata sopra. Gli effetti di movimento del testo diviso possono diventare stravaganti e potenzialmente di disturbo, quindi manipoleremo solo l'HTML o applicheremo stili di movimento solo se l'utente è d'accordo con il movimento.
Ecco una panoramica generale del flusso di lavoro e dei risultati:
- Prepara le variabili condizionali di movimento ridotto per CSS e JS.
- Prepara le utilità di divisione del testo in JavaScript.
- Orchestra le condizioni e le utilità al caricamento della pagina.
- Scrivi transizioni e animazioni CSS per lettere e parole (la parte più bella).
Ecco un'anteprima dei risultati condizionali che vogliamo ottenere:

Se un utente preferisce un movimento ridotto, lasciamo il documento HTML così com'è e non aggiungiamo animazioni. Se il movimento è ok, procediamo a suddividerlo in parti. Ecco un'anteprima dell'HTML dopo che JavaScript ha suddiviso il testo per lettera.

Preparazione delle condizioni di movimento
La media query disponibile @media
(prefers-reduced-motion: reduce)
verrà utilizzata da CSS e
JavaScript in questo progetto. Questa media query è la nostra condizione principale per
decidere se dividere o meno il testo. La media query CSS verrà utilizzata per sospendere
transizioni e animazioni, mentre la media query JavaScript verrà utilizzata per
sospendere la manipolazione HTML.
Preparazione della condizione CSS
Ho utilizzato PostCSS per attivare la sintassi di Media Queries Level 5, in cui posso memorizzare un valore booleano della media query in una variabile:
@custom-media --motionOK (prefers-reduced-motion: no-preference);
Preparazione della condizione JS
In JavaScript, il browser fornisce un modo per controllare le media query. Ho utilizzato la destrutturazione per estrarre e rinominare il risultato booleano dal controllo delle media query:
const {matches:motionOK} = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
)
Posso quindi eseguire il test per motionOK
e modificare il documento solo se l'utente non ha
richiesto di ridurre il movimento.
if (motionOK) {
// document split manipulations
}
Posso controllare lo stesso valore utilizzando PostCSS per attivare la sintassi @nest
di
Nesting Draft 1. Ciò mi consente di
memorizzare tutta la logica relativa all'animazione e ai requisiti di stile per
il genitore e i figli in un unico posto:
letter-animation {
@media (--motionOK) {
/* animation styles */
}
}
Con la proprietà personalizzata PostCSS e un valore booleano JavaScript, siamo pronti ad aggiornare l'effetto in modo condizionale. Questo ci porta alla sezione successiva, in cui analizzo il codice JavaScript per trasformare le stringhe in elementi.
Dividere il testo
Lettere, parole, righe di testo e così via non possono essere animate singolarmente con CSS o JS. Per ottenere l'effetto, abbiamo bisogno di scatole. Se vogliamo animare ogni lettera, ogni lettera deve essere un elemento. Se vogliamo animare ogni parola, ogni parola deve essere un elemento.
- Crea funzioni di utilità JavaScript per dividere le stringhe in elementi
- Orchestrare l'utilizzo di queste utilità
Funzione di utilità per dividere le lettere
Un buon punto di partenza è una funzione che prende una stringa e restituisce ogni lettera in un array.
export const byLetter = text =>
[...text].map(span)
La sintassi spread di ES6 ha reso questa attività molto rapida.
Funzione di utilità per la divisione delle parole
Simile alla divisione delle lettere, questa funzione prende una stringa e restituisce ogni parola in un array.
export const byWord = text =>
text.split(' ').map(span)
Il metodo
split()
sulle stringhe JavaScript ci consente di specificare i caratteri in corrispondenza dei quali eseguire il taglio.
Ho superato uno spazio vuoto, che indica una divisione tra le parole.
Funzione di utilità per la creazione di caselle
L'effetto richiede caselle per ogni lettera e vediamo in queste funzioni che
map()
viene chiamato con una funzione span()
. Ecco la funzione span()
.
const span = (text, index) => {
const node = document.createElement('span')
node.textContent = text
node.style.setProperty('--index', index)
return node
}
È fondamentale notare che una proprietà personalizzata chiamata --index
viene impostata con
la posizione dell'array. Avere le caselle per le animazioni delle lettere è fantastico, ma
avere un indice da utilizzare in CSS è un'aggiunta apparentemente piccola con un grande impatto.
L'impatto più notevole è
sbalorditivo.
Potremo utilizzare --index
per compensare le animazioni e ottenere un aspetto
sfalsato.
Conclusione di Utilità
Il modulo splitting.js
completato:
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)
Il passaggio successivo consiste nell'importazione e nell'utilizzo di queste funzioni byLetter()
e byWord()
.
Orchestrazione split
Con le utilità di divisione pronte all'uso, mettere tutto insieme significa:
- Individuare gli elementi da dividere
- Dividere e sostituire il testo con HTML
Dopodiché, il CSS prende il sopravvento e anima gli elementi / le caselle.
Trovare gli elementi
Ho scelto di utilizzare attributi e valori per archiviare informazioni sull'animazione desiderata e su come dividere il testo. Mi è piaciuto inserire queste opzioni dichiarative
nell'HTML. L'attributo split-by
viene utilizzato da JavaScript per trovare
elementi e creare caselle per lettere o parole. L'attributo
letter-animation
o word-animation
viene utilizzato da CSS per scegliere come target gli elementi
figli e applicare trasformazioni e animazioni.
Ecco un esempio di HTML che mostra i due attributi:
<h1 split-by="letter" letter-animation="breath">animated letters</h1>
<h1 split-by="word" word-animation="trampoline">hover the words</h1>
Trovare elementi da JavaScript
Ho utilizzato la sintassi del selettore CSS per la presenza di attributi per raccogliere l'elenco di elementi di cui voglio dividere il testo:
const splitTargets = document.querySelectorAll('[split-by]')
Trovare elementi da CSS
Ho utilizzato anche il selettore di presenza degli attributi in CSS per dare a tutte le animazioni delle lettere gli stessi stili di base. In un secondo momento, utilizzeremo il valore dell'attributo per aggiungere stili più specifici per ottenere un effetto.
letter-animation {
@media (--motionOK) {
/* animation styles */
}
}
Dividere il testo sul posto
Per ciascuno dei target suddivisi trovati in JavaScript, dividiamo il testo
in base al valore dell'attributo e mappiamo ogni stringa a un <span>
. Possiamo
quindi sostituire il testo dell'elemento con le caselle che abbiamo creato:
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)
}
})
Conclusione dell'orchestrazione
index.js
in completamento:
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)
})
}
Il codice JavaScript potrebbe essere letto nel seguente modo in inglese:
- Importa alcune funzioni di utilità di supporto.
- Controlla se il movimento è accettabile per questo utente, in caso contrario non fare nulla.
- Per ogni elemento da dividere.
- Dividili in base a come devono essere suddivisi.
- Sostituisci il testo con gli elementi.
Dividere animazioni e transizioni
La manipolazione del documento di suddivisione sopra descritta ha appena sbloccato una moltitudine di potenziali animazioni ed effetti con CSS o JavaScript. Nella parte inferiore di questo articolo sono riportati alcuni link per aiutarti a trovare l'ispirazione per dividere le tue risorse.
È il momento di mostrare cosa puoi fare con questa funzionalità. Ti mostrerò 4 animazioni e transizioni basate su CSS. 🤓
Dividere le lettere
Come base per gli effetti di divisione delle lettere, ho trovato utile il seguente CSS. Ho inserito tutte le transizioni e le animazioni dietro la query multimediale di movimento e
poi ho assegnato a ogni nuova lettera secondaria span
una proprietà di visualizzazione e uno stile per
gestire gli spazi bianchi:
[letter-animation] > span {
display: inline-block;
white-space: break-spaces;
}
Lo stile degli spazi bianchi è importante per evitare che gli span che contengono solo uno spazio vengano compressi dal motore di layout. Ora passiamo alle cose divertenti con stato.
Esempio di lettere divise in transizione
Questo esempio utilizza le transizioni CSS per l'effetto di divisione del testo. Con le transizioni abbiamo bisogno di stati tra cui il motore possa animare e ho scelto tre stati: nessun passaggio del mouse, passaggio del mouse nella frase, passaggio del mouse su una lettera.
Quando l'utente passa il mouse sopra la frase, ovvero il contenitore, ridimensiono tutti i figli come se l'utente li avesse allontanati. Poi, quando l'utente passa il mouse sopra una lettera, la porto in primo piano.
@media (--motionOK) {
[letter-animation="hover"] {
&:hover > span {
transform: scale(.75);
}
& > span {
transition: transform .3s ease;
cursor: pointer;
&:hover {
transform: scale(1.25);
}
}
}
}
Esempio di animazione di lettere divise
Questo esempio utilizza un'animazione @keyframe
predefinita per animare all'infinito ogni
lettera e sfrutta l'indice della proprietà personalizzata incorporata per creare un effetto
sfalsato.
@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;
}
}
Dividi parole
Flexbox ha funzionato come tipo di contenitore in questi esempi, sfruttando in modo ottimale l'unità ch
come lunghezza di spazio adeguata.
word-animation {
display: inline-flex;
flex-wrap: wrap;
gap: 1ch;
}
Esempio di parole di transizione suddivise
In questo esempio di transizione utilizzo di nuovo il passaggio del mouse. Poiché l'effetto inizialmente nasconde il contenuto fino al passaggio del mouse, ho fatto in modo che l'interazione e gli stili venissero applicati solo se il dispositivo aveva la capacità di passare il mouse sopra.
@media (hover) {
[word-animation="hover"] {
overflow: hidden;
overflow: clip;
& > span {
transition: transform .3s ease;
cursor: pointer;
&:not(:hover) {
transform: translateY(50%);
}
}
}
}
Esempio di animazione di parole divise
In questo esempio di animazione utilizzo di nuovo CSS @keyframes
per creare un'animazione
infinita sfalsata su un normale paragrafo di testo.
[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;
}
}
Conclusione
Ora che sai come ho fatto, come faresti tu? 🙂
Diversifichiamo i nostri approcci e impariamo tutti i modi per creare sul web. Crea un Codepen o ospita la tua demo, inviami un tweet e la aggiungerò alla sezione Remix della community di seguito.
Origine
Altre demo e fonti d'ispirazione
Remix della community
- Componente web
<text-hover>
di gnehcwu su CodeSandbox