Ikhtisar dasar tentang cara membuat animasi huruf dan kata terpisah.
Dalam postingan ini, saya ingin berbagi pemikiran tentang cara memecahkan interaksi dan animasi teks terpisah untuk web yang minimal, mudah diakses, dan berfungsi di berbagai browser. Coba demonya.
Jika Anda lebih suka video, berikut versi YouTube postingan ini:
Ringkasan
Animasi {i>split text<i} bisa menjadi luar biasa. Kita hampir tidak akan membahas potensi animasi dalam postingan ini, tetapi hal ini memberikan fondasi untuk membangun. Tujuannya adalah untuk menganimasikan secara progresif. Teks harus dapat dibaca secara default, dengan animasi di atasnya. Efek gerakan teks terpisah bisa sangat luar biasa dan berpotensi mengganggu, jadi kita hanya akan memanipulasi HTML, atau menerapkan gaya gerakan jika pengguna mengizinkan gerakan.
Berikut ini ringkasan umum alur kerja dan hasilnya:
- Menyiapkan variabel kondisional gerakan yang dikurangi untuk CSS dan JS.
- Menyiapkan utilitas teks terpisah di JavaScript.
- Orkestrasi kondisional dan utilitas pada pemuatan halaman.
- Tulis transisi dan animasi CSS untuk huruf dan kata (bagian ujung!).
Berikut adalah pratinjau hasil kondisional yang akan kita cari:
Jika pengguna lebih memilih gerakan yang lebih kecil, biarkan dokumen HTML itu sendiri dan tidak melakukan animasi. Jika ada gerakan yang wajar, kita akan melanjutkan dan membaginya menjadi beberapa bagian. Berikut adalah pratinjau HTML setelah JavaScript membagi teks menurut huruf.
Menyiapkan kondisional gerakan
Kueri media @media
(prefers-reduced-motion: reduce)
yang tersedia dengan mudah akan digunakan dari CSS dan
JavaScript dalam project ini. Kueri media ini adalah kondisional utama untuk
memutuskan membagi teks atau tidak. Kueri media CSS akan digunakan untuk menahan transisi dan animasi, sedangkan kueri media JavaScript akan digunakan untuk menahan manipulasi HTML.
Menyiapkan CSS kondisional
Saya menggunakan PostCSS untuk mengaktifkan sintaksis Kueri Media Level 5, tempat saya dapat menyimpan boolean kueri media ke dalam variabel:
@custom-media --motionOK (prefers-reduced-motion: no-preference);
Menyiapkan kondisional JS
Dalam JavaScript, browser menyediakan cara untuk memeriksa kueri media. Saya menggunakan destrukturisasi untuk mengekstrak dan mengganti nama hasil boolean dari pemeriksaan kueri media:
const {matches:motionOK} = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
)
Kemudian, saya dapat menguji motionOK
, dan hanya mengubah dokumen jika pengguna belum
meminta untuk mengurangi gerakan.
if (motionOK) {
// document split manipulations
}
Saya dapat memeriksa nilai yang sama dengan menggunakan PostCSS untuk mengaktifkan sintaksis @nest
dari
Nesting Draft 1. Dengan begitu, saya dapat
menyimpan semua logika tentang animasi dan persyaratan gayanya untuk
induk dan turunan, di satu tempat:
letter-animation {
@media (--motionOK) {
/* animation styles */
}
}
Dengan properti kustom PostCSS dan boolean JavaScript, kita siap mengupgrade efek secara bersyarat. Kita akan masuk ke bagian berikutnya di mana saya memecah JavaScript untuk mengubah {i>string<i} menjadi elemen.
Memisahkan Teks
Huruf teks, kata, garis, dll., tidak dapat dianimasikan satu per satu dengan CSS atau JS. Untuk mencapai efek tersebut, kita memerlukan kotak. Jika kita ingin menganimasikan setiap huruf, maka setiap huruf perlu menjadi elemen. Jika kita ingin menganimasikan setiap kata, maka setiap kata harus menjadi elemen.
- Membuat fungsi utilitas JavaScript untuk memisahkan string menjadi elemen
- Orkestrasi penggunaan utilitas ini
Fungsi utilitas memisahkan huruf
Tempat yang menyenangkan untuk memulai adalah fungsi yang mengambil string dan menampilkan setiap huruf dalam array.
export const byLetter = text =>
[...text].map(span)
Sintaksis spread dari ES6 benar-benar membantu menjadikan tugas tersebut cepat.
Fungsi utilitas memisahkan kata
Mirip dengan memisahkan huruf, fungsi ini mengambil string dan menampilkan setiap kata dalam array.
export const byWord = text =>
text.split(' ').map(span)
Metode
split()
pada string JavaScript memungkinkan kita untuk menentukan karakter mana yang akan diiris.
Saya meneruskan spasi kosong, yang menunjukkan pemisahan antarkata.
Menjadikan kotak berfungsi sebagai utilitas
Efeknya memerlukan kotak untuk setiap huruf, dan kita melihat dalam fungsi tersebut, bahwa
map()
dipanggil dengan fungsi span()
. Berikut adalah fungsi span()
.
const span = (text, index) => {
const node = document.createElement('span')
node.textContent = text
node.style.setProperty('--index', index)
return node
}
Penting untuk diperhatikan bahwa properti khusus yang disebut --index
sedang disetel dengan posisi array. Memiliki kotak untuk animasi huruf memang bagus, tetapi
memiliki indeks untuk digunakan dalam CSS merupakan tambahan yang terlihat kecil dengan dampak yang besar.
Yang paling terlihat dalam dampak besar ini adalah
menakjubkan.
Kita akan dapat menggunakan --index
sebagai cara mengimbangi animasi untuk tampilan
bertahap.
Kesimpulan utilitas
Modul splitting.js
yang telah selesai:
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)
Selanjutnya adalah mengimpor dan menggunakan fungsi byLetter()
dan byWord()
ini.
Orkestrasi terpisah
Setelah beberapa utilitas yang terpisah siap digunakan, menyatukan semuanya berarti:
- Menemukan elemen yang akan dipisahkan
- Memisahkan dan mengganti teks dengan HTML
Setelah itu, CSS akan mengambil alih dan akan menganimasikan elemen / kotak.
Elemen Temuan
Saya memilih menggunakan atribut dan nilai untuk menyimpan
informasi tentang animasi yang diinginkan dan cara memisahkan teks. Saya suka menempatkan opsi
deklaratif ini ke dalam HTML. Atribut split-by
digunakan dari JavaScript, untuk menemukan
elemen dan membuat kotak untuk huruf atau kata. Atribut
letter-animation
atau word-animation
digunakan dari CSS, untuk menargetkan turunan
elemen dan menerapkan transformasi dan animasi.
Berikut adalah contoh HTML yang menunjukkan kedua atribut:
<h1 split-by="letter" letter-animation="breath">animated letters</h1>
<h1 split-by="word" word-animation="trampoline">hover the words</h1>
Menemukan elemen dari JavaScript
Saya menggunakan sintaksis pemilih CSS untuk kehadiran atribut guna mengumpulkan daftar elemen yang ingin memisahkan teks:
const splitTargets = document.querySelectorAll('[split-by]')
Menemukan elemen dari CSS
Saya juga menggunakan pemilih kehadiran atribut dalam CSS untuk memberi semua animasi huruf gaya dasar yang sama. Nanti, kita akan menggunakan nilai atribut untuk menambahkan gaya yang lebih spesifik guna mencapai efek.
letter-animation {
@media (--motionOK) {
/* animation styles */
}
}
Memisahkan teks di tempat
Untuk setiap target pemisahan yang ditemukan di JavaScript, kita akan memisahkan teksnya
berdasarkan nilai atribut dan memetakan setiap string ke <span>
. Kemudian kita bisa
mengganti teks elemen dengan kotak yang kita buat:
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)
}
})
Kesimpulan orkestrasi
index.js
selesai:
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)
})
}
JavaScript dapat dibaca dalam bahasa Inggris berikut:
- Mengimpor beberapa fungsi utilitas bantuan.
- Periksa apakah gerakan diperbolehkan untuk pengguna ini, jika tidak melakukan apa pun.
- Untuk setiap elemen yang ingin dipisahkan.
- Membaginya berdasarkan cara pemisahannya.
- Mengganti teks dengan elemen.
Memisahkan animasi dan transisi
Manipulasi dokumen pemisah di atas baru saja membuka banyak animasi dan efek potensial dengan CSS atau JavaScript. Ada beberapa link di bagian bawah artikel ini untuk membantu menginspirasi potensi pemisahan Anda.
Saatnya menunjukkan apa yang dapat Anda lakukan dengan fitur ini! Saya akan membagikan 4 animasi dan transisi berbasis CSS. 🤓
Pisahkan huruf
Sebagai dasar untuk efek huruf terpisah, menurut saya CSS berikut sangat membantu. Saya menempatkan semua transisi dan animasi di belakang kueri media gerakan, lalu memberi setiap huruf turunan baru span
sebuah properti tampilan serta gaya untuk apa yang harus dilakukan dengan ruang kosong:
[letter-animation] > span {
display: inline-block;
white-space: break-spaces;
}
Gaya ruang putih penting agar span yang hanya berupa spasi, tidak diciutkan oleh mesin tata letak. Sekarang, kita lanjutkan ke hal-hal yang menyenangkan.
Contoh huruf terpisah transisi
Contoh ini menggunakan transisi CSS ke efek teks terpisah. Dengan transisi, kami memerlukan status agar mesin dapat dianimasikan, dan saya memilih tiga status: tanpa mengarahkan kursor, mengarahkan kursor pada kalimat, mengarahkan kursor pada huruf.
Saat pengguna mengarahkan kursor ke kalimat, alias container, saya memperkecil skala semua turunan seolah-olah pengguna mendorongnya lebih jauh. Kemudian, saat pengguna menggeser sebuah huruf, saya akan menampilkannya.
@media (--motionOK) {
[letter-animation="hover"] {
&:hover > span {
transform: scale(.75);
}
& > span {
transition: transform .3s ease;
cursor: pointer;
&:hover {
transform: scale(1.25);
}
}
}
}
Menganimasikan contoh huruf terpisah
Contoh ini menggunakan animasi @keyframe
yang telah ditentukan untuk menganimasikan setiap
huruf tanpa batas, dan memanfaatkan indeks properti kustom inline untuk membuat efek
bertahap.
@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;
}
}
Pisahkan kata
Dalam contoh-contoh ini, Flexbox berfungsi sebagai jenis container,
memanfaatkan unit ch
dengan baik sebagai panjang celah yang sehat.
word-animation {
display: inline-flex;
flex-wrap: wrap;
gap: 1ch;
}
Contoh kata terpisah transisi
Dalam contoh transisi ini, saya menggunakan pengarahan kursor lagi. Karena efek awalnya menyembunyikan konten hingga pengarahan kursor, saya memastikan bahwa interaksi dan gaya hanya diterapkan jika perangkat memiliki kemampuan untuk mengarahkan kursor.
@media (hover) {
[word-animation="hover"] {
overflow: hidden;
overflow: clip;
& > span {
transition: transform .3s ease;
cursor: pointer;
&:not(:hover) {
transform: translateY(50%);
}
}
}
}
Menganimasikan contoh pemisahan kata
Dalam contoh animasi ini, saya menggunakan CSS @keyframes
lagi untuk membuat animasi tanpa batas yang bertahap pada paragraf teks biasa.
[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;
}
}
Kesimpulan
Sekarang Anda tahu bagaimana saya melakukannya, bagaimana Anda akan?! 🙂
Mari lakukan diversifikasi pendekatan dan pelajari semua cara untuk membangun di web. Buat Codepen atau host demo Anda sendiri, kirim tweet, dan saya akan menambahkannya ke bagian remix Komunitas di bawah.
Sumber
Demo dan inspirasi lainnya
Remix komunitas
- Komponen web
<text-hover>
oleh gnehcwu di CodeSandbox