Présentation de base de la création d'animations de lettres et de mots fractionnés.
Dans cet article, je souhaite vous expliquer comment résoudre les problèmes d'animations de texte fractionné et d'interactions pour le Web qui sont 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 ce post:
Présentation
Les animations de fractionnement de texte peuvent être incroyables. Nous n'aborderons à peine que le potentiel d'animation dans cet article, mais il fournit une base sur laquelle s'appuyer. L'objectif est d'animer progressivement. Le texte doit être lisible par défaut, avec l'animation superposée. Les effets d'animation du texte fractionné peuvent devenir extravagants et potentiellement perturbateurs. Nous ne manipulerons donc le code HTML ou n'appliquons des styles d'animation que si l'utilisateur accepte le mouvement.
Voici un aperçu général du workflow et des résultats:
- Préparez des variables conditionnelles de mouvement réduites pour CSS et JS.
- Préparez les utilitaires de texte fractionné en JavaScript.
- Orchestrez les conditions et les utilitaires lors du chargement de la page.
- Écrivez des transitions et des animations CSS pour les lettres et les mots (la partie "rad" !).
Voici un aperçu des résultats conditionnels que nous allons obtenir:
Si un utilisateur préfère un mouvement réduit, nous laissons le document HTML tel quel et ne réalisons aucune animation. Si le mouvement est accepté, nous allons le découper en morceaux. Voici un aperçu du code HTML une fois que JavaScript a divisé le texte par lettre.
Préparer des conditions de mouvement
La requête média @media
(prefers-reduced-motion: reduce)
, pratiquement disponible, sera utilisée à partir de CSS et de JavaScript dans ce projet. Cette requête média est notre condition principale
pour décider de diviser le texte ou non. La requête média CSS permet de suspendre les transitions et les animations, tandis que la requête média JavaScript permet de suspendre la manipulation HTML.
Préparer l'instruction conditionnelle CSS
J'ai utilisé PostCSS pour activer la syntaxe des requêtes média de niveau 5, dans laquelle je peux stocker une requête média de niveau 5 dans une variable:
@custom-media --motionOK (prefers-reduced-motion: no-preference);
Préparer l'instruction conditionnelle JS
En JavaScript, le navigateur offre un moyen de vérifier les requêtes média. J'ai utilisé la déstructuration pour extraire et renommer le résultat booléen de la vérification des requêtes média:
const {matches:motionOK} = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
)
Je peux ensuite tester motionOK
et ne modifier le document que si l'utilisateur n'a pas demandé à réduire le mouvement.
if (motionOK) {
// document split manipulations
}
Je peux vérifier la même valeur en utilisant PostCSS pour activer la syntaxe @nest
à partir de l'imbrication brouillon 1. Cela me permet de stocker toute la logique de l'animation et ses exigences de style pour le parent et les enfants, en un seul endroit:
letter-animation {
@media (--motionOK) {
/* animation styles */
}
}
Avec la propriété personnalisée PostCSS et une valeur booléenne JavaScript, nous pouvons mettre à niveau l'effet de manière conditionnelle. Cela nous amène à la section suivante, dans laquelle je décompose le JavaScript pour transformer les chaînes en éléments.
Division du texte
Vous ne pouvez pas animer individuellement les lettres, les mots, les lignes, etc. avec CSS ou JS. Pour obtenir cet effet, nous avons besoin de cadres. Si nous voulons animer chaque lettre, alors chaque lettre doit être un élément. Si nous voulons animer chaque mot, alors chaque mot doit être un élément.
- Créer des fonctions utilitaires JavaScript permettant de diviser des chaînes en éléments
- Orchestrer l'utilisation de ces utilitaires
Fonction utilitaire de division de lettres
Vous pouvez commencer par utiliser une fonction qui prend une chaîne et renvoie chaque lettre d'un tableau.
export const byLetter = text =>
[...text].map(span)
La syntaxe de spread d'ES6 a 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 d'un tableau.
export const byWord = text =>
text.split(' ').map(span)
La méthode split()
sur les chaînes JavaScript nous permet de spécifier les caractères à utiliser pour le segment.
J'ai transmis un espace vide, indiquant une séparation entre les mots.
Créer une fonction utilitaire de 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 important de noter qu'une propriété personnalisée appelée --index
est définie avec la position du tableau. Disposer de zones de texte pour les animations de lettres est pratique, mais disposer d'un index à utiliser en CSS est un ajout en apparence mineur, ayant un impact important.
Le plus notable de cet impact est stupéfiant.
Nous pourrons utiliser --index
pour décaler les animations pour obtenir un résultat décalé.
Conclusion sur 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)
Vous allez ensuite importer et utiliser ces fonctions byLetter()
et byWord()
.
Orchestration partagée
Maintenant que les utilitaires de fractionnement sont prêts à être utilisés, assembler le tout donne les résultats suivants:
- Trouver les éléments à diviser
- en les divisant et en les remplaçant par du code HTML ;
Ensuite, CSS prend le relais et anime les éléments / cases.
Recherche d'éléments
J'ai choisi d'utiliser des attributs et des valeurs pour stocker des informations sur l'animation souhaitée et sur la façon de diviser le texte. J'aimais intégrer ces options
déclaratives dans le code HTML. L'attribut split-by
est utilisé à partir de JavaScript pour rechercher des éléments et créer des zones pour des lettres ou des mots. L'attribut letter-animation
ou word-animation
est utilisé dans CSS pour cibler les éléments enfants des éléments, et appliquer des transformations et des animations.
Voici un exemple de code HTML illustrant les deux attributs:
<h1 split-by="letter" letter-animation="breath">animated letters</h1>
<h1 split-by="word" word-animation="trampoline">hover the words</h1>
Recherche d'é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 éléments dont le texte doit être fractionné:
const splitTargets = document.querySelectorAll('[split-by]')
Rechercher des éléments à partir du code CSS
J'ai également utilisé le sélecteur de présence d'attribut en CSS pour attribuer à toutes les animations de lettres les mêmes styles de base. Plus tard, nous utiliserons la valeur de l'attribut pour ajouter des styles plus spécifiques afin d'obtenir un effet.
letter-animation {
@media (--motionOK) {
/* animation styles */
}
}
Division du texte en cours
Pour chacune des cibles de fractionnement que nous trouvons dans JavaScript, nous allons diviser le texte en fonction de la valeur de l'attribut et mapper chaque chaîne à une <span>
. Nous pouvons ensuite remplacer le texte de l'élément par les zones 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 de l'orchestration
index.js
terminé:
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 les langues suivantes:
- Importez des fonctions utilitaires d'assistance.
- Vérifiez si les mouvements peuvent être effectués par l'utilisateur. Si ce n'est pas le cas, ne faites rien.
- Pour chaque élément à scinder.
- Répartissez-les en fonction de la manière dont ils le souhaitent.
- Remplacez du texte par des éléments.
Diviser des animations et des transitions
La manipulation de documents de division ci-dessus vient de débloquer une multitude d'animations et d'effets potentiels avec CSS ou JavaScript. Vous trouverez quelques liens au bas de cet article pour vous inspirer de votre potentiel de division.
Voyons ce que vous pouvez en faire ! Je vais partager quatre transitions et animations basées sur CSS. 🤓
Diviser les lettres
J'ai trouvé que le code CSS suivant était utile pour créer les effets de lettres scindées. J'ai placé toutes les transitions et animations derrière la requête multimédia de mouvement, puis j'attribue à chaque nouvelle lettre enfant span
une propriété d'affichage et un style pour ce qu'il faut faire avec les espaces blancs:
[letter-animation] > span {
display: inline-block;
white-space: break-spaces;
}
Le style des espaces blancs est important pour que les éléments Span qui ne sont qu'un espace ne soient pas réduits par le moteur de mise en page. Passons maintenant aux choses amusantes avec état.
Exemple de lettres fractionnées de transition
Cet exemple utilise des transitions CSS pour l'effet de fractionnement du texte. Pour les transitions, nous avons besoin d'états pour que le moteur s'anime. J'ai choisi trois états: pas de survol, pointage dans la phrase et survol sur une lettre.
Lorsque l'utilisateur pointe sur la phrase (c'est-à-dire le conteneur), j'effectue un scaling à la baisse de tous les enfants comme si l'utilisateur les avait repoussés un peu plus loin. Ensuite, lorsque l'utilisateur passe la souris sur une lettre, je l'avance.
@media (--motionOK) {
[letter-animation="hover"] {
&:hover > span {
transform: scale(.75);
}
& > span {
transition: transform .3s ease;
cursor: pointer;
&:hover {
transform: scale(1.25);
}
}
}
}
Exemple d'animation de lettres divisées
Cet exemple utilise une animation @keyframe
prédéfinie pour animer infiniment chaque lettre et exploite l'index de propriété personnalisée intégré pour créer un effet de décalage.
@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 les mots
Dans ces exemples, Flexbox a fonctionné comme un type de conteneur, exploitant bien l'unité ch
en tant que longueur d'écart saine.
word-animation {
display: inline-flex;
flex-wrap: wrap;
gap: 1ch;
}
Exemple de division des transitions
Dans cet exemple de transition, j'utilise de nouveau la souris. Comme l'effet masque initialement le contenu jusqu'au survol, je me suis assuré que l'interaction et les styles n'étaient appliqués que si l'appareil pouvait pointer dessus.
@media (hover) {
[word-animation="hover"] {
overflow: hidden;
overflow: clip;
& > span {
transition: transform .3s ease;
cursor: pointer;
&:not(:hover) {
transform: translateY(50%);
}
}
}
}
Exemple de division d'animation
Dans cet exemple d'animation, j'utilise à nouveau CSS @keyframes
pour créer une animation infinie décalée sur un paragraphe de texte standard.
[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 tu en ferais ?! 🙂
Diversissons nos approches et apprenons toutes les façons de créer sur le Web. Créez un Codepen ou animez votre propre démo. Envoyez-moi un tweet à mon adresse e-mail pour que je l'ajoute à la section "Remix de la communauté" ci-dessous.
Source
Plus de démonstrations et d'inspiration
Remix de la communauté
- Composant Web
<text-hover>
par gnehcwu sur CodeSandbox