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 video, berikut versi YouTube dari postingan ini:
Ringkasan
Animasi teks terpisah bisa sangat menarik. Kita hanya akan membahas sedikit potensi animasi dalam postingan ini, tetapi hal ini memberikan dasar untuk membangun animasi. 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
Nesting Draft 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 untuk mengupgrade efek secara kondisional. Kita akan sampai ke bagian berikutnya di mana saya menguraikan JavaScript untuk mengubah {i>string<i} menjadi elemen.
Memisahkan Teks
Huruf teks, kata, baris, dll. tidak dapat dianimasikan satu per satu dengan CSS atau JS. Untuk mendapatkan efek ini, kita memerlukan kotak. Jika kita ingin menganimasikan setiap huruf, setiap huruf harus berupa elemen. Jika kita ingin menganimasikan setiap kata, maka setiap kata harus menjadi elemen.
- Membuat fungsi utilitas JavaScript untuk memisahkan string menjadi elemen
- Mengatur penggunaan utilitas ini
Fungsi utilitas pemisahan huruf
Tempat yang menyenangkan untuk memulai adalah dengan 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 pemisahan kata
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 mana yang akan dibagi.
Saya melewati ruang kosong, yang menunjukkan pemisahan di antara kata.
Membuat fungsi utilitas box
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 itu bagus, tetapi
memiliki indeks untuk digunakan di CSS adalah tambahan yang tampaknya kecil dengan dampak besar.
Yang paling penting 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 terpisah yang siap digunakan, menyatukan semuanya berarti:
- Menemukan elemen yang akan dibagi
- Memisahkan dan mengganti teks dengan HTML
Setelah itu, CSS akan mengambil alih dan akan 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 memberikan gaya dasar yang sama ke semua animasi huruf. Nanti, kita akan menggunakan nilai atribut untuk menambahkan gaya yang lebih spesifik untuk mendapatkan efek.
letter-animation {
@media (--motionOK) {
/* animation styles */
}
}
Memisahkan teks di tempat
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 proses:
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.
- Ganti 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 yang didorong 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 untuk dianimasikan oleh mesin, dan saya memilih tiga status: tanpa kursor, arahkan kursor dalam kalimat, arahkan kursor ke 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;
}
}
Pisahkan 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 terpisah 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%);
}
}
}
}
Contoh animasi kata terpisah
Dalam contoh animasi ini, saya menggunakan CSS @keyframes
lagi untuk membuat animasi
tanpa batas yang berurutan 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 setelah Anda tahu cara saya melakukannya, bagaimana Anda akan melakukannya?! 🙂
Mari kita diversifikasi pendekatan kami dan mempelajari semua cara untuk membangun di web. Buat Codepen atau host demo Anda sendiri, tweet ke saya, 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