Uma visão geral básica de como criar animações com letras divididas e animações de palavras.
Nesta postagem, quero compartilhar ideias sobre maneiras de resolver animações de texto dividido e interações para a Web que são mínimas, acessíveis e funcionam em vários navegadores. Teste a demonstração.
Se preferir vídeo, aqui está uma versão do YouTube desta postagem:
Visão geral
Animações de texto dividido podem ser incríveis. Não vamos falar muito sobre o potencial da animação nesta postagem, mas essa é uma base de base. O objetivo é animar progressivamente. O texto precisa ser legível por padrão, com a animação criada na parte de cima. Os efeitos de movimento de texto dividido podem ficar extravagantes e possivelmente disruptivos. Portanto, só manipularemos o HTML ou aplicaremos estilos de movimento se o usuário concordar com os movimentos.
Esta é uma visão geral do fluxo de trabalho e dos resultados:
- Prepare variáveis condicionais de movimento reduzida para CSS e JS.
- Prepare os utilitários de texto divididos no JavaScript.
- Orquestre os condicionais e utilitários no carregamento da página.
- Escreva transições e animações CSS para letras e palavras (a parte mais ousada!).
Esta é uma visualização dos resultados condicionais que queremos:
Se um usuário preferir movimento reduzido, deixaremos o documento HTML em paz e não faremos nenhuma animação. Se o movimento estiver OK, vamos dividi-lo em partes. Esta é uma visualização do HTML depois que o JavaScript dividiu o texto por letra.
Como preparar condicionais de movimento
A consulta de mídia @media
(prefers-reduced-motion: reduce)
convenientemente disponível será usada em CSS e
JavaScript neste projeto. Essa consulta de mídia é nossa principal condicional
para decidir se dividir o texto ou não. A consulta de mídia CSS será usada para reter
transições e animações, enquanto a consulta de mídia JavaScript será usada para
reter a manipulação HTML.
Como preparar a condicional do CSS
Usei PostCSS para ativar a sintaxe das Consultas de mídia nível 5, em que posso armazenar um booleano de consulta de mídia em uma variável:
@custom-media --motionOK (prefers-reduced-motion: no-preference);
Como preparar a condicional JS
Em JavaScript, o navegador oferece uma maneira de verificar consultas de mídia. Usei a desestruturação para extrair e renomear o resultado booleano da verificação de consulta de mídia:
const {matches:motionOK} = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
)
Posso testar o motionOK
e só mudar o documento se o usuário não
pedir a redução do movimento.
if (motionOK) {
// document split manipulations
}
Posso verificar o mesmo valor usando PostCSS para ativar a sintaxe @nest
do
Resumo de aninhamento 1. Isso me permite
armazenar toda a lógica sobre a animação e seus requisitos de estilo para os
pais e filhos em um só lugar:
letter-animation {
@media (--motionOK) {
/* animation styles */
}
}
Com a propriedade personalizada PostCSS e um booleano JavaScript, estamos prontos para fazer upgrade condicional do efeito. Isso nos leva à próxima seção, em que vou dividir o JavaScript para transformar strings em elementos.
Como dividir o texto
Letras de texto, palavras, linhas etc. não podem ser animadas individualmente com CSS ou JS. Para conseguir o efeito, precisamos de caixas. Se quisermos animar cada letra, então cada letra precisa ser um elemento. Se quisermos animar cada palavra, cada palavra precisa ser um elemento.
- Criar funções utilitárias JavaScript para dividir strings em elementos
- Orquestrar o uso desses utilitários
Função utilitária de divisão de letras
Um bom lugar para começar é com uma função que usa uma string e retorna cada letra de uma matriz.
export const byLetter = text =>
[...text].map(span)
A sintaxe distribuição do ES6 realmente ajudou a tornar isso uma tarefa rápida.
Função utilitária de divisão de palavras
Semelhante à divisão de letras, essa função usa uma string e retorna cada palavra em uma matriz.
export const byWord = text =>
text.split(' ').map(span)
O método
split()
em strings JavaScript permite especificar quais caracteres serão divididos.
Passei um espaço vazio, indicando uma divisão entre as palavras.
Como fazer caixas com função utilitária
O efeito exige caixas para cada letra. Observe nessas funções que
map()
está sendo chamado com uma função span()
. Veja a função span()
.
const span = (text, index) => {
const node = document.createElement('span')
node.textContent = text
node.style.setProperty('--index', index)
return node
}
É importante observar que uma propriedade personalizada chamada --index
está sendo definida com
a posição da matriz. Ter as caixas para as animações de letras é ótimo, mas
ter um índice para usar no CSS é uma adição aparentemente pequena com um grande impacto.
O mais notável nesse grande impacto é
esmagador.
Podemos usar --index
como uma forma de deslocar as animações para uma aparência
escalonada.
Conclusão sobre serviços públicos
O módulo splitting.js
foi concluído:
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)
Em seguida, está importando e usando essas funções byLetter()
e byWord()
.
Orquestração dividida
Com os utilitários de divisão prontos para uso, unir tudo significa:
- Como descobrir quais elementos dividir
- Dividindo-os e substituindo o texto por HTML
Depois disso, o CSS assume o controle e anima os elementos / caixas.
Encontrar elementos
Escolhi usar atributos e valores para armazenar informações sobre a animação
desejada e como dividir o texto. Gostei de colocar essas opções
declarativas no HTML. O atributo split-by
é usado em JavaScript para encontrar
elementos e criar caixas para letras ou palavras. O atributo
letter-animation
ou word-animation
é usado no CSS para direcionar os filhos
de elementos e aplicar transformações e animações.
Aqui está um exemplo de HTML que demonstra os dois atributos:
<h1 split-by="letter" letter-animation="breath">animated letters</h1>
<h1 split-by="word" word-animation="trampoline">hover the words</h1>
Encontrar elementos do JavaScript
Usei a sintaxe do seletor de CSS para presença de atributos e reunir a lista de elementos que querem dividir o texto:
const splitTargets = document.querySelectorAll('[split-by]')
Encontrar elementos de CSS
Também usei o seletor de presença de atributo no CSS para dar a todas as animações de letras os mesmos estilos de base. Mais tarde, vamos usar o valor do atributo para adicionar estilos mais específicos e criar um efeito.
letter-animation {
@media (--motionOK) {
/* animation styles */
}
}
Dividir o texto no lugar
Para cada um dos destinos de divisão encontrados em JavaScript, dividiremos o texto
com base no valor do atributo e mapearemos cada string para um <span>
. Em seguida,
podemos substituir o texto do elemento pelas caixas que fizemos:
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)
}
})
Conclusão da orquestração
index.js
concluído:
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)
})
}
O JavaScript pode ser lido no seguinte inglês:
- Importe algumas funções utilitárias auxiliares.
- Confira se o movimento está adequado para o usuário. Caso contrário, não faça nada.
- Para cada elemento que quer ser dividido.
- Divida-os com base em como eles querem fazer isso.
- Substituir o texto por elementos.
Como dividir animações e transições
A manipulação de documentos de divisão acima desbloqueou uma infinidade de possíveis animações e efeitos com CSS ou JavaScript. Há alguns links na parte inferior deste artigo para ajudar a inspirar seu potencial de divisão.
Hora de mostrar do que você é capaz! vou compartilhar quatro animações e transições orientadas por CSS. 🤓
Letras divididas
Como base para os efeitos de letras divididas, achei o CSS a seguir útil. Coloquei todas as transições e animações por trás da consulta de mídia de movimento e,
em seguida, forneço a cada nova letra filha span
uma propriedade de exibição e um estilo para o que
fazer com os espaços em branco:
[letter-animation] > span {
display: inline-block;
white-space: break-spaces;
}
O estilo dos espaços em branco é importante para que os períodos, que são apenas um espaço, não sejam recolhidos pelo mecanismo de layout. Agora vamos para a diversão com estado.
Exemplo de letras divididas de transição
Este exemplo usa transições CSS para o efeito de texto dividido. Com as transições, precisamos de estados para a animação do mecanismo. Eu escolhi três estados: não passar o cursor, passar o cursor na frase, passar o cursor sobre uma letra.
Quando o usuário passa o cursor sobre a frase (também chamada de contêiner), redimensiono todos os filhos como se o usuário os tivesse afastado. Então, quando o usuário passa o cursor sobre uma letra, eu a levo para frente.
@media (--motionOK) {
[letter-animation="hover"] {
&:hover > span {
transform: scale(.75);
}
& > span {
transition: transform .3s ease;
cursor: pointer;
&:hover {
transform: scale(1.25);
}
}
}
}
Exemplo de animação de letras divididas
Este exemplo usa uma animação @keyframe
predefinida para animar infinitamente cada
letra e aproveita o índice de propriedade personalizada inline para criar um efeito
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 palavras
O Flexbox funcionou como um tipo de contêiner nesses exemplos, aproveitando bem
a unidade ch
como um comprimento de intervalo saudável.
word-animation {
display: inline-flex;
flex-wrap: wrap;
gap: 1ch;
}
Exemplo de palavras divididas de transição
Neste exemplo de transição, vou usar o recurso de passar o cursor novamente. Como o efeito inicialmente oculta o conteúdo até passar o cursor, garantimos que a interação e os estilos sejam aplicados apenas se o dispositivo puder passar o cursor.
@media (hover) {
[word-animation="hover"] {
overflow: hidden;
overflow: clip;
& > span {
transition: transform .3s ease;
cursor: pointer;
&:not(:hover) {
transform: translateY(50%);
}
}
}
}
Exemplo de animação de palavras divididas
Neste exemplo de animação, uso o CSS @keyframes
novamente para criar uma animação
infinita escalonada em um parágrafo normal de texto.
[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;
}
}
Conclusão
Agora que você sabe como eu fiz isso, como você iria?! 🙂
Vamos diversificar nossas abordagens e aprender todas as maneiras de criar na Web. Crie um Codepen ou apresente sua própria demonstração, envie um tweet para mim e vou adicioná-la à seção "Remixes da comunidade" abaixo.
Origem
Mais demonstrações e inspiração
Remixes da comunidade
- Componente da Web
<text-hover>
por gnehcwu no CodeSandbox