Creare animazioni di testo diviso

Una panoramica di base su come creare animazioni con lettere e parole divise.

In questo post voglio condividere idee su come risolvere animazioni di testo diviso interazioni per il web minime, accessibili e funzionanti su più browser. Prova la demo.

Demo

Se preferisci i video, ecco una versione di questo post su YouTube:

Panoramica

Le animazioni del testo diviso possono essere incredibili. Sminuiremo a malapena la superficie del potenziale di animazione in questo post, ma fornisce le basi per costruire su di Google. L'obiettivo è un'animazione progressiva. Il testo deve essere leggibile predefinita, con l'animazione più alta. Gli effetti di movimento del testo divisi possono diventare stravaganti e potenzialmente dirompenti, quindi manipoleremo solo il codice HTML, oppure applicare gli stili di movimento se l'utente è d'accordo con il movimento.

Ecco una panoramica generale del flusso di lavoro e dei risultati:

  1. Prepara il movimento condizionale per CSS e JS.
  2. Preparare le utilità di testo diviso in JavaScript.
  3. Orchestra le condizionali e le utilità presenti nella pagina caricamento.
  4. Scrivere transizioni e animazioni CSS per le lettere e le parole (la parte più bella!).

Ecco un'anteprima dei risultati condizionali che abbiamo pensato:

screenshot di Chrome DevTools con il riquadro Elementi aperto e il movimento ridotto impostato su "Reduce" e h1 non è suddiviso
. L'utente preferisce movimento ridotto: il testo è leggibile / non diviso

Se un utente preferisce la riduzione dei movimenti, lasciamo solo il documento HTML e non l'animazione. Se il movimento è corretto, procediamo a suddividerlo in pezzi. Ecco un anteprima del codice HTML dopo che JavaScript ha suddiviso il testo per lettera.

screenshot di Chrome DevTools con il riquadro Elementi aperto e il movimento ridotto impostato su "Reduce" e h1 non è suddiviso
. L'utente è d'accordo con il movimento; testo suddiviso in più <span> elementi

Preparazione delle condizioni di movimento in corso...

La query multimediale @media (prefers-reduced-motion: reduce) comodamente disponibile verrà utilizzata da CSS e JavaScript in questo progetto. Questa query multimediale è il nostro condizionale principale per decidere se dividere o meno il testo. La query supporti CSS verrà utilizzata per trattenere transizioni e animazioni, mentre la media query JavaScript verrà utilizzata la manipolazione dell'HTML.

Preparazione della condizione CSS

Ho utilizzato PostCSS per attivare la sintassi delle query multimediali di livello 5, dove posso archiviare da un valore booleano di query supporti all'interno di una variabile:

@custom-media --motionOK (prefers-reduced-motion: no-preference);

Preparazione del condizionale JS

In JavaScript, il browser fornisce un modo per controllare le query supporti, distruggere per estrarre e rinominare il risultato booleano dal controllo della query supporti:

const {matches:motionOK} = window.matchMedia(
  '(prefers-reduced-motion: no-preference)'
)

Posso quindi eseguire test per motionOK e modificare il documento solo se l'utente non ha di ridurre il movimento.

if (motionOK) {
  // document split manipulations
}

Posso verificare lo stesso valore utilizzando PostCSS per attivare la sintassi @nest da Bozza di nidificazione 1. Questo mi consente di archiviare tutta la logica dell'animazione e i relativi requisiti di stile per principali e secondari, in un unico posto:

letter-animation {
  @media (--motionOK) {
    /* animation styles */
  }
}

Con la proprietà personalizzata PostCSS e un valore booleano JavaScript, siamo pronti aggiornare l'effetto in modo condizionale. Passiamo alla sezione successiva, in cui suddividere il codice JavaScript per la trasformazione delle stringhe in elementi.

Suddivisione del testo

Le lettere di testo, le parole, le righe e così via non possono essere animate singolarmente con CSS o JS. Per ottenere l'effetto, abbiamo bisogno di caselle. Se vogliamo animare ogni lettera, ogni lettera deve essere un elemento. Se vogliamo animare ogni parola, parola deve essere un elemento.

  1. Creare funzioni di utilità JavaScript per suddividere le stringhe in elementi
  2. Orchestra l'utilizzo di queste utilità

Funzione di utilità per la suddivisione delle lettere

Un punto di partenza divertente è utilizzare una funzione che prende una stringa e restituisce ciascuna lettera in un array.

export const byLetter = text =>
  [...text].map(span)

La distribuire la sintassi di ES6 ha davvero contribuito a rendere l'attività un'attività rapida.

Funzione di utilità suddivisione delle parole

Come per la divisione delle lettere, questa funzione prende una stringa e restituisce ogni parola in un array.

export const byWord = text =>
  text.split(' ').map(span)

La split() sulle stringhe JavaScript ci consente di specificare a quali caratteri eseguire la suddivisione. Ho passato uno spazio vuoto, a indicare una divisione tra le parole.

Creazione delle funzioni di utilità delle caselle

L'effetto richiede delle caselle per ogni lettera e in queste funzioni vediamo 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 viene impostata una proprietà personalizzata denominata --index la posizione dell'array. Avere dei riquadri per le animazioni delle lettere è fantastico, ma avere un indice da usare in CSS è un'aggiunta apparentemente ridotta e di grande impatto. La cosa più importante in questo grande impatto è sconcertante. Potremo utilizzare --index per compensare le animazioni per uno sfalsamento look.

Conclusione su utility

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)

Ora devi importare e utilizzare queste funzioni byLetter() e byWord().

Orchestrazione suddivisa

Quando le utilità di suddivisione sono pronte all'uso, riunire tutti questi elementi significa:

  1. Individuare gli elementi da suddividere
  2. Suddivisione e sostituzione del testo con HTML

Dopodiché, il CSS prende il controllo e animerà gli elementi / le caselle.

Elementi per la ricerca

Ho scelto di utilizzare attributi e valori per memorizzare le informazioni animazione e come dividere il testo. Mi è piaciuto inserire queste opzioni dichiarative nel codice HTML. L'attributo split-by viene utilizzato da JavaScript, per trovare e creano caselle per lettere o parole. L'attributo L'elemento letter-animation o word-animation viene utilizzato da CSS per scegliere l'elemento target secondari e applicare trasformazioni e animazioni.

Ecco un esempio di codice HTML che illustra 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 degli attributi per raccogliere l'elenco di elementi che devono suddividere il testo:

const splitTargets = document.querySelectorAll('[split-by]')

Ricerca di elementi da CSS

Ho anche utilizzato il selettore della presenza dell'attributo in CSS per applicare animazioni a tutte le lettere gli stessi stili di base. In seguito, utilizzeremo il valore dell'attributo per aggiungere informazioni stili per ottenere un effetto.

letter-animation {
  @media (--motionOK) {
    /* animation styles */
  }
}

Suddivisione del testo sul posto

Per ogni target di suddivisione che troviamo in JavaScript, dividiamo il relativo testo in base al valore dell'attributo e mappa ogni stringa a un <span>. Possiamo quindi sostituisci 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 corso:

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 può essere letto nel seguente inglese:

  1. Importare alcune funzioni di utilità helper.
  2. Controlla se il movimento è a posto per questo utente; in caso contrario, non fare nulla.
  3. Per ogni elemento che vuoi suddividere.
    1. Dividili in base a come vogliono essere suddivisi.
    2. Sostituisci il testo con elementi.

Suddivisione di animazioni e transizioni

La precedente manipolazione dei documenti ha appena sbloccato una moltitudine di potenziali animazioni ed effetti con CSS o JavaScript. Ci sono alcuni link in fondo a questo articolo per aiutarti a trovare ispirazione per il tuo potenziale di divisione.

È il momento di dimostrare cosa puoi fare con questo strumento. condividerò 4 animazioni basate su CSS e transizioni. 🤓

Dividere le lettere

Come base per gli effetti delle lettere divisa, ho trovato il seguente CSS utili. Metto tutte le transizioni e le animazioni dietro la query multimediale di animazione assegna a ogni nuova lettera secondaria span una proprietà di visualizzazione e uno stile per quale a che fare con gli spazi:

[letter-animation] > span {
  display: inline-block;
  white-space: break-spaces;
}

Lo stile degli spazi bianchi è importante, perché le sezioni sono solo uno spazio, non vengono compresse dal motore di layout. E ora passiamo alle cose divertenti e divertenti.

Esempio di lettere divisa per la transizione

Questo esempio utilizza le transizioni CSS per l'effetto di testo diviso. Con le transizioni necessitano di stati per l'animazione del motore e ho scelto tre stati: no passare il mouse sopra una frase, passare il mouse sopra una lettera.

Quando l'utente passa il mouse sopra la frase, ovvero il container, rimuovo tutte le bambini come se l'utente li spingesse più lontano. Quindi, quando l'utente passa il mouse sopra lettera, lo annullo.

@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

In questo esempio viene utilizzata un'animazione @keyframe predefinita per animare all'infinito ogni e sfrutta l'indice delle proprietà personalizzate incorporate per creare uno sfalsamento effetto.

@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

In questi esempi, Flexbox ha funzionato come un tipo di container, sfruttando l'unità ch come lunghezza di spazio vuoto.

word-animation {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 1ch;
}
Strumenti di sviluppo Flexbox che mostrano il divario tra le parole

Esempio di transizione di parole divise

In questo esempio di transizione, uso di nuovo il passaggio del mouse. Poiché l'effetto inizialmente nasconde contenuti fino al passaggio del mouse, ho verificato che l'interazione e gli stili siano stati applicati se il dispositivo ha la possibilità di passare il mouse.

@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 il CSS @keyframes per creare una campagna sfalsata animazione infinita 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 ci ho fatto, come lo faresti?! 🙂

Diversificaamo i nostri approcci e impariamo tutti i modi per creare sul web. Crea un codepen o ospita la tua demo, inviaci un tweet e lo aggiungerò al Remix della community di seguito.

Origine

Altre demo e ispirazione

Remix della community