Animationen für geteilten Text erstellen

Ein grundlegender Überblick über die Erstellung von Animationen zum Aufteilen von Buchstaben und Wörtern.

In diesem Beitrag möchte ich meine Gedanken zu Möglichkeiten zur Lösung von animierten und interaktiven Textzeilen für das Web teilen, die minimalistisch, barrierefrei und plattformübergreifend sind. Demo ansehen

Demo

Wenn du lieber ein Video ansiehst, findest du hier eine YouTube-Version dieses Beitrags:

Übersicht

Textanimationen können sehr beeindruckend sein. In diesem Beitrag streifen wir nur die Oberfläche des Animationspotenzials, aber er bietet eine solide Grundlage, auf der Sie aufbauen können. Das Ziel ist die schrittweise Animation. Der Text sollte standardmäßig lesbar sein und die Animation sollte darüber liegen. Bewegungseffekte für geteilten Text können extravagant und potenziell ablenkend sein. Wir bearbeiten daher nur HTML oder wenden Bewegungsstile an, wenn der Nutzer mit Bewegung einverstanden ist.

Hier eine allgemeine Übersicht über den Workflow und die Ergebnisse:

  1. Bereiten Sie bedingte Variablen mit reduzierter Bewegung für CSS und JS vor.
  2. Vorbereiten von Split-Text-Dienstprogrammen in JavaScript
  3. Orchestrieren Sie die bedingten Anweisungen und Dienstprogramme beim Seitenaufbau.
  4. Erstellen Sie CSS-Übergänge und -Animationen für Buchstaben und Wörter (das ist der coole Teil!).

Hier ist eine Vorschau der bedingten Ergebnisse:

Screenshot der Chrome-Entwicklertools mit geöffnetem Bereich „Elemente“ und reduzierter Bewegung auf „Reduzieren“ festgelegt. Die H1-Überschrift ist nicht gesplittet.
Der Nutzer bevorzugt reduzierte Bewegung: Text ist gut lesbar und nicht gesplittet

Wenn ein Nutzer weniger Bewegungselemente bevorzugt, lassen wir das HTML-Dokument unverändert und führen keine Animation durch. Wenn Bewegung in Ordnung ist, schneiden wir sie in einzelne Stücke auf. Hier ist eine Vorschau des HTML-Codes, nachdem der Text durch JavaScript in Buchstaben aufgeteilt wurde.

Screenshot der Chrome-Entwicklertools mit geöffnetem Bereich „Elemente“ und reduzierter Bewegung auf „Reduzieren“ festgelegt. Die H1-Überschrift ist nicht gesplittet.
Nutzer ist mit Bewegung einverstanden; Text in mehrere <span>-Elemente unterteilt

Bewegungsbedingungen werden vorbereitet

Die verfügbare Mediaabfrage @media (prefers-reduced-motion: reduce) wird in diesem Projekt in CSS und JavaScript verwendet. Diese Medienabfrage ist unsere primäre Bedingung, um zu entscheiden, ob Text geteilt werden soll oder nicht. Mit der CSS-Medienabfrage werden Übergänge und Animationen unterdrückt, während die JavaScript-Medienabfrage die HTML-Manipulation verhindert.

Bedingte CSS-Anweisung vorbereiten

Ich habe PostCSS verwendet, um die Syntax von Media Queries Level 5 zu aktivieren, mit der ich eine boolesche Mediaabfrage in einer Variablen speichern kann:

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

Vorbereiten der JS-Bedingung

In JavaScript bietet der Browser eine Möglichkeit, Medienabfragen zu prüfen. Ich habe das boolesche Ergebnis aus der Medienabfrageprüfung mit Destrukturierung extrahiert und umbenannt:

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

Ich kann dann auf motionOK prüfen und das Dokument nur ändern, wenn der Nutzer keine Bewegungsreduzierung angefordert hat.

if (motionOK) {
  // document split manipulations
}

Ich kann denselben Wert prüfen, indem ich mit PostCSS die @nest-Syntax aus Nesting Draft 1 aktiviere. So kann ich die gesamte Logik der Animation und die Stilanforderungen für das übergeordnete und untergeordnete Element an einem Ort speichern:

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

Mit der benutzerdefinierten PostCSS-Eigenschaft und einem booleschen JavaScript-Code können Sie den Effekt unter bestimmten Bedingungen upgraden. Im nächsten Abschnitt erkläre ich das JavaScript zum Umwandeln von Strings in Elemente.

Text aufteilen

Buchstaben, Wörter, Zeilen usw. können nicht einzeln mit CSS oder JS animiert werden. Um diesen Effekt zu erzielen, benötigen wir Boxen. Wenn wir jeden Buchstaben animieren möchten, muss jeder Buchstabe ein Element sein. Wenn wir jedes Wort animieren möchten, muss jedes Wort ein Element sein.

  1. JavaScript-Dienstfunktionen zum Aufteilen von Strings in Elemente erstellen
  2. Nutzung dieser Dienstprogramme orchestrieren

Dienstfunktion zum Teilen von Buchstaben

Am besten beginnen Sie mit einer Funktion, die einen String verwendet und jeden Buchstaben in einem Array zurückgibt.

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

Die gestreute Syntax von ES6 hat dazu beigetragen, dass diese Aufgabe sehr schnell war.

Dienstfunktion zum Aufteilen von Wörtern

Ähnlich wie bei der Aufteilung von Buchstaben nimmt diese Funktion einen String an und gibt jedes Wort in einem Array zurück.

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

Mit der Methode split() für JavaScript-Strings können wir angeben, an welchen Zeichen das Schneiden erfolgen soll. Ich habe ein Leerzeichen übergeben, das auf eine Aufteilung zwischen Wörtern hinweist.

Dienstprogrammfunktion für Blöcke erstellen

Für den Effekt sind Kästchen für jeden Buchstaben erforderlich. In diesen Funktionen sehen wir, dass map() mit einer span()-Funktion aufgerufen wird. Hier ist die Funktion span().

const span = (text, index) => {
  const node = document.createElement('span')

  node.textContent = text
  node.style.setProperty('--index', index)

  return node
}

Beachten Sie, dass ein benutzerdefiniertes Attribut namens --index mit der Array-Position festgelegt wird. Die Felder für die Buchstabenanimationen sind großartig, aber ein Index zur Verwendung in CSS ist eine scheinbar kleine Ergänzung mit großer Wirkung. Am auffälligsten ist dabei die Staggering-Funktion. Wir können --index verwenden, um Animationen für eine gestaffelte Darstellung zu verschieben.

Schlussfolgerung zu Dienstprogrammen

Das splitting.js-Modul ist abgeschlossen:

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)

Als Nächstes lernen Sie, die Funktionen byLetter() und byWord() zu importieren und zu verwenden.

Geteilte Orchestrierung

Die Tools zum Aufteilen sind einsatzbereit. So funktionierts:

  1. Elemente finden, die Sie teilen möchten
  2. Sie aufteilen und Text durch HTML ersetzen

Danach übernimmt CSS und animiert die Elemente/Boxen.

Elemente suchen

Ich habe Attribute und Werte verwendet, um Informationen zur gewünschten Animation und zum Aufteilen des Texts zu speichern. Ich fand es gut, diese deklarativen Optionen in die HTML-Datei einzufügen. Das Attribut split-by wird in JavaScript verwendet, um Elemente zu finden und Felder für Buchstaben oder Wörter zu erstellen. Das Attribut letter-animation oder word-animation wird in CSS verwendet, um Transformationen und Animationen auf Elementkinder anzuwenden.

Hier ein Beispiel für HTML-Code mit den beiden Attributen:

<h1 split-by="letter" letter-animation="breath">animated letters</h1>
<h1 split-by="word" word-animation="trampoline">hover the words</h1>

Elemente über JavaScript finden

Ich habe die CSS-Selektorsyntax für das Vorhandensein von Attributen verwendet, um eine Liste der Elemente zu erstellen, deren Text aufgeteilt werden soll:

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

Elemente aus dem Preisvergleichsportal finden

Außerdem habe ich die Attributpräsenz in CSS verwendet, um allen Buchstabenanimationen die gleichen Basisstile zuzuweisen. Später verwenden wir den Attributwert, um spezifischere Stile hinzuzufügen und einen Effekt zu erzielen.

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

Text an Ort und Stelle aufteilen

Für jedes der Split-Ziele, die wir in JavaScript finden, wird der Text basierend auf dem Wert des Attributs aufgeteilt und jeder String einer <span> zugeordnet. Anschließend können wir den Text des Elements durch die Felder ersetzen, die wir erstellt haben:

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)
  }
})

Fazit zur Orchestrierung

index.js abgeschlossen:

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)
  })
}

Der JavaScript-Code könnte in folgendem Englisch gelesen werden:

  1. Importieren Sie einige Dienstprogrammfunktionen.
  2. Prüfen, ob Bewegung für diesen Nutzer in Ordnung ist. Andernfalls nichts tun.
  3. Für jedes Element, das aufgeteilt werden soll.
    1. Sie können sie nach Belieben aufteilen.
    2. Ersetzen Sie Text durch Elemente.

Animationen und Übergänge aufteilen

Durch die oben beschriebene Dokumentaufteilung stehen Ihnen eine Vielzahl von möglichen Animationen und Effekten mit CSS oder JavaScript zur Verfügung. Am Ende dieses Artikels finden Sie einige Links, die Ihnen als Inspiration dienen können.

Jetzt ist es an der Zeit, zu zeigen, was du damit anfangen kannst. Ich zeige Ihnen vier CSS-basierte Animationen und Übergänge. 🤓

Buchstaben trennen

Als Grundlage für die Effekte der geteilten Buchstaben fand ich das folgende CSS hilfreich. Ich habe alle Übergänge und Animationen hinter die Motion-Media-Abfrage gestellt und dann jedem neuen untergeordneten Buchstaben span eine Anzeigeeigenschaft sowie einen Stil für die Behandlung von Weißräumen zugewiesen:

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

Der Stil für Leerräume ist wichtig, damit die Spannen, die nur Leerzeichen sind, nicht von der Layout-Engine minimiert werden. Nun zu den zustandsorientierten, unterhaltsamen Inhalten.

Beispiel für aufgeteilte Buchstaben mit Wechsel

In diesem Beispiel werden CSS-Übergänge für den Split-Texteffekt verwendet. Für Übergänge benötigen wir Zustände, zwischen denen die Engine animieren kann. Ich habe drei Zustände ausgewählt: kein Hovering, Hovering im Satz und Hovering auf einem Buchstaben.

Wenn der Nutzer den Mauszeiger auf den Satz bzw. den Container bewegt, werden alle untergeordneten Elemente verkleinert, als würde der Nutzer sie weiter wegschieben. Wenn der Nutzer den Mauszeiger auf einen Buchstaben bewegt, wird er hervorgehoben.

@media (--motionOK) {
  [letter-animation="hover"] {
    &:hover > span {
      transform: scale(.75);
    }

    & > span {
      transition: transform .3s ease;
      cursor: pointer;

      &:hover {
        transform: scale(1.25);
      }
    }
  }
}

Beispiel für geteilte Buchstaben

In diesem Beispiel wird eine vordefinierte @keyframe-Animation verwendet, um jeden Buchstaben unendlich zu animieren. Außerdem wird der Inline-Index der benutzerdefinierten Eigenschaften genutzt, um einen Staffeleffekt zu erzeugen.

@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;
  }
}

Wörter aufteilen

In diesen Beispielen hat Flexbox als Containertyp gut funktioniert und die Einheit ch als angemessene Lücke genutzt.

word-animation {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 1ch;
}
Flexbox-Devtools mit Lücke zwischen den Wörtern

Beispiel für aufgeteilte Wörter mit Übergang

In diesem Beispiel für eine Überleitung verwende ich wieder den Hover-Effekt. Da der Effekt den Inhalt anfangs bis zum Hovering ausblendet, habe ich dafür gesorgt, dass die Interaktion und die Stile nur angewendet wurden, wenn das Gerät die Funktion zum Hovering unterstützte.

@media (hover) {
  [word-animation="hover"] {
    overflow: hidden;
    overflow: clip;

    & > span {
      transition: transform .3s ease;
      cursor: pointer;

      &:not(:hover) {
        transform: translateY(50%);
      }
    }
  }
}

Beispiel für animierte geteilte Wörter

In diesem Beispiel verwende ich wieder CSS @keyframes, um eine versetzte, endlose Animation für einen normalen Textabsatz zu erstellen.

[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;
  }
}

Fazit

Jetzt, da Sie wissen, wie ich das gemacht habe, wie würden Sie es machen? 🙂

Lassen Sie uns unsere Ansätze diversifizieren und alle Möglichkeiten kennenlernen, wie Sie im Web entwickeln können. Erstelle einen Codepen oder hoste deine eigene Demo, tweete mir einen Link dazu und ich füge sie unten in den Abschnitt „Community-Remixe“ ein.

Quelle

Weitere Demos und Inspiration

Remixe der Community