Ringkasan dasar tentang cara membuat animasi kata dan huruf terpisah.
Dalam postingan ini, saya ingin membagikan pemikiran tentang cara menyelesaikan animasi dan interaksi teks terpisah untuk web yang minimal, mudah diakses, dan berfungsi di seluruh browser. Coba demo.
Jika Anda lebih suka menonton video, berikut versi YouTube untuk postingan ini:
Ringkasan
Animasi teks terpisah bisa sangat menarik. Kita tidak akan membahas sebagian besar potensi animasi dalam postingan ini, tetapi hal ini akan memberikan fondasi untuk membangunnya. Tujuannya adalah untuk menganimasikan secara progresif. Teks harus dapat dibaca secara default, dengan animasi yang dibuat di atasnya. Efek gerakan teks terpisah dapat menjadi berlebihan dan berpotensi mengganggu, jadi kita hanya akan memanipulasi HTML, atau menerapkan gaya gerakan jika pengguna tidak keberatan dengan gerakan.
Berikut adalah ringkasan umum alur kerja dan hasilnya:
- Siapkan variabel kondisional gerakan yang dikurangi untuk CSS dan JS.
- Siapkan utilitas teks terpisah di JavaScript.
- Atur kondisional dan utilitas saat pemuatan halaman.
- Tulis transisi dan animasi CSS untuk huruf dan kata (bagian yang keren!).
Berikut adalah pratinjau hasil bersyarat yang kita inginkan:
Jika pengguna memilih gerakan yang dikurangi, kita akan membiarkan dokumen HTML dan tidak melakukan animasi. Jika gerakannya sudah bagus, kita lanjutkan dengan memotongnya menjadi beberapa bagian. Berikut adalah pratinjau HTML setelah JavaScript memisahkan 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 kami untuk
memutuskan apakah akan memisahkan teks atau tidak. Kueri media CSS akan digunakan untuk menahan
transisi dan animasi, sedangkan kueri media JavaScript akan digunakan untuk
menahan manipulasi HTML.
Menyiapkan kondisional CSS
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
Di 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 menggunakan PostCSS untuk mengaktifkan sintaksis @nest
dari
Draf Nest 1. Hal ini memungkinkan saya
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. Hal ini akan membawa kita ke bagian berikutnya tempat saya memerinci JavaScript untuk mengubah string menjadi elemen.
Memisahkan Teks
Huruf teks, kata, baris, dll. tidak dapat dianimasikan satu per satu dengan CSS atau JS. Untuk mencapai efek ini, kita membutuhkan kotak. Jika kita ingin menganimasikan setiap huruf, setiap huruf harus menjadi elemen. Jika kita ingin menganimasikan setiap kata, setiap kata harus berupa elemen.
- Membuat fungsi utilitas JavaScript untuk membagi string menjadi elemen
- Mengatur penggunaan utilitas ini
Fungsi utilitas pemisahan 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 mempermudah tugas tersebut.
Fungsi utilitas kata pemisahan
Serupa 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 menentukan karakter yang akan dipotong.
Saya melewati ruang kosong, yang menunjukkan pemisahan di antara kata.
Membuat fungsi utilitas kotak
Efek ini 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 kustom yang disebut --index
ditetapkan dengan
posisi array. Memiliki kotak untuk animasi huruf memang bagus, tetapi
memiliki indeks untuk digunakan dalam CSS merupakan tambahan yang kecil dengan dampak yang besar.
Yang paling terkenal dalam dampak besar ini adalah
mengejutkan.
Kita dapat menggunakan --index
sebagai cara untuk mengimbangi animasi agar tampilannya
bertahap.
Kesimpulan utilitas
Modul splitting.js
dalam penyelesaian:
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)
Berikutnya adalah mengimpor dan menggunakan fungsi byLetter()
dan byWord()
ini.
Orkestrasi terpisah
Dengan utilitas pemisahan yang siap digunakan, menggabungkan semuanya berarti:
- Menemukan elemen yang akan dibagi
- Memisahkan dan mengganti teks dengan HTML
Setelah itu, CSS akan mengambil alih dan menganimasikan elemen / kotak.
Menemukan Elemen
Saya memilih untuk menggunakan atribut dan nilai untuk menyimpan informasi tentang animasi
yang diinginkan dan cara memisahkan teks. Saya suka memasukkan 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 serta animasi.
Berikut adalah contoh HTML yang menunjukkan kedua atribut tersebut:
<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 teksnya dibagi:
const splitTargets = document.querySelectorAll('[split-by]')
Menemukan elemen dari CSS
Saya juga menggunakan pemilih kehadiran atribut di CSS untuk memberi semua animasi huruf gaya dasar yang sama. Nanti, kita akan menggunakan nilai atribut untuk menambahkan gaya yang lebih spesifik untuk mencapai suatu efek.
letter-animation {
@media (--motionOK) {
/* animation styles */
}
}
Memisahkan teks di tempatnya
Untuk setiap target pemisahan yang ditemukan di JavaScript, kita akan membagi teksnya
berdasarkan nilai atribut dan memetakan setiap string ke <span>
. Kemudian, kita dapat
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
dalam penyelesaian:
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 sudah baik untuk pengguna ini, jika tidak, jangan lakukan apa pun.
- Untuk setiap elemen yang ingin dipisah.
- Pisahkan berdasarkan cara yang diinginkan.
- Mengganti teks dengan elemen.
Memisahkan animasi dan transisi
Manipulasi dokumen pemisahan di atas baru saja membuka banyak potensi animasi dan efek 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. 🤓
Memisahkan huruf
Sebagai dasar untuk efek huruf terpisah, saya merasa CSS berikut
berguna. Saya menempatkan semua transisi dan animasi di balik kueri media gerakan, lalu
memberi setiap huruf turunan baru span
properti tampilan beserta gaya untuk
apa yang harus dilakukan dengan spasi kosong:
[letter-animation] > span {
display: inline-block;
white-space: break-spaces;
}
Gaya spasi kosong penting agar span yang hanya berupa spasi, tidak diciutkan oleh mesin tata letak. Sekarang, kita akan membahas hal-hal menyenangkan yang bersifat stateful.
Contoh huruf terpisah transisi
Contoh ini menggunakan transisi CSS ke efek teks terpisah. Dengan transisi, kita memerlukan status agar mesin dapat menganimasikannya, dan saya memilih tiga status: tidak mengarahkan kursor, mengarahkan kursor dalam kalimat, mengarahkan kursor pada huruf.
Saat pengguna mengarahkan kursor ke kalimat, alias penampung, saya menskalakan kembali semua turunan seolah-olah pengguna mendorongnya lebih jauh. Kemudian, saat pengguna mengarahkan kursor ke 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);
}
}
}
}
Contoh animasi 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
bertingkat.
@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;
}
}
Memisahkan kata
Flexbox berfungsi sebagai jenis penampung untuk saya di sini dalam contoh ini, yang memanfaatkan unit ch
dengan baik sebagai panjang celah yang baik.
word-animation {
display: inline-flex;
flex-wrap: wrap;
gap: 1ch;
}
Contoh kata pemisah transisi
Dalam contoh transisi ini, saya menggunakan kursor lagi. Karena efek awalnya menyembunyikan konten hingga mengarahkan 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 kata terpisah
Dalam contoh animasi ini, saya menggunakan @keyframes
CSS lagi untuk membuat animasi
tanpa batas secara bergiliran pada paragraf teks reguler.
[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
Setelah Anda tahu cara saya melakukannya, bagaimana Anda melakukannya? 🙂
Mari kita diversifikasi pendekatan dan pelajari semua cara untuk mem-build di web. Buat Codepen atau hosting demo Anda sendiri, kirim tweet kepada saya, dan saya akan menambahkannya ke bagian Remix komunitas di bawah ini.
Sumber
Demo dan inspirasi lainnya
Remix komunitas
- Komponen web
<text-hover>
oleh gnehcwu di CodeSandbox