Présentation générale de la création d'animations de lettres et de mots fractionnées
Dans ce post, je veux partager la réflexion sur les façons de résoudre les animations de texte fractionné et des interactions minimes, accessibles et compatibles avec tous les navigateurs. Essayez la démonstration.
Si vous préférez la vidéo, voici une version YouTube de cet article:
Présentation
Les animations de texte fractionné peuvent être incroyables. Nous allons à peine effleurer la surface de potentiel d'animation dans cet article, mais il fournit une base pour construire de données. L'objectif est l'animation progressive. Le texte doit être lisible par par défaut, avec l'animation construite sur le dessus. Les effets de mouvement de fractionnement du texte peuvent extravagants et potentiellement gênants, nous ne manipulerons que du code HTML, ou appliquer des styles de mouvement si l'utilisateur est d'accord avec le mouvement.
Voici un aperçu général du workflow et des résultats:
- Préparer la réduction des mouvements conditionnels pour CSS et JavaScript.
- Préparer les utilitaires de texte fractionné dans JavaScript.
- Orchestrer les instructions conditionnelles et les utilitaires sur la page de votre application.
- Écrire des animations et des transitions CSS des lettres et des mots (la partie spéciale !).
Voici un aperçu des résultats conditionnels que nous recherchons:
![Capture d'écran des outils de développement Chrome avec le panneau "Elements" ouvert et l'option "Reduce" (réduction des mouvements) définie sur "reduce" et "h1" s'affiche non fractionné](https://web.dev/static/articles/building/split-text-animations/image/screenshot-the-chrome-de-65fd5b490f405.png?authuser=6&hl=fr)
Si un utilisateur préfère réduire les mouvements, nous laissons le document HTML tel quel et nous ne de l'animation. Si le mouvement est acceptable, nous le découpons en plusieurs parties. Voici un Aperçu du code HTML après que JavaScript a divisé le texte par lettre
![Capture d'écran des outils de développement Chrome avec le panneau "Elements" ouvert et l'option "Reduce" (réduction des mouvements) définie sur "reduce" et "h1" s'affiche non fractionné](https://web.dev/static/articles/building/split-text-animations/image/screenshot-the-chrome-de-fd950f1664ff6.png?authuser=6&hl=fr)
Préparer des instructions conditionnelles de mouvement
La requête média @media
(prefers-reduced-motion: reduce)
, disponible, qui est pratique, sera utilisée à partir du CSS et
JavaScript dans ce projet. Cette requête média est notre condition principale pour
décider de scinder
le texte ou non. La requête média CSS sera utilisée pour retenir
les transitions et les animations, tandis que la requête média JavaScript sera utilisée pour
ne pas manipuler HTML.
Préparer l'instruction CSS conditionnelle
J'ai utilisé PostCSS pour activer la syntaxe des requêtes média de niveau 5, dans lequel je peux stocker une valeur booléenne de requête média dans une variable:
@custom-media --motionOK (prefers-reduced-motion: no-preference);
Préparer l'instruction conditionnelle JS
En JavaScript, le navigateur permet de vérifier les requêtes média. déstructuration pour extraire et renommer le résultat booléen du contrôle de requête média:
const {matches:motionOK} = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
)
Je peux ensuite tester motionOK
et modifier le document uniquement si l'utilisateur n'a pas
de réduire les mouvements.
if (motionOK) {
// document split manipulations
}
Je peux vérifier la même valeur en utilisant PostCSS pour activer la syntaxe @nest
à partir de
Brouillon d'imbrication 1. Cela me permet de
stocker toute la logique de l'animation et ses exigences de style pour
parents et enfants, depuis un seul et même endroit:
letter-animation {
@media (--motionOK) {
/* animation styles */
}
}
Avec la propriété personnalisée PostCSS et une valeur booléenne JavaScript, nous pouvons pour améliorer l'effet de manière conditionnelle. Cela nous amène à la section suivante où je décomposer le code JavaScript pour transformer des chaînes en éléments.
Scinder du texte
Les lettres, les mots, les lignes, etc. ne peuvent pas être animés individuellement avec CSS ou JS. Pour obtenir l'effet, il nous faut des cases. Si nous voulons animer chaque lettre, chaque lettre doit être un élément. Si nous voulons animer chaque mot, le mot doit être un élément.
- Créer des fonctions utilitaires JavaScript pour diviser des chaînes en éléments
- Orchestrer l'utilisation de ces utilitaires
Fonction utilitaire de division de lettres
Un bon point de départ consiste à utiliser une fonction qui prend une chaîne et renvoie chaque dans un tableau.
export const byLetter = text =>
[...text].map(span)
La répartir la syntaxe d'ES6 ont vraiment contribué à rendre cette tâche rapide.
Fonction utilitaire de division des mots
Semblable à la division des lettres, cette fonction prend une chaîne et renvoie chaque mot dans un tableau.
export const byWord = text =>
text.split(' ').map(span)
La
split()
sur les chaînes JavaScript nous permet de spécifier les caractères à segmenter.
J'ai inséré un espace vide, indiquant une division entre les mots.
Réaliser une fonction utilitaire des boîtes
L'effet nécessite des cases pour chaque lettre, et nous voyons dans ces fonctions que
map()
est appelé avec une fonction span()
. Voici la fonction span()
.
const span = (text, index) => {
const node = document.createElement('span')
node.textContent = text
node.style.setProperty('--index', index)
return node
}
Il est essentiel de noter qu'une propriété personnalisée appelée --index
est définie avec
la position du tableau. Avoir les cases pour les animations
de lettres est génial, mais
Avoir un index à utiliser en CSS est un ajout apparemment petit, avec un impact important.
Le plus notable à cause
de cet impact important est
stupéfiant.
Nous pourrons utiliser --index
pour décaler les animations d'un événement décalé
un style.
Conclusion concernant les utilitaires
Module splitting.js
terminé:
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)
L'étape suivante consiste à importer et à utiliser ces fonctions byLetter()
et byWord()
.
Orchestration partagée
Une fois les utilitaires de division prêts à l'emploi, assembler le tout donne:
- Trouver les éléments à diviser
- Diviser ces éléments et remplacer le texte par du code HTML
Ensuite, le CSS prend le relais et anime les éléments / zones.
Éléments du résultat
J'ai choisi d'utiliser des attributs et des valeurs pour stocker des informations
et comment diviser le texte. J'ai aimé proposer ces options déclaratives
dans le code HTML. L'attribut split-by
est utilisé à partir de JavaScript pour rechercher
et créer des zones pour les lettres ou les mots. L'attribut
letter-animation
ou word-animation
est utilisé dans le code CSS pour cibler l'élément.
et appliquer des transformations et des animations.
Voici un exemple de code HTML qui illustre ces deux attributs:
<h1 split-by="letter" letter-animation="breath">animated letters</h1>
<h1 split-by="word" word-animation="trampoline">hover the words</h1>
Rechercher des éléments à partir de JavaScript
J'ai utilisé la syntaxe du sélecteur CSS pour la présence d'attributs afin de rassembler la liste des pour lesquels le texte doit être divisé:
const splitTargets = document.querySelectorAll('[split-by]')
Rechercher des éléments à partir du CSS
J'ai également utilisé le sélecteur de présence d'attribut en CSS pour afficher toutes les animations de lettres les mêmes styles de base. Plus tard, nous utiliserons la valeur de l'attribut pour ajouter différents styles pour obtenir un effet.
letter-animation {
@media (--motionOK) {
/* animation styles */
}
}
Division du texte
Pour chaque cible de fractionnement trouvée dans JavaScript, nous diviserons le texte
en fonction de la valeur de l'attribut et mappez chaque chaîne à un <span>
. Nous pouvons
puis remplacez le texte de l'élément par les cases que nous avons créées:
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)
}
})
Conclusion sur l'orchestration
index.js
terminés:
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)
})
}
Le JavaScript peut être lu dans l'anglais suivant:
- Importez des fonctions utilitaires d'assistance.
- Vérifiez si les mouvements sont autorisés pour cet utilisateur. Si ce n'est pas le cas, ne faites rien.
- Pour chaque élément à diviser.
- Divisez-les en fonction de la manière dont elles doivent l'être.
- Remplacez le texte par des éléments.
Diviser des animations et des transitions
La manipulation du document de division ci-dessus vient de débloquer une multitude les animations et les effets potentiels avec CSS ou JavaScript. Il y a quelques liens au bas de cet article pour vous aider à trouver une idée de votre potentiel de division.
Il est temps de montrer ce que vous pouvez faire ! Je partagerai 4 animations CSS et les transitions. 🤓
Diviser les lettres
Comme base pour les effets de lettres fractionnées, j'ai constaté que le CSS suivant était
utiles. J’ai placé toutes les transitions et animations
derrière la requête média de mouvement et
puis attribuer à chaque nouvelle lettre enfant span
une propriété d'affichage et un style pour
à voir avec les espaces:
[letter-animation] > span {
display: inline-block;
white-space: break-spaces;
}
Le style des espaces blancs est important pour que les trajectoires qui ne sont qu'un espace ne sont pas réduits par le moteur de mise en page. Passons maintenant aux choses amusantes avec état.
Exemple de lettres de transition fractionnées
Cet exemple utilise des transitions CSS vers l'effet de fractionnement de texte. Avec les transitions, nous des états nécessaires pour que le moteur s'anime. J'ai choisi trois états: non survoler, survoler dans une phrase, survoler une lettre.
Lorsque l'utilisateur pointe sur la phrase, ou conteneur, je réduis l'ensemble les enfants comme si l'utilisateur les repoussait. Ensuite, lorsque l'utilisateur pointe de la lettre d'information, je l'amène.
@media (--motionOK) {
[letter-animation="hover"] {
&:hover > span {
transform: scale(.75);
}
& > span {
transition: transform .3s ease;
cursor: pointer;
&:hover {
transform: scale(1.25);
}
}
}
}
Animer des lettres fractionnées
Cet exemple utilise une animation @keyframe
prédéfinie pour animer indéfiniment chaque élément
et exploite l'index de propriété personnalisée intégré pour créer un décalage
l'effet.
@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;
}
}
Diviser en mots
Flexbox a fonctionné comme un type
de conteneur pour moi dans ces exemples.
Utiliser l'unité ch
comme une longueur d'écart correcte.
word-animation {
display: inline-flex;
flex-wrap: wrap;
gap: 1ch;
}
Exemple de mots séparés par une transition
Dans cet exemple de transition, j'utilise à nouveau le survol. Étant donné que l'effet masque initialement jusqu'au passage de la souris, je me suis assuré que l'interaction et les styles n'étaient appliqués si l'appareil pouvait survoler l'écran.
@media (hover) {
[word-animation="hover"] {
overflow: hidden;
overflow: clip;
& > span {
transition: transform .3s ease;
cursor: pointer;
&:not(:hover) {
transform: translateY(50%);
}
}
}
}
Animer des mots fractionnés
Dans cet exemple d'animation, j'utilise à nouveau le CSS @keyframes
pour créer un décalage
une animation infinie sur un paragraphe normal de texte.
[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;
}
}
Conclusion
Maintenant que tu sais comment j'ai fait, comment faire ?! 🙂
Diversifiez nos approches et découvrons toutes les manières de créer des applications sur le Web. Créez un Codepen ou hébergez votre propre démo, envoyez-moi un tweet pour que je l'ajoute au section "Remix de la communauté" ci-dessous.
Source
Plus de démos et d'inspiration
Remix de la communauté
- Composant Web
<text-hover>
de gnehcwu sur CodeSandbox