D
P
0

CSS & Web Animation

`transform` Diam-Diam Di-drop Browser? `calc()` Masih Merujuk CSS Variable yang Sudah Di-rename

26 Juli 2026·4 menit baca
`transform` Diam-Diam Di-drop Browser? `calc()` Masih Merujuk CSS Variable yang Sudah Di-rename

Gejalanya

Di sebuah situs klien ada carousel product-showcase: satu slide besar di tengah, dan di bawahnya strip thumbnail yang mestinya ikut geser saat kamu maju ke slide berikutnya, supaya thumbnail yang aktif selalu berada di tengah. Masalahnya, strip itu diam total. Apa pun slide yang aktif, thumbnail-nya tetap menampilkan tetangga yang sama persis, seolah posisinya terkunci di index 0. Slide besarnya berganti mulus, hanya strip di bawah yang tidak pernah bergerak.

Yang bikin pusing: nol error di console. Tidak ada Uncaught, tidak ada warning, tidak ada baris CSS yang dicoret merah di DevTools. Dan ternyata ini sudah rusak diam-diam sejak beberapa versi lalu, tepatnya sejak sebuah rename di v1.7.14, tanpa ada yang sadar sampai klien bertanya kenapa thumbnail-nya tidak pernah geser.

Jalan buntu yang saya susuri

Tersangka pertama saya jelas: hitungan index-nya salah. Strip geser pakai translate3d yang besarnya bergantung pada index aktif, jadi kalau index-nya macet di 0, wajar tidak ada yang bergerak. Saya log index setiap kali slide berganti:

console.log("active index:", indexMV);

Angkanya naik rapi: 0, 1, 2, 3. Jadi JS tahu index yang benar. Bukan di situ.

Tersangka kedua: mungkin handler-nya tidak jalan, atau elemen strip-nya salah target. Saya taruh log di dalam handler dan cek referensi elemennya. Handler jalan tiap slide ganti, elemennya benar. JS-nya benar-benar mengeksekusi kode yang menyetel transform. Tapi strip-nya tetap diam.

Yang akhirnya membuka semuanya: saya buka elemen strip di DevTools dan lihat inline style-nya. JS jelas menghitung dan menyetel transform, tapi atribut style elemen itu kosong. Tidak ada transform sama sekali. Saya coba set manual dari console, menempelkan string persis yang dihasilkan kode:

el.style.transform = "calc(-1 * (var(--wg-thumb-w) + var(--wg-thumb-gap)))";
console.log(el.style.transform); // "" (kosong)

Balikannya string kosong. Browser menolak nilai itu tanpa bersuara sedikit pun. Di sinilah lampu menyala: assignment-nya tidak gagal karena JS error, tapi karena nilainya invalid dan CSSOM diam-diam membuangnya.

Akar masalahnya

Saya perhatikan string yang dihasilkan: isinya var(--wg-thumb-w) dan var(--wg-thumb-gap). Saya grep seluruh CSS tema untuk dua nama itu:

grep -rn -- "--wg-thumb" src/

Kosong. Nama itu tidak ada lagi di mana pun. Ternyata di v1.7.14 ada rename namespace besar-besaran: semua custom property --wg-* (sisa dari komponen lama bernama WearableGallery) diganti jadi --folio-*. Rename-nya rapi di sisi CSS, semua definisi variable sudah ikut ganti. Tapi satu referensi ketinggalan: sebuah template string di animations.js:1432 masih menyusun calc() dengan nama variable lama.

Dan inilah kunci kenapa gagalnya senyap. calc() yang salah satu term-nya adalah custom property yang tidak terdefinisi menjadi invalid secara keseluruhan. Waktu kamu set element.style.transform ke nilai invalid, CSSOM tidak melempar exception; ia hanya mengabaikan assignment itu dan membiarkan properti-nya seperti semula, dalam kasus ini kosong. Jadi tidak ada error di console, tidak ada baris merah, tidak ada apa-apa. Transform-nya sekadar tidak pernah ada, dan strip berhenti di posisi awalnya selamanya.

Ini beda dengan kelas bug CSS variable yang lain, misalnya variable yang hilang karena di-tree-shake build tool. Di sini build-nya baik-baik saja; variable --folio-* yang baru ada dan valid. Yang salah cuma satu string di JS yang masih menunjuk ke nama yang sudah mati.

Perbaikannya

Perbaikan intinya satu baris: samakan referensi JS dengan nama variable yang baru.

// sebelum (rusak: var tidak ada, calc invalid, transform dibuang):
`calc(${-indexMV} * (var(--wg-thumb-w) + var(--wg-thumb-gap)))`
// sesudah:
`calc(${-indexMV} * (var(--folio-thumb-w) + var(--folio-thumb-gap)))`

Begitu diganti, calc() jadi valid, transform kembali diterima, dan strip thumbnail langsung geser mengikuti slide aktif seperti seharusnya.

Tapi memperbaiki satu baris itu tidak cukup untuk tenang. Bug ini terjadi justru karena rename yang saya kira sudah tuntas ternyata menyisakan satu referensi nyasar. Jadi langkah terakhir saya adalah membuktikan tidak ada sisa lain. Saya grep seluruh tema untuk nama lama, bukan cuma di CSS tapi di JS juga:

grep -rn -e "--wg-" -e "wgallery" src/

Nol hasil. Baru setelah itu saya yakin rename-nya benar-benar bersih.

Poin yang saya bawa pulang

  • Rename CSS custom property tidak berhenti di file CSS. Referensi string di JS, template literal, setProperty, dan calc() yang dirakit runtime ikut kena. Grep nama lama di seluruh codebase, jangan cuma di stylesheet.
  • calc() dengan custom property yang tidak terdefinisi jadi invalid seluruhnya, dan itu gagal senyap. Tidak ada error, transform-nya cuma tidak pernah muncul.
  • Set element.style.someProp ke nilai invalid tidak melempar apa-apa. CSSOM mengabaikannya diam-diam. Kalau elemen tidak bergerak padahal JS "menyetel" style, cek apakah nilainya benar-benar nyangkut lewat el.style.transform.
  • Kalau JS tahu index yang benar tapi elemen tetap tidak bergerak, curigai nilai style yang ditolak, bukan logika event-nya.
  • Bug yang tidak menghasilkan error sama sekali bisa hidup berbulan-bulan. Tutup rename besar dengan grep verifikasi, bukan dengan asumsi "sudah semua kok".