Table of Contents
▼- Pergeseran Batas: CSS Pseudo-class vs JavaScript Event Listener
- Fitur CSS 2026 yang Dulu Hanya Bisa Dilakukan JavaScript
- Kasus Nyata: Toggle, Dialog, Accordion, dan Animation
- Kapan JavaScript Masih Tidak Bisa Digantikan CSS
- Strategi Hybrid: CSS-first, JavaScript sebagai Fallback
- Dampak Performa yang Nyata
- Kesimpulan
Dulu ada garis yang cukup jelas: CSS untuk tampilan, JavaScript untuk perilaku. Tapi di 2026, garis itu makin sulit dilihat.
Fitur-fitur CSS modern sudah bisa menangani toggle, dialog, accordion, animasi berbasis scroll, bahkan state management sederhana — tanpa satu pun baris JavaScript.
Ini bukan sekadar tren estetika. Developer yang tahu kapan harus memilih CSS murni bisa memangkas bundle size, mengurangi beban pada main thread, dan menghasilkan UI yang lebih responsif secara signifikan.
Artikel ini akan memandu kamu dari pergeseran konseptual hingga implementasi nyata.
Pergeseran Batas: CSS Pseudo-class vs JavaScript Event Listener
Selama bertahun-tahun, JavaScript menjadi satu-satunya cara untuk merespons aksi pengguna secara dinamis.
Kamu butuh addEventListener, state variable, manipulasi DOM, dan seringkali sebuah framework hanya untuk membuat sesuatu yang sederhana seperti dropdown terbuka saat diklik.
CSS sejak lama punya pseudo-class seperti :hover dan :focus. Tapi keduanya terbatas — tidak ada memori state, tidak bisa memengaruhi elemen lain secara bebas.
Yang berubah drastis adalah kemunculan :has(), :is(), :not() generasi baru, dan terutama :has() sebagai "parent selector" yang dulu mustahil ada di CSS.
Sekarang CSS bisa bertanya: "Apakah elemen ini punya child dalam kondisi tertentu?"
/* Jika form punya input yang sedang fokus, ubah tampilan label */
.form-group:has(input:focus) label {
color: var(--color-primary);
font-weight: 600;
}
Ini bukan JavaScript. Ini CSS murni yang merespons state DOM secara real-time.
Kemudian ada @starting-style untuk animasi saat elemen pertama kali muncul, transition-behavior: allow-discrete untuk elemen display: none yang kini bisa dianimasikan, dan anchor positioning untuk tooltip tanpa JavaScript positioning logic.
Fitur CSS 2026 yang Dulu Hanya Bisa Dilakukan JavaScript
1. popover API + CSS :popover-open
Attribute popover kini native di HTML, dan CSS bisa merespons statenya langsung.
<button popovertarget="menu">Buka Menu</button>
<div id="menu" popover>
<p>Ini konten popover</p>
</div>
[popover] {
opacity: 0;
transform: translateY(-8px);
transition: opacity 0.2s, transform 0.2s, display 0.2s allow-discrete;
}
[popover]:popover-open {
opacity: 1;
transform: translateY(0);
}
@starting-style {
[popover]:popover-open {
opacity: 0;
transform: translateY(-8px);
}
}
Tidak ada JavaScript. Tidak ada classList.toggle. Browser mengelola state buka-tutup secara native.
2. <details> dan <summary> dengan Animasi Penuh
Accordion interaktif kini bisa 100% CSS dengan animasi yang mulus.
details {
overflow: hidden;
}
details[open] summary ~ * {
animation: slideDown 0.3s ease-out;
}
@keyframes slideDown {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
3. CSS @property dan Custom Properties yang Animatable
Dulu kamu butuh JavaScript untuk menginterpolasi nilai custom property dalam animasi.
@property --gradient-angle {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
.card {
background: conic-gradient(from var(--gradient-angle), #6366f1, #a855f7, #6366f1);
animation: rotate-gradient 4s linear infinite;
}
@keyframes rotate-gradient {
to {
--gradient-angle: 360deg;
}
}
Ini gradient yang berputar tanpa satu baris JavaScript pun.
4. Scroll-Driven Animations
Artikel sebelumnya di KerjaKode sudah membahas ini, tapi penting disebutkan dalam konteks perbandingan: animation-timeline: scroll() dan view() menggantikan seluruh logika IntersectionObserver untuk kasus animasi berbasis posisi scroll.
Kasus Nyata: Toggle, Dialog, Accordion, dan Animation
Mari kita lihat implementasi konkret yang sebelumnya selalu memakai JavaScript.
Toggle Dark Mode Tanpa JavaScript
Kamu bisa menggunakan checkbox tersembunyi dan :checked pseudo-class sebagai state toggle.
<input type="checkbox" id="theme-toggle" class="sr-only">
<label for="theme-toggle">Toggle Dark Mode</label>
<main class="content">...</main>
.sr-only {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(0,0,0,0);
}
#theme-toggle:checked ~ .content {
background: #0f172a;
color: #f1f5f9;
}
State tersimpan di elemen form. CSS merespons. Zero JavaScript.
Modal Dialog dengan <dialog> Native
<button onclick="document.getElementById('modal').showModal()">Buka</button>
<dialog id="modal">
<p>Konten modal di sini</p>
<form method="dialog">
<button>Tutup</button>
</form>
</dialog>
dialog {
border: none;
border-radius: 12px;
padding: 2rem;
max-width: 500px;
opacity: 0;
transform: scale(0.95);
transition: opacity 0.2s, transform 0.2s, display 0.2s allow-discrete;
}
dialog[open] {
opacity: 1;
transform: scale(1);
}
@starting-style {
dialog[open] {
opacity: 0;
transform: scale(0.95);
}
}
dialog::backdrop {
background: rgb(0 0 0 / 0.5);
backdrop-filter: blur(4px);
}
Perhatikan: tombol "Buka" masih memakai JavaScript (showModal()), tapi animasi masuk-keluar dan backdrop sepenuhnya CSS.
Accordion dengan :has() dan <details>
.faq-container {
display: flex;
flex-direction: column;
gap: 1rem;
}
details {
border: 1px solid #e2e8f0;
border-radius: 8px;
padding: 0 1rem;
}
details[open] {
border-color: #6366f1;
}
summary {
padding: 1rem 0;
cursor: pointer;
font-weight: 600;
list-style: none;
}
summary::after {
content: "+";
float: right;
transition: transform 0.2s;
}
details[open] summary::after {
transform: rotate(45deg);
}
details > p {
padding-bottom: 1rem;
animation: fadeIn 0.25s ease;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
Ini accordion yang berfungsi penuh — dengan animasi ikon dan transisi konten — tanpa JavaScript.
Kapan JavaScript Masih Tidak Bisa Digantikan CSS
CSS yang semakin powerful bukan berarti JavaScript tidak relevan. Ada batasan yang nyata dan penting dipahami.
State yang perlu disimpan atau dikirim ke server.
CSS tidak punya memori di luar session page. Jika toggle dark mode perlu diingat untuk kunjungan berikutnya, kamu butuh localStorage atau cookies — keduanya hanya bisa diakses via JavaScript.
Logika kondisional yang kompleks.
CSS tidak bisa melakukan kalkulasi dinamis seperti "tampilkan elemen ini hanya jika nilai field A lebih dari nilai field B." :has() sangat powerful, tapi tidak bisa membandingkan nilai.
Fetch dan komunikasi network.
Semua interaksi dengan API — autocomplete, infinite scroll, submit form ke backend, real-time data — tetap membutuhkan JavaScript.
Aksesibilitas yang kompleks.
Mengelola aria-expanded, aria-selected, focus management untuk keyboard navigation pada komponen custom masih membutuhkan JavaScript. CSS tidak bisa mengubah atribut ARIA.
Event yang tidak punya padanan CSS.
resize, scroll dengan logika tertentu, intersectionObserver untuk lazy loading konten dinamis, gesture touch yang kompleks — semua ini masih ranah JavaScript.
Animasi yang dikontrol secara programatik.
Jika pengguna bisa pause, reverse, atau seek sebuah animasi, Web Animations API di JavaScript jauh lebih tepat daripada CSS animation.
Strategi Hybrid: CSS-first, JavaScript sebagai Fallback
Pendekatan terbaik untuk tim frontend modern bukan memilih satu di antara keduanya, tapi membangun dengan filosofi CSS-first.
Prinsipnya sederhana: jika sebuah interaksi bisa diselesaikan dengan CSS, gunakan CSS. Tambahkan JavaScript hanya untuk kebutuhan yang benar-benar tidak bisa dipenuhi CSS.
Keuntungan Konkret CSS-first
Pertama, bundle size lebih kecil. Setiap baris JavaScript yang dihapus adalah byte yang tidak perlu didownload, di-parse, dan dieksekusi.
Kedua, performa rendering lebih baik. CSS animation yang menggunakan transform dan opacity berjalan di compositor thread, bukan main thread. Ini berarti animasi tetap mulus meski main thread sedang sibuk.
Ketiga, lebih resilient. CSS tidak bisa crash. Jika ada error di JavaScript, interaksi berbasis JS berhenti bekerja. Interaksi berbasis CSS akan tetap berfungsi.
Implementasi Pola CSS-first
// Deteksi apakah browser support fitur CSS yang dibutuhkan
const supportsPopover = HTMLElement.prototype.hasOwnProperty('popover');
const supportsHas = CSS.supports('selector(:has(*))');
if (!supportsPopover) {
// Fallback: implementasi popover dengan JavaScript
initLegacyPopover();
}
// Untuk animasi: hanya tambahkan class jika CSS tidak bisa handle
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (!prefersReducedMotion) {
document.querySelectorAll('.animate-on-scroll').forEach(el => {
// Hanya aktifkan jika CSS scroll-driven animation tidak tersedia
if (!CSS.supports('animation-timeline: scroll()')) {
observeWithIntersectionObserver(el);
}
});
}
Polanya jelas: CSS dulu, JavaScript sebagai jaring pengaman.
Checklist Sebelum Menulis JavaScript untuk UI
Sebelum membuka file JavaScript untuk interaksi UI, tanyakan ini:
- Apakah ini bisa diselesaikan dengan pseudo-class (
:hover,:focus,:checked,:has())? - Apakah elemen HTML semantik (
<details>,<dialog>,popover) sudah tersedia? - Apakah animasinya bisa pakai
@keyframesatau scroll-driven animation? - Apakah state-nya hanya visual dan tidak perlu disimpan?
Jika semua jawaban "ya", CSS cukup.
Dampak Performa yang Nyata
Bukan sekadar teori. Pergantian JavaScript dengan CSS punya dampak terukur.
Sebuah komponen accordion sederhana yang menggunakan JavaScript classList.toggle membutuhkan parsing, execution, dan event binding. Untuk 10 accordion di halaman yang sama, biaya ini mungkin kecil tapi tetap ada.
Ketika kamu menggantinya dengan <details> native + CSS animation, kamu mengeliminasi semua overhead tersebut. Browser sudah tahu cara menanganinya secara native.
Untuk aplikasi yang lebih besar — katakanlah sebuah design system dengan puluhan komponen — pendekatan CSS-first bisa memangkas ratusan kilobyte dari bundle JavaScript, yang langsung berdampak pada First Input Delay (FID) dan Total Blocking Time (TBT).
Kesulitan dengan tugas programming atau butuh bantuan coding? KerjaKode siap membantu menyelesaikan tugas IT dan teknik informatika Anda. Dapatkan bantuan profesional di jasa tugas IT KerjaKode.
Kesimpulan
Di 2026, pertanyaannya bukan lagi "CSS atau JavaScript?" tapi "berapa banyak yang bisa kita serahkan ke CSS?"
Fitur seperti :has(), popover API, <dialog> native, @starting-style, dan scroll-driven animation telah menggeser garis batas secara fundamental.
Developer yang memahami batas ini bisa membangun UI yang lebih cepat, lebih ringan, dan lebih tahan terhadap error.
Mulailah dengan CSS. Tambahkan JavaScript hanya saat CSS benar-benar tidak cukup. Itu filosofi yang akan membuat frontend kamu unggul di era modern ini.