Geonode logo
Geonode Team

Geonode Team

Dikemas kini: 7 Oktober 2026

Diterbitkan: 2 September 2026

Lembar Referensi Selektor CSS: Panduan dengan Contoh

Selektor CSS adalah cara tercepat untuk menunjukkan elemen mana yang dimaksud. Selektor ini digunakan untuk penataan gaya, melakukan kueri dalam JavaScript, dan ekstraksi data di setiap pustaka scraping yang mumpuni. Referensi ini disusun untuk penggunaan praktis: tabel sintaks terlebih dahulu, kemudian pseudo-class yang benar-benar layak disebutkan, lalu spesifisitas, dan terakhir pola-pola yang sering muncul. Referensi ini juga membahas hal-hal yang masih belum dapat dilakukan oleh CSS, yang daftarnya kini lebih pendek daripada sebelumnya.

Catatan mengenai siapa yang menulis ini dan mengapa hal itu tidak terlalu relevan di sini: kami adalah Geonode dan kami menjual proxy kepada orang-orang yang melakukan pekerjaan ekstraksi data. Pilihan selektor tidak memengaruhi apa pun yang kami jual, dan satu-satunya kesamaan yang layak disebutkan adalah untuk tujuan diagnostik — selektor yang tidak cocok dengan apa pun dan permintaan yang diblokir terlihat identik dari luar, namun keduanya merupakan masalah yang sama sekali tidak terkait. Jika halaman berhasil dimuat dan selektor Anda tidak menemukan apa pun, referensi ini adalah tempat yang tepat dan tidak ada yang perlu diubah mengenai cara halaman tersebut diambil.

Selektor Dasar

SelektorCocok dengan
*Setiap elemen
divSetiap elemen div
.cardElemen dengan kelas card
#mainElemen dengan id main
.card.featuredElemen dengan kedua kelas
div.cardElemen div dengan kelas card
div, pElemen div dan elemen p

Dua di antaranya patut diperhatikan.

.card.featured tanpa spasi berarti kedua kelas tersebut ada pada satu elemen. .card .featured dengan spasi berarti elemen dengan kelas featured di dalam elemen dengan kelas card. Satu karakter saja dapat mengubah makna secara total, dan ini adalah kesalahan ketik yang paling umum di bidang ini.

div, p adalah daftar selektor, bukan hubungan. Daftar ini mencocokkan semua elemen dalam salah satu kelompok, dan setiap bagian dievaluasi secara independen — sehingga div, p.note mencocokkan semua elemen div dan paragraf dengan kelas note, bukan elemen div dengan kelas note.

Kombinator

Elemen-elemen ini menunjukkan hubungan antar elemen.

SelektorCocok dengan
div pp di mana saja di dalam div (keturunan)
div > pp yang merupakan anak langsung dari div
h2 + pp yang berada tepat setelah h2 (saudara sebaris)
h2 ~ pSetiap p setelah h2 dengan induk yang sama (saudara umum)

Kombinator keturunan berupa spasi, sehingga mudah dimasukkan secara tidak sengaja dan mudah terlewatkan saat membaca.

> lebih tepat dan biasanya lebih andal. div > p tidak akan cocok dengan paragraf yang dibalut dalam <section> bulan depan — yang terdengar seperti kelemahan, namun seringkali justru sebaliknya, karena selektor yang diam-diam mulai cocok dengan lebih banyak elemen daripada yang dimaksudkan lebih buruk daripada selektor yang berhenti cocok dan memberi tahu Anda.

+ dan ~ adalah kombinator saudara dan keduanya hanya melihat ke depan. Tidak ada kombinator "saudara sebelumnya" dalam CSS; :has() memberikan efek tersebut secara tidak langsung, yang akan dibahas di bawah ini.

Pemilih Atribut

Seringkali merupakan opsi paling stabil yang tersedia, karena atribut biasanya dipilih secara sengaja.

PemilihCocok dengan
[href]Elemen dengan atribut href
[href="/about"]Nilai persis
[href^="/docs"]Nilai dimulai dengan
[href$=".pdf"]Nilai diakhiri dengan
[href*="download"]Nilai mengandung
[class~="card"]Nilai berupa daftar yang dipisahkan spasi yang mengandung kata card
[lang|="en"]Nilai berupa en atau dimulai dengan en-
[data-state="open" i]Pencocokan tanpa membedakan huruf besar/kecil

Dua di antaranya jarang digunakan.

[class~="card"] sama persis dengan .card — operator ~= melakukan pencocokan kata yang dipisahkan oleh spasi, yang merupakan hal yang dibutuhkan oleh atribut class. Mengetahui keberadaannya berguna terutama untuk memahami apa yang sebenarnya dilakukan oleh .card, dan untuk membuat selektor secara terprogram ketika Anda memiliki nama atribut dalam sebuah variabel.

Bendera i membuat pencocokan tidak peka huruf besar-kecil, yang sangat berguna untuk nilai atribut yang huruf besar-kecilnya bervariasi di seluruh situs.

Khusus untuk ekstraksi, atribut data-* lebih diutamakan daripada kelas. Sebuah [data-testid="product-card"] dipilih oleh pengembang sebagai titik kait yang stabil; sedangkan nama kelas dapat dihasilkan ulang oleh alat build pada setiap proses deploy.

Pseudo-Kelas: Struktural

SelektorCocok dengan
:first-childElemen yang merupakan anak pertama dari induknya
:last-childAnak terakhir
:only-childElemen yang tidak memiliki saudara sebaris
:nth-child(3)Anak ketiga
:nth-child(2n)Anak dengan nomor genap
:nth-child(2n+1)Anak dengan nomor ganjil
:nth-child(-n+3)Tiga anak pertama
:nth-last-child(2)Anak kedua dari belakang
:first-of-typeElemen pertama dari jenisnya di antara saudara sejenis
:nth-of-type(2)Elemen kedua dari jenisnya
:emptyElemen yang tidak memiliki anak, termasuk teks
:rootAkar dokumen, biasanya html

Varian "-of-type" lebih penting daripada yang disadari orang. p:first-child hanya cocok dengan paragraf jika paragraf tersebut merupakan anak pertama dari induknya — jadi jika judul muncul terlebih dahulu, tidak ada yang cocok. p:first-of-type cocok dengan paragraf pertama terlepas dari apa yang mendahuluinya. Untuk ekstraksi, yang kedua hampir selalu yang Anda maksud.

:nth-child(-n+3) untuk "tiga yang pertama" adalah ungkapan yang patut diingat dari sintaks An+B, bersama dengan :nth-child(n+4) untuk "yang keempat dan seterusnya". Menggabungkannya akan menghasilkan rentang: :nth-child(n+2):nth-child(-n+5) memilih anak-anak dari yang kedua hingga kelima.

Pseudo-Kelas: Logis

Kelompok yang mengalami perubahan paling signifikan dalam beberapa tahun terakhir.

SelektorCocok dengan
:not(.hidden)Elemen tanpa kelas hidden
:is(h1, h2, h3)Salah satu dari selektor yang tercantum
:where(h1, h2, h3)Sama dengan :is() tetapi dengan spesifisitas nol
:has(> img)Elemen yang mengandung keturunan atau saudara yang cocok

:is() dan :where() mempersingkat daftar yang berulang. :is(article, section) > h2 menggantikan article > h2, section > h2, dan penghematan ini bertambah dengan cepat pada daftar yang lebih panjang. Satu-satunya perbedaan di antara keduanya adalah spesifisitas: :is() mengambil spesifisitas dari argumennya yang paling spesifik, sedangkan :where() selalu memberikan nilai nol.

:not() menerima daftar selektor di peramban modern, sehingga :not(.a, .b) berfungsi dan berarti "tidak ada". Perilaku argumen tunggal pada versi lama mengharuskan penggunaan rantai :not(.a):not(.b).

:has() adalah yang paling penting. Dokumentasi MDN menjelaskannya sebagai representasi "sebuah elemen jika salah satu selektor relatif yang diberikan sebagai argumen cocok dengan setidaknya satu elemen saat diikat terhadap elemen ini", yang menyediakan "cara untuk memilih elemen induk atau elemen saudara sebelumnya relatif terhadap elemen referensi". Statusnya adalah "Baseline widely available", didukung di berbagai peramban sejak Desember 2023.

div.card:has(span.sold-out)     /* a card containing a sold-out marker */
h1:has(+ p)                     /* an h1 immediately followed by a p */
li:has(~ li.active)             /* an li with a later active sibling */
label:has(input:checked)        /* a label wrapping a checked input */

Tiga batasan yang didokumentasikan: ia "tidak dapat disarangkan" di dalam :has() lain, pseudo-elemen tidak valid di dalamnya atau sebagai titik acuan untuknya, dan spesifisitasnya mengikuti aturan yang sama seperti :is() dan :not() — argumen yang paling spesifik.

Pseudo-Kelas: Status dan Bentuk

SelektorCocok dengan
:hover, :focus, :activeStatus interaksi
:focus-visibleFokus yang seharusnya menampilkan lingkaran terlihat
:focus-withinElemen yang berisi keturunan yang difokuskan
:checkedKotak centang yang dicentang, tombol radio, atau opsi yang dipilih
:disabled, :enabledStatus kontrol formulir
:required, :optionalAtribut validasi formulir
:valid, :invalidStatus validasi batasan
:placeholder-shownBidang masukan yang menampilkan teks placeholder-nya
:targetElemen yang sesuai dengan fragmen URL
:visited, :linkStatus tautan

Sebagian besar hal ini berkaitan dengan gaya tampilan daripada ekstraksi data, dengan dua pengecualian. :checked benar-benar berguna untuk membaca status formulir dalam otomatisasi pengujian, dan :disabled memberi tahu Anda apakah suatu kontrol interaktif — yang sering kali menjelaskan mengapa klik tidak menghasilkan apa-apa.

Perhatikan bahwa :hover dan :focus tidak dapat diakses secara efektif menggunakan querySelectorAll dalam konteks pengikisan data, karena kedua status tersebut tidak ada dalam dokumen yang baru saja Anda parsing.

Spesifisitas, Secara Singkat

Berlaku saat selektor bersaing dalam menentukan gaya, dan tidak berlaku untuk melakukan kueri — penting untuk diketahui karena kebingungan antara kedua konteks tersebut sering terjadi.

Spesifisitas dihitung berdasarkan tiga angka:

KomponenDisumbangkan oleh
ID#main
Kelas, atribut, pseudo-kelas.card, [href], :hover
Elemen, pseudo-elemendiv, ::before

Jika dibandingkan dari kiri ke kanan: berapa pun jumlah kelas tidak akan pernah melebihi satu ID. Gaya inline mengungguli semuanya, dan !important mengungguli gaya inline, itulah sebabnya keduanya lebih merupakan pilihan terakhir daripada alat bantu.

Dua catatan modern. :where() tidak memberikan spesifisitas sama sekali, sehingga menjadi pilihan tepat untuk nilai default perpustakaan yang seharusnya dapat diubah oleh pengguna tanpa kesulitan. Dan :is(), :not(), serta :has() semuanya mengikuti spesifisitas argumen yang paling spesifik, sehingga :is(#main, div) memiliki spesifisitas yang sama dengan #main.

Untuk querySelectorAll dan scraping, spesifisitas sama sekali tidak berlaku. Selektor tersebut cocok dengan suatu elemen atau tidak; tidak ada yang bersaing.

Pola untuk Ekstraksi

Selektor yang benar-benar melakukan pekerjaan dalam sebuah scraper.

Kartu produk dalam tata letak grid:

div.product-grid > article.product-card

Tautan ke berkas PDF:

a[href$=".pdf"]

Tautan eksternal:

a[href^="http"]:not([href*="example.com"])

Hook pengujian yang stabil, bukan sebuah kelas:

[data-testid="price"]

Kontainer yang berisi sesuatu:

tr:has(td.error)
article:has(img)
form:has(input:invalid)

Paragraf pertama sebuah artikel, terlepas dari apa yang ada di depannya:

article p:first-of-type

Lewati baris header:

tbody tr:not(:first-child)

Ambil baris kedua hingga kesebelas:

tbody tr:nth-child(n+2):nth-child(-n+11)

Elemen dengan token kelas tertentu, yang dibuat secara programatik:

[class~="card"]

Sel kosong yang ingin Anda kecualikan:

td:not(:empty)

Menulis Selektor yang Tidak Mudah Rusak

Referensi memberi tahu Anda apa saja yang tersedia. Ketahanan berasal dari pemilihan di antara opsi-opsi tersebut, dan perbedaan antara selektor yang tetap berfungsi setelah perancangan ulang dan selektor yang akan rusak minggu depan sepenuhnya bergantung pada apa yang menjadi dasarnya.

Urutkan anchor Anda berdasarkan seberapa sengaja mereka dipilih. Sebuah data-testid ada karena pengembang menempatkannya di sana untuk otomatisasi, sehingga ini adalah elemen paling stabil di halaman. id berada di urutan berikutnya — biasanya disengaja, kadang-kadang dihasilkan secara otomatis. Elemen semantik atau peran ARIA stabil karena mengandung makna. Nama kelas yang ditulis secara manual cukup stabil. Nama kelas yang dihasilkan secara otomatis, seperti css-1x9dj2k, berubah pada setiap proses build dan tidak memiliki nilai apa pun. Selektor posisional adalah yang paling tidak stabil di antara semuanya, karena selektor ini mengkodekan bentuk halaman yang tepat pada satu momen tertentu.

Jadilah sespesifik yang dibutuhkan oleh maknanya, dan jangan lebih dari itu. body > div > div > div.content > p bersifat presisi namun rapuh: penambahan wrapper di mana pun dalam rantai tersebut akan merusaknya. .content p mengekspresikan kebutuhan yang sebenarnya dan tetap berfungsi meski terjadi restrukturisasi. Insting untuk menambah spesifisitas demi keamanan justru menghasilkan hasil yang berlawanan dengan keamanan.

Pilihlah selektor yang gagal dengan jelas. Selektor yang cocok dengan nol elemen menimbulkan masalah yang jelas. Selektor yang cocok dengan terlalu banyak elemen secara diam-diam mengembalikan elemen pertama, yang mungkin masuk akal namun bisa saja salah. Jika diberi pilihan, pilihlah versi yang akan gagal daripada versi yang akan melenceng — div > p daripada div p ketika hubungan tersebut benar-benar langsung.

Simpan selektor di satu tempat. Empat puluh string selektor yang tersebar di seluruh basis kode adalah empat puluh risiko independen. Jika dikumpulkan dalam satu modul dengan nama yang deskriptif, mereka menjadi peta dari apa yang Anda andalkan, dan memperbarui setelah perubahan situs hanya membutuhkan waktu satu jam, bukan satu hari untuk menelusuri kode.

Pastikan bentuk dari apa yang Anda ekstrak. Ini adalah kebiasaan yang mendeteksi pergeseran diam-diam. Jika harga harus sesuai dengan pola mata uang, periksalah. Jika daftar tidak pernah memiliki kurang dari dua puluh item, anggap kurang dari dua puluh sebagai kesalahan. Tanpa ini, selektor yang mulai mencocokkan elemen yang salah akan menghasilkan data yang salah namun terstruktur dengan baik tanpa henti, dan tidak ada yang memicu pengecualian pada titik mana pun.

Simpan HTML yang telah Anda parsing. Ketika sebuah selektor rusak, membandingkan markup lama dengan yang baru akan menunjukkan kepada Anda dengan tepat apa yang berubah dalam hitungan detik. Mengunduh ulang untuk menyelidiki lebih lambat, menghabiskan bandwidth, dan mungkin memberikan Anda halaman yang berbeda dari yang sebenarnya gagal.

Hal-hal yang Masih Belum Dapat Dilakukan oleh CSS

Daftar singkat ini berisi alasan-alasan yang sah untuk menggunakan XPath.

Mencocokkan berdasarkan isi teks. Tidak ada standar :contains(). Standar ini pernah diusulkan namun ditinggalkan, dan tidak ada browser yang mengimplementasikannya. Ini adalah celah terbesar dan alasan mengapa pola "mencari nilai berdasarkan labelnya" menjadi ranah XPath — //dt[normalize-space()='Price']/following-sibling::dd[1] tidak memiliki padanan dalam CSS.

Menavigasi ke leluhur sembarang. :has() menyediakan pemilihan orang tua bersyarat — "div yang mengandung span ini" — tetapi tidak ada sumbu leluhur umum. Menelusuri beberapa tingkat ke atas ke wadah tertentu memerlukan XPath.

Fungsi string. Tidak ada pemotongan, tidak ada substring, tidak ada konversi huruf besar-kecil, tidak ada penggabungan. Apa pun yang Anda cocokkan, Anda memprosesnya setelahnya dalam bahasa pemrograman Anda.

Mengeksekusi kueri XML dengan namespace. CSS tidak memiliki dukungan namespace yang berarti. Untuk sitemap, RSS, atau SOAP, gunakan XPath.

Memilih saudara sebelumnya secara langsung. :has() memberikan efek tersebut — h2:has(+ p) memilih heading — tetapi tidak ada kombinator - yang setara dengan +.

Itulah daftar lengkap untuk keperluan praktis. Segala hal lain yang biasanya orang lakukan dengan XPath, kini dapat dilakukan oleh CSS, dan biasanya dengan kode yang lebih mudah dibaca.

Perbedaan Lingkungan yang Perlu Diperiksa

Hal yang paling sering mengejutkan terkait selektor adalah adanya fitur yang tersedia di tempat lain, bukan di tempat Anda menjalankannya.

Browser mendukung semua yang tercantum di sini, termasuk :has(), :is(), :where(), dan :not() dengan argumen ganda.

Parser sisi server sangat bervariasi. cssselect dari Python, yang digunakan oleh lxml dan Scrapy, menerjemahkan CSS menjadi XPath — yang berfungsi dengan baik untuk selektor klasik dan kurang baik untuk selektor yang lebih baru. Dukungan :has() khususnya tidak universal, dan selektor yang berfungsi di konsol browser mungkin menimbulkan kesalahan atau diam-diam tidak mengembalikan apa pun di parser.

BeautifulSoup menggunakan soupsieve untuk metode select()-nya, yang memiliki cakupan yang baik namun tidak identik, dan sama sekali tidak mendukung XPath.

Playwright dan Selenium menggunakan mesin browser, sehingga dukungannya sesuai dengan browser — dengan Playwright juga menawarkan penentu teks dan peran yang mencakup banyak hal yang tidak dapat diekspresikan oleh CSS.

Kebiasaan praktis: uji selektor di lingkungan yang akan menjalankannya. Konsol browser memang nyaman, tetapi menguji implementasi yang berbeda terhadap DOM pasca-JavaScript, yang merupakan dua hal yang dapat menyesatkan Anda.

Pertanyaan Lainnya

Apa perbedaan antara .card.featured dan .card .featured?

Yang pertama, tanpa spasi, akan mencocokkan satu elemen yang memiliki kedua kelas tersebut. Yang kedua, dengan spasi, akan mencocokkan elemen dengan kelas featured yang berada di dalam elemen dengan kelas card. Satu spasi saja sudah cukup untuk mengubah maknanya secara total, dan ini merupakan kesalahan selektor CSS yang paling umum.

Bagaimana cara memilih elemen induk dalam CSS?

Dengan :has() — div:has(> span.price) memilih div, bukan span. Fitur ini telah tersedia secara luas di berbagai browser sejak Desember 2023. Tidak ada selektor leluhur umum, sehingga untuk mencapai wadah tertentu beberapa tingkat di atasnya masih memerlukan XPath.

Apakah selektor CSS dapat mencocokkan teks?

Tidak. Tidak ada pseudo-class standar :contains(); pseudo-class ini pernah diusulkan namun tidak pernah diadopsi. Pencocokan berdasarkan konten teks memerlukan XPath, atau lokator khusus perpustakaan seperti getByText() dari Playwright.

Apa perbedaan antara :nth-child dan :nth-of-type? `

`:nth-childmenghitung semua anak dari elemen induk;:nth-of-typehanya menghitung elemen dengan tipe yang sama. Jadi,p:first-childtidak akan mencocokkan apa pun jika ada judul di depan, sedangkanp:first-of-type`` akan mencocokkan paragraf pertama terlepas dari apa pun.

Apa fungsi :is() dan apa perbedaannya dengan :where()?

Keduanya menerima daftar selektor dan mencocokkan salah satunya, sehingga mempersingkat selektor yang berulang. Satu-satunya perbedaan adalah spesifisitas: :is() mengadopsi spesifisitas dari argumennya yang paling spesifik, sedangkan :where() selalu memberikan nilai nol — yang menjadikan :where() ideal untuk nilai default yang mudah diganti.

Bagaimana cara kerja spesifisitas CSS?

ID memiliki prioritas lebih tinggi daripada kelas, atribut, dan pseudo-kelas, yang pada gilirannya memiliki prioritas lebih tinggi daripada selektor elemen dan pseudo-elemen, jika dibandingkan komponen per komponen. Gaya inline lebih diutamakan daripada selektor, dan !important lebih diutamakan daripada keduanya. Semua ini tidak berlaku saat Anda menggunakan selektor untuk melakukan kueri, bukan untuk memberi gaya.

Apakah selektor CSS lebih baik daripada XPath untuk penggalian data?

Untuk pemilihan berdasarkan class, id, atribut, dan struktur, ya — lebih singkat dan jelas. Untuk mencocokkan konten teks atau menelusuri ke atas hingga ke leluhur sembarang, XPath diperlukan. Sebagian besar pustaka pengikisan mendukung keduanya, dan menggunakan masing-masing sesuai konteksnya adalah hal yang wajar.

Mengapa selektor saya berfungsi di browser tetapi tidak di pengikis saya?

Ada dua penyebab umum. DOM browser sudah diproses oleh JavaScript, sedangkan parser Anda melihat HTML mentah, sehingga elemen tersebut mungkin tidak ada dalam data yang Anda ambil. Selain itu, implementasi CSS di sisi server tidak mencakup semua selektor modern — khususnya :has() yang tidak didukung secara konsisten di luar browser.

Kesimpulan

Inti kerja selektor CSS sebenarnya cukup sederhana: tipe, kelas, dan id untuk identitas; empat kombinator untuk hubungan; selektor atribut untuk elemen yang dipilih secara sengaja; serta beberapa pseudo-class untuk posisi dan status.

Tiga kebiasaan berikut ini lebih efektif dalam meningkatkan kualitas selektor yang sebenarnya daripada sekadar mengetahui sintaks tambahan. Pilihlah > daripada spasi kosong jika hubungannya benar-benar langsung, karena selektor yang berhenti mencocokkan lebih berguna daripada yang mulai mencocokkan terlalu banyak. Pilihlah atribut data-* daripada nama kelas, karena kelas dihasilkan ulang oleh alat build sedangkan atribut dipilih oleh manusia. Dan pilihlah :nth-of-type daripada :nth-child ketika yang dimaksud adalah "paragraf kedua" daripada "anak kedua".

:has() Apakah penambahan ini layak diadopsi secara sengaja? Pemilihan induk dan kondisi saudara dalam CSS biasa menghilangkan sebagian besar hal yang sebelumnya memaksa orang menggunakan XPath, dan fitur ini telah tersedia secara luas cukup lama untuk diandalkan di browser. Di luar browser, periksa parser Anda terlebih dahulu — di situlah kejutan-kejutan yang tersisa berada.