Ein grundlegender Überblick über das Erstellen von Animationen mit Buchstaben und Wörtern.
In diesem Beitrag möchte ich darüber nachdenken, wie sich geteilte Textanimationen und -interaktionen für das Web lösen lassen, die minimal, barrierefrei und browserübergreifend funktionieren. Demo ansehen
Falls du lieber ein Video hast, findest du hier eine YouTube-Version dieses Beitrags:
Überblick
Animationen mit geteiltem Text können fantastisch sein. Wir werden in diesem Beitrag kaum an der Oberfläche des Animationspotenzials kratzen, aber es bietet eine Grundlage, auf der wir aufbauen können. Das Ziel ist die schrittweise Animation. Der Text sollte standardmäßig lesbar sein. Die Animation wird oben eingeblendet. Bewegungseffekte für aufgeteilten Text können extravagant und potenziell störend sein. Daher bearbeiten wir HTML nur dann oder wenden Bewegungsstile an, wenn der Nutzer mit Bewegung einverstanden ist.
Im Folgenden erhalten Sie einen allgemeinen Überblick über den Workflow und die Ergebnisse:
- Vorbereiten bedingter Variablen für reduzierte Bewegung für CSS und JS
- Bereiten Sie Dienstprogramme für geteilten Text in JavaScript vor.
- Orchestrieren Sie die Bedingungen und Dienstprogramme beim Seitenaufbau.
- Schreiben Sie CSS-Übergänge und -Animationen für Buchstaben und Wörter.
Hier ist eine Vorschau der bedingten Ergebnisse, die wir verwenden werden:
Möchte ein Nutzer möglichst wenig Bewegung, lassen wir das HTML-Dokument unverändert und erstellen keine Animation. Wenn Bewegung in Ordnung ist, fahren wir fort und zerlegen sie. Hier sehen Sie eine Vorschau des HTML-Codes, nachdem JavaScript den Text nach Buchstaben aufgeteilt hat.
Bewegungsbedingungen vorbereiten
Die praktisch verfügbare Medienabfrage @media
(prefers-reduced-motion: reduce)
wird in diesem Projekt über CSS und JavaScript verwendet. Diese Medienabfrage ist die primäre Bedingung
für die Entscheidung, ob Text aufgeteilt werden soll. Die CSS-Medienabfrage wird verwendet, um Übergänge und Animationen zurückzuhalten, während die JavaScript-Medienabfrage verwendet wird, um die HTML-Manipulation zu unterdrücken.
CSS-Bedingung vorbereiten
Ich habe PostCSS verwendet, um die Syntax von Medienabfragen Ebene 5 zu aktivieren, wo ich einen booleschen Wert für Medienabfragen in einer Variablen speichern kann:
@custom-media --motionOK (prefers-reduced-motion: no-preference);
JS-Bedingung vorbereiten
In JavaScript bietet der Browser eine Möglichkeit, Medienabfragen zu prüfen. Ich habe destruktururing verwendet, um das boolesche Ergebnis aus der Medienabfrageprüfung zu extrahieren und umzubenennen:
const {matches:motionOK} = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
)
Ich kann dann auf motionOK
testen und das Dokument nur ändern, wenn der Nutzer die Reduzierung von Bewegungen nicht angefordert hat.
if (motionOK) {
// document split manipulations
}
Ich kann denselben Wert mithilfe von PostCSS prüfen, um die @nest
-Syntax aus Verschachtelungsentwurf 1 zu aktivieren. So kann ich die gesamte Logik der Animation sowie ihre Stilanforderungen für die übergeordneten und untergeordneten Elemente an einem Ort speichern:
letter-animation {
@media (--motionOK) {
/* animation styles */
}
}
Mit der benutzerdefinierten PostCSS-Eigenschaft und einem booleschen JavaScript-Wert können wir den Effekt unter bestimmten Bedingungen aktualisieren. Das bringt uns zum nächsten Abschnitt, in dem ich das JavaScript für die Umwandlung von Zeichenfolgen in Elemente aufschlüssele.
Text wird geteilt
Textbuchstaben, Wörter, Zeilen usw. können nicht einzeln mit CSS oder JS animiert werden. Um diesen Effekt zu erzielen, brauchen wir Boxen. Wenn wir jeden Buchstaben animieren wollen, muss jeder Buchstabe ein Element sein. Wenn wir jedes Wort animieren möchten, muss jedes Wort ein Element sein.
- JavaScript-Dienstfunktionen zum Aufteilen von Strings in Elemente erstellen
- Nutzung dieser Dienstprogramme orchestrieren
Dienstprogrammfunktion „Buchstaben teilen“
Wir empfehlen, mit einer Funktion zu beginnen, die einen String annimmt und jeden Buchstaben in einem Array zurückgibt.
export const byLetter = text =>
[...text].map(span)
Mit der Spread-Syntax von ES6 war dies wirklich eine schnelle Aufgabe.
Dienstprogrammfunktion „Wörter aufteilen“
Ähnlich wie beim Aufteilen von Buchstaben verwendet diese Funktion einen String und gibt jedes Wort in einem Array zurück.
export const byWord = text =>
text.split(' ').map(span)
Mit der split()
-Methode für JavaScript-Strings können wir angeben, welche Zeichen als Trennzeichen verwendet werden sollen.
Ich ging an ein leeres Leerzeichen weiter, was auf eine Trennung zwischen Wörtern hinweist.
Felder zum Dienstprogramm machen
Für den Effekt sind Felder für jeden Buchstaben erforderlich und in diesen Funktionen wird map()
mit einer span()
-Funktion aufgerufen. 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 eine benutzerdefinierte Eigenschaft namens --index
mit der Arrayposition festgelegt wird. Die Felder für die Buchstabenanimationen sind großartig, aber ein Index für die Verwendung in CSS ist eine scheinbar kleine Ergänzung mit einer großen Wirkung.
Besonders auffällig ist dabei die herausragende Wirkung.
Wir werden --index
verwenden können, um Animationen für einen gestaffelten Look zu verschieben.
Fazit zu Versorgungsunternehmen
Das abgeschlossene Modul 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)
Als Nächstes importieren und verwenden Sie die Funktionen byLetter()
und byWord()
.
Split-Orchestrierung
Wenn die Dienstprogramme zur Aufteilung betriebsbereit sind, bedeutet die Zusammenfassung Folgendes:
- Finden, welche Elemente aufgeteilt werden sollen
- Teilen und Ersetzen von Text durch HTML
Danach übernimmt CSS die Animation und animiert die Elemente / Felder.
Elemente suchen
Ich habe Attribute und Werte verwendet, um Informationen über die gewünschte Animation und die Aufteilung des Texts zu speichern. Ich habe diese deklarativen Optionen
in den HTML-Code eingefügt. 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 Elemente auf untergeordnete Elemente auszurichten und Transformationen und Animationen anzuwenden.
Hier ist ein Beispiel für HTML, das die beiden Attribute veranschaulicht:
<h1 split-by="letter" letter-animation="breath">animated letters</h1>
<h1 split-by="word" word-animation="trampoline">hover the words</h1>
Elemente aus JavaScript suchen
Ich habe die CSS-Selektor-Syntax für die Attributpräsenz verwendet, um die Liste der Elemente zu erfassen, deren Text aufgeteilt werden soll:
const splitTargets = document.querySelectorAll('[split-by]')
Elemente aus CSS finden
Außerdem habe ich den Selektor für die Attributpräsenz in CSS verwendet, um allen Buchstabenanimationen dieselben Basisstile zu geben. Später verwenden wir den Attributwert, um spezifischere Stile hinzuzufügen und so einen Effekt zu erzielen.
letter-animation {
@media (--motionOK) {
/* animation styles */
}
}
Text wird geteilt
Für jedes der aufgeteilten Ziele in JavaScript teilen wir den Text basierend auf dem Wert des Attributs auf und ordnen jeden String einer <span>
zu. Wir können dann 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 der 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:
- Importieren Sie einige Hilfsprogrammfunktionen.
- Prüfe, ob Bewegungen für diesen Nutzer in Ordnung sind. Andernfalls unternimmst du nichts.
- Für jedes Element, das aufgeteilt werden soll.
- Teile sie danach ein, wie sie aufgeteilt werden sollen.
- Ersetzen Sie Text durch Elemente.
Animationen und Übergänge teilen
Die oben genannte Aufteilungsdokumentmanipulation hat gerade eine Vielzahl von möglichen Animationen und Effekten mit CSS oder JavaScript freigeschaltet. Am Ende dieses Artikels finden Sie einige Links, die Ihnen helfen können, die Aufteilung zu erleichtern.
Jetzt ist es an der Zeit zu zeigen, was du damit alles machen kannst. Ich stelle Ihnen 4 CSS-gesteuerte Animationen und Übergänge vor. 🤓
Teilen von Buchstaben
Als Grundlage für die Split-Letter-Effekte fand ich das folgende CSS hilfreich. Ich platziere alle Übergänge und Animationen hinter der Motion-Medienabfrage und weise jedem neuen untergeordneten Buchstaben span
eine Anzeigeeigenschaft sowie einen Stil für die Verwendung von Leerräumen zu:
[letter-animation] > span {
display: inline-block;
white-space: break-spaces;
}
Der Stil der Leerzeichen ist wichtig, damit die Spannen, die nur ein Leerzeichen sind, nicht durch die Layout-Engine minimiert werden. Kommen wir nun zu den zustandsorientierten, lustigen Dingen.
Beispiel für getrennte Buchstaben
In diesem Beispiel werden CSS-Übergänge zum Effekt „Text teilen“ verwendet. Bei Übergängen brauchen wir Stadien, zwischen denen die Suchmaschine animiert werden kann, und ich habe drei Stadien ausgewählt: keinen Mouseover, den Mauszeiger in einem Satz und den Mauszeiger auf einen Buchstaben.
Wenn der Nutzer den Mauszeiger auf den Satz bzw. den Container bewegt, verkleinere ich alle untergeordneten Elemente, als ob der Nutzer sie weiter weggestoßen hätte. Wenn die Nutzenden die Maus über einen Buchstaben bewegen, bringe ich ihn nach vorne.
@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. Mithilfe des benutzerdefinierten Inline-Attributindex wird ein gestaffelter Effekt erzeugt.
@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
Flexbox hat in diesen Beispielen für mich als Containertyp funktioniert und die ch
-Einheit als gesunde Lückenlänge genutzt.
word-animation {
display: inline-flex;
flex-wrap: wrap;
gap: 1ch;
}
Beispiel für aufgeteilte Wörter mit Übergang
In diesem Übergangsbeispiel verwende ich wieder den Mauszeiger. Da der Effekt zuerst den Inhalt verbirgt, bis der Mauszeiger darauf bewegt wird, habe ich darauf geachtet, dass die Interaktion und die Stile nur angewendet werden, wenn das Gerät den Mauszeiger darüber bewegen kann.
@media (hover) {
[word-animation="hover"] {
overflow: hidden;
overflow: clip;
& > span {
transition: transform .3s ease;
cursor: pointer;
&:not(:hover) {
transform: translateY(50%);
}
}
}
}
Beispiel für geteilte Wörter animiert
In diesem Animationsbeispiel verwende ich wieder CSS @keyframes
, um eine gestaffelte unendliche Animation für einen regelmäßigen 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, wo du weißt, wie ich es gemacht habe, wie würdest du es tun?! 🙂
Diversifizieren wir unsere Ansätze und lernen Sie alle Möglichkeiten kennen, wie wir das Web nutzen können. Erstelle einen Codepen oder veranstalte deine eigene Demo, twittere mich mit ihr und ich füge sie unten zum Abschnitt „Community-Remixe“ hinzu.
Quelle
Weitere Demos und Inspiration
Community-Remixe
<text-hover>
-Webkomponente von gnehcwu in CodeSandbox