Cara Membuat Efek Ketik Otomatis dengan JavaScript
Efek ketik otomatis membuat teks muncul huruf demi huruf seperti sedang diketik. Panduan ini membangunnya dari nol dengan JavaScript dan CSS, plus penanganan kursor berkedip.
Efek ketik otomatis sering dipakai di halaman landing, portofolio, atau hero section untuk menampilkan beberapa kalimat bergantian. Teks muncul huruf demi huruf seolah sedang diketik, lalu dihapus sebelum kalimat berikutnya tampil. Membuatnya tidak butuh library tambahan, cukup JavaScript dasar dan sedikit CSS.
Menyiapkan Struktur HTML
Mulai dari wadah teks yang kosong, satu elemen untuk teks yang diketik dan satu elemen untuk kursor. Kursor dipisah supaya mudah diberi animasi berkedip lewat CSS.
<div class="typed" aria-live="polite">
<span id="typed-text"></span><span class="cursor">|</span>
</div>
Atribut aria-live="polite" membuat pembaca layar membacakan teks yang berubah tanpa memotong kalimat lain yang sedang dibaca. Karakter pipa dipakai sebagai kursor karena cukup satu karakter, tidak perlu elemen tambahan.
Menulis Logika Pengetikan
Inti efeknya: satu fungsi memotong teks satu karakter, menampilkannya, lalu memanggil dirinya lagi setelah jeda. Variabel penanda menyimpan posisi karakter yang sedang diketik.
const el = document.getElementById('typed-text');
const frasa = ['Web itu cepat.', 'Kode itu jelas.', 'Animasi itu halus.'];
let indexFrasa = 0;
let indexHuruf = 0;
let menghapus = false;
function ketik() {
const teks = frasa[indexFrasa];
el.textContent = teks.slice(0, indexHuruf);
if (!menghapus) {
if (indexHuruf < teks.length) {
indexHuruf++;
setTimeout(ketik, 90);
return;
}
menghapus = true;
setTimeout(ketik, 1200);
return;
}
if (indexHuruf > 0) {
indexHuruf--;
setTimeout(ketik, 45);
return;
}
menghapus = false;
indexFrasa = (indexFrasa + 1) % frasa.length;
setTimeout(ketik, 300);
}
ketik();
Kecepatan menghapus dibuat dua kali lebih cepat dari mengetik. Pengunjung sudah membaca kalimatnya, jadi penghapusan tidak perlu lambat. Jeda 1200 ms sebelum menghapus memberi waktu mata berhenti sejenak di akhir kalimat.
Pemanggilan rekursif lewat setTimeout dipakai di sini karena jeda antarhuruf tidak seragam dan tidak perlu disinkronkan ke frame layar. Kalau kamu butuh animasi yang bergerak tiap frame, seperti kursor mengikuti posisi teks, pertimbangkan memilih antara setTimeout, setInterval, dan requestAnimationFrame.
Menghias dengan CSS: Kursor Berkedip
Kursor cukup diberi animasi opacity dua keadaan supaya terlihat berkedip. Jangan pakai display karena bisa menggeser tata letak.
.typed {
font-family: monospace;
font-size: 1.5rem;
min-height: 2.2rem;
}
.cursor {
display: inline-block;
margin-left: 2px;
animation: kedip 1s steps(1) infinite;
}
@keyframes kedip {
50% { opacity: 0; }
}
min-height mencegah wadah mengempis saat teks habis dihapus. Tanpa itu, elemen di bawahnya melompat naik setiap kali kalimat kembali kosong. steps(1) membuat perpindahan opacity terjadi langsung, bukan berangsur, sehingga mirip kursor sungguhan.
Menyisipkan Teks dengan Aman ke Halaman
Contoh di atas memakai textContent, jadi aman untuk teks yang sudah dipercaya. Kalau kalimatmu datang dari input pengguna atau API, jangan ganti ke innerHTML mentah. Pisahkan wadah teks dan kursor seperti pada HTML awal, lalu perbarui hanya teks di dalam span-nya. Cara memperbarui DOM tanpa merusak elemen lain dibahas di cara menampilkan data ke halaman web dengan JavaScript.
Mengatur Ulang saat Kalimat Berganti
Saat indexFrasa bertambah, jangan lupa mereset atau membiarkan indexHuruf kembali dari nol. Di kode di atas, penghapusan mengembalikan indexHuruf ke 0 sebelum frasa diganti, jadi tidak ada karakter sisa. Kalau kamu menambahkan frasa secara dinamis lewat array baru, pastikan indexFrasa dihitung ulang dengan % frasa.length supaya tidak menunjuk elemen yang tidak ada.
Menghentikan Animasi saat Tab Tidak Aktif
Halaman yang tidak dilihat tetap menjalankan setTimeout dan menghabiskan baterai perangkat. Tambahkan pemeriksaan document.hidden di awal fungsi, lalu lanjutkan saat tab kembali terlihat.
function ketik() {
if (document.hidden) {
setTimeout(ketik, 500);
return;
}
// lanjutkan logika pengetikan
}
Pendekatan ini lebih sederhana daripada membatalkan timer dengan clearTimeout dan memulainya ulang. Cukup buat fungsi berhenti sejenak lalu memeriksa lagi. Animasi juga tidak melompat jauh di latar belakang.
Menyesuaikan Preferensi Pengguna
Sebagian orang memilih mengurangi animasi di sistem operasinya. Hormati pilihan itu lewat media query prefers-reduced-motion. Kalau aktif, tampilkan langsung frasa pertama tanpa efek ketik dan hentikan animasi kursor.
const kurangiGerak = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (kurangiGerak) {
el.textContent = frasa[0];
document.querySelector('.cursor').style.display = 'none';
} else {
ketik();
}
Pemeriksaan ini dilakukan sekali di awal. Kalau pengguna mengubah preferensi saat halaman sudah terbuka, efeknya baru berlaku setelah muat ulang. Untuk kebutuhan blog dan portofolio, itu cukup dan tidak menambah kompleksitas.
Merapikan Kode agar Mudah Diubah
Setelah semuanya jalan, kumpulkan angka jeda di satu objek supaya kamu tidak perlu menyisir seluruh fungsi saat ingin mempercepat atau memperlambat animasi.
- kecepatanKetik: jeda antarhuruf saat mengetik, misalnya 90 ms.
- kecepatanHapus: jeda antarhuruf saat menghapus, biasanya setengah dari kecepatan ketik.
- jedaPenuh: waktu berhenti setelah satu frasa selesai.
- jedaGanti: jeda sebelum frasa berikutnya mulai diketik.
Dengan cara ini, mengubah ritme animasi cukup mengedit satu tempat. Simpan objek pengaturan di atas fungsi ketik dan rujuk nilainya lewat properti, bukan variabel terpisah.
Ringkasan
Efek ketik otomatis dibangun dari satu fungsi rekursif yang memotong string per karakter, ditambah kursor yang dianimasikan lewat CSS. Struktur HTML yang memisahkan teks dan kursor memudahkan pembaruan konten, sementara pemeriksaan document.hidden dan prefers-reduced-motion menjaga animasi tetap sopan terhadap perangkat dan preferensi pengunjung.
Pertanyaan yang Sering Diajukan
Apakah efek ketik otomatis memperlambat halaman?
Tidak, selama teksnya pendek dan jumlah timer yang berjalan sedikit. Satu timer aktif pada satu waktu karena fungsi berikutnya baru dijadwalkan setelah fungsi sebelumnya selesai. Yang perlu dihindari adalah banyak elemen dengan efek ketik berjalan bersamaan tanpa jeda berhenti.
Bisakah teks yang diketik diambil dari API?
Bisa. Ambil data lebih dulu, simpan hasilnya ke array frasa, baru jalankan fungsi pengetikan. Pastikan teks dimasukkan lewat textContent atau dipisahkan dari markup kursor agar karakter khusus tidak merusak struktur halaman.
Bagaimana cara menghentikan animasi secara permanen?
Simpan ID timer dari setTimeout ke variabel, lalu panggil clearTimeout pada ID tersebut. Karena fungsi di sini memanggil dirinya sendiri, kamu perlu menyimpan ID setiap kali penjadwalan terjadi agar timer terakhir juga bisa dibatalkan.