Una descripción general fundamental de cómo crear animaciones de letras y palabras divididas.
En esta publicación, quiero compartir algunas ideas para resolver interacciones y animaciones de texto dividido en la Web que son mínimas, accesibles y funcionan en todos los navegadores. Prueba la demostración.
Si prefieres ver un video, aquí tienes una versión de YouTube de esta publicación:
Descripción general
Las animaciones de texto dividido pueden ser increíbles. En esta publicación, apenas hablaremos del potencial de animación, pero brinda una base sobre la cual desarrollar. El objetivo es animar progresivamente. El texto debe ser legible de forma predeterminada, y la animación se compila sobre la parte superior. Los efectos de movimiento de texto dividido pueden resultar extravagantes y potencialmente disruptivos, por lo que solo manipularemos HTML o aplicaremos estilos de movimiento si el usuario está de acuerdo con el movimiento.
Esta es una descripción general del flujo de trabajo y los resultados:
- Prepara variables condicionales de movimiento reducido para CSS y JS.
- Prepara utilidades de texto dividido en JavaScript.
- Organiza las condicionales y utilidades en la carga de la página.
- Escribe transiciones y animaciones de CSS para letras y palabras (la parte ideal).
A continuación, se muestra una vista previa de los resultados condicionales que buscamos:
Si un usuario prefiere un movimiento reducido, dejaremos solo el documento HTML y no realizaremos ninguna animación. Si el movimiento está bien, lo cortamos en pedazos. A continuación, se muestra una vista previa del código HTML después de que JavaScript dividió el texto por letra.
Cómo preparar condicionales de movimiento
En este proyecto, se usará la consulta de medios @media
(prefers-reduced-motion: reduce)
que está disponible de forma conveniente desde CSS y JavaScript. Esta consulta de medios es nuestro condicional principal
para decidir dividir el texto o no. La consulta de medios de CSS se usará para retener transiciones y animaciones, mientras que la consulta de medios de JavaScript se usará para retener la manipulación de HTML.
Cómo preparar el condicional de CSS
Usé PostCSS para habilitar la sintaxis del nivel 5 de consultas de medios, en las que puedo almacenar un valor booleano de consulta de medios en una variable:
@custom-media --motionOK (prefers-reduced-motion: no-preference);
Prepara el condicional de JS
En JavaScript, el navegador proporciona una manera de verificar las consultas de medios. Usé la desestructuración para extraer y cambiar el nombre del resultado booleano de la verificación de consulta de medios:
const {matches:motionOK} = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
)
Luego, puedo probar motionOK
y solo cambiar el documento si el usuario no solicitó reducir el movimiento.
if (motionOK) {
// document split manipulations
}
Puedo verificar el mismo valor con PostCSS para habilitar la sintaxis @nest
desde Anidar borrador 1. Esto me permite almacenar toda la lógica de la animación y sus requisitos de estilo para el elemento superior y el secundario, en un solo lugar:
letter-animation {
@media (--motionOK) {
/* animation styles */
}
}
Con la propiedad personalizada PostCSS y un valor booleano de JavaScript, estamos listos para actualizar condicionalmente el efecto. Eso nos lleva a la siguiente sección, en la que describo JavaScript para transformar cadenas en elementos.
División del texto
Las letras de texto, las palabras, las líneas, etc., no se pueden animar individualmente con CSS o JS. Para lograr el efecto, necesitamos cuadros. Si queremos animar cada letra, cada letra debe ser un elemento. Si queremos animar cada palabra, cada palabra debe ser un elemento.
- Crear funciones de utilidad de JavaScript para dividir cadenas en elementos
- Organizar el uso de estas utilidades
Función de utilidad de división de letras
Un lugar divertido para comenzar es una función que toma una cadena y devuelve cada letra de un array.
export const byLetter = text =>
[...text].map(span)
La sintaxis extendida de ES6 realmente ayudó a que esa tarea fuera más rápida.
Función de utilidad de división de palabras
De manera similar a la división de letras, esta función toma una string y muestra cada palabra del array.
export const byWord = text =>
text.split(' ').map(span)
El método split()
en las strings de JavaScript nos permite especificar en qué caracteres segmentar.
Pasé un espacio vacío, que indica una división entre palabras.
Cómo crear la utilidad de las cajas
El efecto requiere cuadros para cada letra, y vemos en esas funciones que se llama a map()
con una función span()
. Esta es la función span()
.
const span = (text, index) => {
const node = document.createElement('span')
node.textContent = text
node.style.setProperty('--index', index)
return node
}
Es fundamental tener en cuenta que se configura una propiedad personalizada llamada --index
con la posición del array. Es excelente tener los cuadros para las animaciones de las letras, pero tener un índice para usar en CSS es una adición aparentemente pequeña con un gran impacto.
Lo más notable en este gran impacto es el asombroso.
Podremos usar --index
como forma de desplazar animaciones para lograr una apariencia escalonada.
Conclusión de las utilidades
Completa el módulo 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)
A continuación, importa y usa estas funciones byLetter()
y byWord()
.
Organización dividida
Con las utilidades de división listas para usar, reunir todo implica lo siguiente:
- Buscar qué elementos dividir
- Dividir y reemplazar texto por HTML
Luego, CSS se hace cargo de los elementos y los cuadros, y los anima.
Busca elementos
Elegí usar atributos y valores para almacenar información sobre la animación deseada y cómo dividir el texto. Me gustó incluir estas opciones
declarativas en el HTML. El atributo split-by
se usa desde JavaScript para encontrar elementos y crear cuadros para letras o palabras. El atributo letter-animation
o word-animation
se usa de CSS para orientarse a los elementos secundarios y aplicar transformaciones y animaciones.
A continuación, te mostramos un ejemplo de HTML que demuestra los dos atributos:
<h1 split-by="letter" letter-animation="breath">animated letters</h1>
<h1 split-by="word" word-animation="trampoline">hover the words</h1>
Cómo buscar elementos en JavaScript
Usé la sintaxis del selector CSS para la presencia de atributos con el fin de recopilar la lista de elementos que quieren dividir su texto:
const splitTargets = document.querySelectorAll('[split-by]')
Cómo buscar elementos de CSS
También utilicé el selector de presencia de atributos en CSS para otorgar los mismos estilos base a todas las animaciones de letras. Más adelante, usaremos el valor del atributo para agregar diseños más específicos y lograr un efecto.
letter-animation {
@media (--motionOK) {
/* animation styles */
}
}
División del texto en el lugar
Para cada una de las segmentaciones de división que encontramos en JavaScript, dividiremos su texto según el valor del atributo y asignaremos cada cadena a una <span>
. Luego, podemos reemplazar el texto del elemento con los cuadros que creamos:
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)
}
})
Conclusión de la orquestación
index.js
para completar:
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)
})
}
El código JavaScript se puede leer en el siguiente inglés:
- Importa algunas funciones de utilidad auxiliares.
- Comprueba si el movimiento es adecuado para este usuario. De lo contrario, no hagas nada.
- Para cada elemento que se desee dividir.
- Divídelos según cómo quieran hacerlo.
- Reemplazar el texto por elementos
Cómo dividir animaciones y transiciones
La manipulación de documentos anterior acaba de desbloquear una gran cantidad de posibles animaciones y efectos con CSS o JavaScript. Hay algunos vínculos en la parte inferior de este artículo que te ayudarán a expandir tu potencial de división.
Es momento de demostrar lo que puedes hacer con esto. compartiré 4 animaciones y transiciones basadas en CSS. 🤓
Letras divididas
Como base para los efectos de letra dividida, me pareció útil el siguiente CSS. Pongo todas las transiciones y animaciones detrás de la consulta de medios de movimiento y, luego, le asigno a cada letra secundaria span
una propiedad de pantalla y un estilo para qué hacer con los espacios en blanco:
[letter-animation] > span {
display: inline-block;
white-space: break-spaces;
}
El diseño de espacios en blanco es importante para que el motor de diseño no contraiga los intervalos que son solo un espacio. Ahora pasemos a la diversión con estado.
Ejemplo de letras divididas en la transición
En este ejemplo, se usan transiciones CSS para el efecto de texto dividido. Con las transiciones, necesitamos estados entre los que debe animar el motor. Elegí tres estados: no colocar el cursor sobre un elemento, colocar el cursor sobre una oración y colocar el cursor sobre una letra.
Cuando el usuario coloca el cursor sobre la oración, también conocida como el contenedor, redujo la escala de todos los elementos secundarios como si el usuario los alejara más. Luego, a medida que el usuario coloca el cursor sobre una letra, la llevo hacia adelante.
@media (--motionOK) {
[letter-animation="hover"] {
&:hover > span {
transform: scale(.75);
}
& > span {
transition: transform .3s ease;
cursor: pointer;
&:hover {
transform: scale(1.25);
}
}
}
}
Ejemplo de animación de letras divididas
En este ejemplo, se usa una animación @keyframe
predefinida para animar de forma infinita cada letra y se aprovecha el índice de propiedades personalizadas intercalado para crear un efecto escalonado.
@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;
}
}
Dividir palabras
Flexbox funcionó como un tipo de contenedor aquí en estos ejemplos, lo que aprovechó muy bien la unidad ch
como una longitud de intervalo adecuada.
word-animation {
display: inline-flex;
flex-wrap: wrap;
gap: 1ch;
}
Ejemplo de transición de palabras divididas
En este ejemplo de transición, utilizo el desplazamiento de nuevo. Como el efecto oculta inicialmente el contenido hasta que colocas el cursor sobre él, me aseguré de que la interacción y los estilos solo se aplicaran si el dispositivo podía colocar el cursor sobre ellos.
@media (hover) {
[word-animation="hover"] {
overflow: hidden;
overflow: clip;
& > span {
transition: transform .3s ease;
cursor: pointer;
&:not(:hover) {
transform: translateY(50%);
}
}
}
}
Ejemplo de animación de palabras divididas
En este ejemplo de animación, utilizo CSS @keyframes
de nuevo para crear una animación infinita escalonada en un párrafo de texto normal.
[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;
}
}
Conclusión
Ahora que sabes cómo lo hice, ¿cómo lo harías? 🙂
Diversifiquemos nuestros enfoques y aprendamos todas las formas de desarrollar en la Web. Crea una Codepen o aloja tu propia demostración, twittea con ella y la agregaré a la sección de remixes de la comunidad a continuación.
Fuente
Más inspiración y demostraciones
Remixes de la comunidad
- Componente web
<text-hover>
de gnehcwu en CodeSandbox