Kamu pasti pernah lihat tombol yang warnanya langsung berubah pas di-hover — satu detik biru, detik berikutnya langsung gelap, tanpa transisi sama sekali. Hasilnya memang jalan, tapi terasa kasar. Antarmuka yang benar-benar rapi itu bergerak luwes dari satu kondisi ke kondisi lain: tombol menggelap perlahan, kartu terangkat mulus, menu meluncur terbuka. Kehalusan seperti inilah yang membedakan halaman yang sekadar berfungsi dari halaman yang terasa enak dipakai.
Yang menyenangkan, kamu nggak butuh JavaScript sama sekali untuk semua itu. Transition CSS memungkinkan kamu bilang ke browser: “kalau property ini berubah, jangan langsung lompat ke nilai baru — geser pelan-pelan ke sana dalam sepersekian detik.” Cukup satu baris CSS, dan setiap perubahan mendadak berubah jadi animasi yang halus. Ayo kita pelajari caranya.
Apa yang sebenarnya dilakukan transition
Transition itu mengawasi sebuah property. Begitu property-nya berubah, alih-alih membiarkannya melompat ke nilai baru, transition menganimasikan perubahan itu selama durasi yang kamu tentukan. Pemicunya bisa apa saja yang mengubah property tersebut: :hover, sebuah class yang ditambah lewat JavaScript, atau perubahan state apa pun. Transition-nya sendiri cuma menjelaskan bagaimana perubahan itu seharusnya berjalan.
Ini contoh paling sederhana — tombol yang warna latarnya memudar saat di-hover:
.button {
background-color: #00b8e6;
transition: background-color 0.3s;
}
.button:hover {
background-color: #0090b8;
}
Tanpa baris transition, hover akan langsung membalik warnanya seketika. Dengan baris itu, warnanya bergeser dari biru muda ke biru gelap selama 0,3 detik — dan kembali lagi sama mulusnya saat kursor menjauh. Perhatikan bahwa transition-nya dipasang di kondisi dasar (.button), bukan di :hover. Ini disengaja, dan penting.
Pasang transition di state dasar, bukan di hover
Kesalahan yang sering dilakukan pemula adalah menulis transition di dalam .button:hover. Kalau begitu, animasinya cuma jalan saat kursor masuk — pas kursor menjauh, elemennya balik seketika tanpa animasi. Deklarasikan transition di kondisi diam (.button), maka dia berlaku dua arah: saat kursor masuk maupun keluar. Pegangannya: transition menjelaskan perilaku normal sebuah elemen, jadi tempatnya ya di style normal elemen itu.
Empat property transition
Shorthand transition sebenarnya merangkum sampai empat property terpisah. Begitu kamu paham masing-masingnya satu per satu, bentuk shorthand-nya nanti jadi gampang dimengerti.
| Property | Yang diatur | Contoh |
|---|---|---|
transition-property |
Property mana yang dianimasikan | background-color |
transition-duration |
Berapa lama prosesnya | 0.3s |
transition-timing-function |
Kurva kecepatannya | ease-in-out |
transition-delay |
Berapa lama menunggu sebelum mulai | 0.1s |
Kalau ditulis lengkap satu per satu, tombol tadi jadi begini:
.button {
transition-property: background-color;
transition-duration: 0.3s;
transition-timing-function: ease;
transition-delay: 0s;
}
Dalam praktik, kamu jarang menulis keempatnya lengkap seperti ini — shorthand jauh lebih ringkas. Tapi setidaknya kamu jadi tahu apa yang sebenarnya terjadi di balik layar. Yuk kita bahas satu-satu.
transition-property — apa yang dianimasikan
Ini menyebutkan property (atau beberapa property) yang ingin kamu animasikan. Kamu bisa menarget satu property, beberapa sekaligus, atau pakai kata kunci all untuk menganimasikan semua property yang berubah:
/* cuma satu property */
transition-property: opacity;
/* beberapa yang spesifik, dipisah koma */
transition-property: opacity, transform;
/* semua yang berubah */
transition-property: all;
all memang praktis, tapi pakainya perlu sedikit hati-hati. Kata kunci itu menyuruh browser mengawasi setiap property yang bisa dianimasikan, dan kadang ini memunculkan animasi tak terduga pada hal yang nggak kamu maksudkan. Menyebut nama property yang benar-benar kamu butuhkan lebih jelas, dan biasanya juga lebih ringan.
transition-duration — berapa lama prosesnya
Durasi adalah berapa lama animasinya berjalan, dalam detik (s) atau milidetik (ms):
transition-duration: 0.3s; /* sama dengan 300ms */
Durasi adalah faktor paling besar yang menentukan rasa sebuah transition. Terlalu cepat dan efeknya nyaris nggak kelihatan; terlalu lambat dan antarmukanya terasa lemot. Untuk efek hover dan perubahan UI kecil, kisaran 150ms sampai 300ms biasanya pas — cukup gesit supaya responsif, tapi tetap cukup pelan supaya terasa mulus.
Transition butuh durasi supaya ada
Kalau kamu nggak mengatur durasi (atau mengaturnya jadi 0s), berarti nggak ada transition sama sekali — perubahannya terjadi seketika, persis seolah-olah kamu nggak pernah menulis property-nya. Durasilah yang memberi waktu animasi untuk berjalan. Bagian yang satu ini nggak boleh ketinggalan.
transition-timing-function — kurva kecepatan
Transition nggak harus bergerak dengan kecepatan tetap. Timing function membentuk percepatannya — apakah dia mulai pelan lalu makin cepat, melesat di awal lalu mengerem halus, atau jalan konstan dari awal sampai akhir. Detail inilah yang bikin gerakan terasa natural, bukan kaku seperti robot.
transition-timing-function: ease; /* bawaan: mulai pelan, tengah cepat, akhir pelan */
transition-timing-function: linear; /* kecepatan tetap */
transition-timing-function: ease-in; /* mulai pelan, akhir cepat */
transition-timing-function: ease-out; /* mulai cepat, akhir pelan */
transition-timing-function: ease-in-out; /* pelan di kedua ujung */
Bedanya halus tapi nyata. ease-out adalah pilihan default yang bagus untuk hal yang muncul atau bergerak masuk ke layar — terasa gesit dan mantap, lalu melambat lembut saat sampai. linear terlihat mekanis dan paling cocok dipakai untuk hal seperti spinner yang memang seharusnya berputar dengan tempo tetap. Kalau kamu mau kontrol penuh, cubic-bezier() memungkinkan kamu menggambar kurvamu sendiri, tapi kata kunci bawaan sudah menutupi sebagian besar pekerjaan nyata.
transition-delay — menunggu sebelum mulai
Delay menahan transition sejenak sebelum dia mulai berjalan:
transition-delay: 0.1s;
Sebagian besar waktu, nilai ini akan kamu biarkan 0s. Delay baru terasa gunanya pada efek berurutan — membuat beberapa elemen beranimasi satu demi satu dengan memberi tiap elemen delay yang sedikit lebih besar — atau pada tooltip yang sebaiknya menunggu sebentar sebelum muncul, supaya nggak berkedip setiap kali kursor tak sengaja lewat.
Bentuk shorthand
Begitu keempat bagiannya masuk akal, shorthand transition merangkumnya jadi satu baris yang rapi. Urutannya: property, durasi, timing-function, delay:
.button {
transition: background-color 0.3s ease-in-out 0s;
}
Dalam praktik, kebanyakan orang membuang bagian yang nggak dibutuhkan. Kalau nggak ada delay, ya tinggalkan saja. Dua nilai yang hampir selalu kamu cantumkan adalah property dan durasi:
.button {
transition: background-color 0.3s;
}
Saat dua nilai waktu muncul bersamaan, nilai pertama selalu durasi dan yang kedua adalah delay — begitu cara browser membedakannya. Jadi transition: opacity 0.3s 0.1s artinya animasi 0,3 detik yang menunggu 0,1 detik dulu sebelum mulai.
Menganimasikan beberapa property sekaligus
Efek nyata sering mengubah lebih dari satu hal sekaligus — misalnya kartu yang sekaligus terangkat dan jadi lebih terang. Kamu menuliskan transition tiap property dipisah koma, dan tiap property boleh punya timing-nya sendiri:
.card {
transition: transform 0.3s ease-out, box-shadow 0.3s ease-out;
}
.card:hover {
transform: translateY(-6px);
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
}
Di sini kartunya naik enam piksel dan bayangannya membesar, keduanya selama 0,3 detik yang sama, menghasilkan kesan “terangkat dari halaman” yang memuaskan. Kamu bisa saja meringkasnya jadi transition: all 0.3s ease-out dan tetap jalan — tapi menyebut transform dan box-shadow secara eksplisit membuatmu tetap pegang kendali atas apa persisnya yang dianimasikan.
Utamakan transform dan opacity untuk animasi yang mulus
Browser bisa menganimasikan transform dan opacity dengan sangat efisien karena keduanya nggak memaksa halaman menghitung ulang tata letak. Menganimasikan property seperti width, height, top, atau margin membuat browser mengukur dan menggambar ulang halaman di setiap frame, dan ini bisa tersendat di perangkat yang lebih lambat. Kapan pun sebuah gerakan bisa kamu ungkapkan sebagai transform (misalnya pakai translateY ketimbang mengubah top), lakukan itu — animasimu bakal terasa jauh lebih mulus.
Apa yang bisa dan tidak bisa di-transition
Nggak semua property bisa dianimasikan. Aturan umumnya: sebuah property bisa dianimasikan kalau browser sanggup menghitung nilai-nilai di antaranya. Warna, panjang, opacity, dan transform semuanya punya “titik tengah” yang jelas, jadi mereka beranimasi dengan mulus. Hal yang nggak punya kondisi antara nggak bisa dianimasikan.
Jebakan klasiknya adalah display. Kamu nggak bisa menganimasikan display: none menjadi display: block dengan mulus — nggak ada titik tengah antara “tidak ada di layout” dan “ada di layout”, jadi perubahannya selalu seketika. Hampir semua orang pernah kejebak di sini: mereka mencoba memunculkan menu tersembunyi dengan menganimasikan display, lalu bingung kenapa nggak ada yang beranimasi.
Solusinya adalah menganimasikan opacity (dan sering kali visibility) sebagai gantinya:
.menu {
opacity: 0;
visibility: hidden;
transition: opacity 0.3s ease, visibility 0.3s;
}
.menu.open {
opacity: 1;
visibility: visible;
}
Menunya muncul dan menghilang lewat opacity, sementara visibility mengatur kapan dia bisa diklik dan kapan tidak. Ini pola standar untuk menampilkan dan menyembunyikan sesuatu dengan mulus, dan layak banget kamu hafalkan.
Contoh praktis: tombol yang rapi
Sekarang kita gabungkan ide-ide intinya jadi tombol yang benar-benar bakal kamu pakai di proyek nyata — warna, angkatan, dan bayangan yang sama-sama bergerak halus saat di-hover:
.btn {
background-color: #00b8e6;
color: #ffffff;
padding: 12px 24px;
border: none;
border-radius: 8px;
cursor: pointer;
transition: background-color 0.2s ease,
transform 0.2s ease,
box-shadow 0.2s ease;
}
.btn:hover {
background-color: #0090b8;
transform: translateY(-2px);
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.2);
}
.btn:active {
transform: translateY(0);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}
<button class="btn">Mulai Sekarang</button>
Saat di-hover, tombolnya menggelap sedikit, naik dua piksel, dan tumbuh bayangan lembut — semuanya dalam 0,2 detik yang gesit. Saat :active (selagi diklik), dia menekan turun lagi, memberi sensasi “tertekan” yang terasa nyata. Nggak satu pun dari ini butuh JavaScript, dan justru detail seperti inilah yang orang rasakan meski mereka nggak pernah sadar memperhatikannya.
Catatan soal aksesibilitas
Gerakan memang menyenangkan buat kebanyakan orang, tapi buat sebagian lain dia bisa bikin nggak nyaman, bahkan mual. Browser menyediakan pengaturan untuk hal ini, dan kamu sebaiknya menghormatinya. Media query prefers-reduced-motion memungkinkan kamu mematikan atau memperhalus animasi bagi pengguna yang sudah meminta sistemnya untuk mengurangi gerakan:
@media (prefers-reduced-motion: reduce) {
* {
transition-duration: 0.01ms !important;
}
}
Ini secara efektif menonaktifkan transition bagi siapa pun yang sudah memilih keluar, tanpa kamu harus menulis ulang setiap aturan. Tambahan kecil ini membuat situsmu jauh lebih perhatian, dan jadi salah satu ciri pekerjaan front-end yang profesional. Kalau kamu mau menyegarkan ingatan soal media query, panduan kami tentang desain responsif membahas cara kerjanya.
Penutup
Transition CSS adalah cara paling mudah membuat antarmuka terasa hidup, dan sekarang seluruh perkakasnya sudah kamu pegang:
- Sebuah transition menganimasikan property dengan mulus saat dia berubah — dipicu oleh
:hover, pergantian class, atau perubahan state apa pun. - Deklarasikan di state dasar, bukan di hover, supaya dia jalan dua arah.
- Empat bagiannya adalah
transition-property,transition-duration,transition-timing-function, dantransition-delay— dirangkum oleh shorthand dengan urutan itu. - Durasi menentukan rasanya (150–300ms untuk kebanyakan UI); timing function membentuk kurva kecepatan (
ease-outdefault yang bagus). - Animasikan beberapa property dengan nilai dipisah koma, dan utamakan
transformsertaopacitydemi performa yang mulus. - Kamu nggak bisa men-transition
display— gunakanopacitydanvisibilitysebagai gantinya. - Hormati
prefers-reduced-motionsupaya pengguna yang sensitif terhadap gerakan tetap nyaman.
Transition menangani kasus sederhana dengan sangat baik: perubahan dari satu state ke state lain. Tapi begitu kamu butuh gerakan yang berjalan sendiri — berulang, banyak tahap, jalan tanpa interaksi pengguna sama sekali — ada alat yang lebih bertenaga menanti. Sebelum ke sana, kamu perlu dulu menguasai property yang bikin gerakan terasa mulus sejak awal: transform CSS, yang kita bahas berikutnya.