Panduan Untuk Pemilih Kelas Pseudo CSS Modern yang Baru Didukung

Diterbitkan: 2022-03-10
Ringkasan cepat Draf Editor Kelompok Kerja CSS untuk Penyeleksi Level 4 menyertakan beberapa penyeleksi kelas semu yang sudah memiliki kandidat proposal di sebagian besar browser modern. Panduan ini akan mencakup yang saat ini memiliki dukungan terbaik bersama dengan contoh untuk menunjukkan bagaimana Anda dapat mulai menggunakannya hari ini!

Selektor kelas semu adalah yang dimulai dengan karakter titik dua “ : ” dan cocok berdasarkan status elemen saat ini. Status mungkin relatif terhadap pohon dokumen, atau sebagai respons terhadap perubahan status seperti :hover atau :checked .

:any-link

Meskipun didefinisikan di Selectors Level 4, kelas semu ini telah memiliki dukungan lintas-browser untuk beberapa waktu. Kelas semu any-link akan cocok dengan hyperlink jangkar selama ia memiliki href . Ini akan cocok dengan cara yang setara dengan mencocokkan :link dan :visited sekaligus. Pada dasarnya, ini dapat mengurangi gaya Anda dengan satu pemilih jika Anda menambahkan properti dasar seperti color yang ingin Anda terapkan ke semua tautan terlepas dari status kunjungannya.

 :any-link { color: blue; text-underline-offset: 0.05em; }

Catatan penting tentang spesifisitas adalah bahwa :any-link akan menang melawan a sebagai pemilih bahkan jika a ditempatkan lebih rendah di kaskade karena memiliki kekhususan kelas. Dalam contoh berikut, tautannya akan berwarna ungu:

 :any-link { color: purple; } a { color: red; }

Jadi, jika Anda memperkenalkan :any-link , ketahuilah bahwa Anda harus menyertakannya pada instance a sebagai pemilih jika mereka akan bersaing langsung untuk kekhususan.

:focus-visible

Saya berani bertaruh bahwa salah satu pelanggaran aksesibilitas paling umum di seluruh web adalah menghapus outline pada elemen interaktif seperti tautan, tombol, dan input formulir untuk status :focus . Salah satu tujuan utama dari outline itu adalah untuk berfungsi sebagai indikator visual bagi pengguna yang terutama menggunakan keyboard untuk bernavigasi. Status fokus yang terlihat sangat penting sebagai alat pencari jalan karena pengguna tersebut melakukan tab di seluruh antarmuka dan untuk membantu memperkuat apa yang merupakan elemen interaktif. Secara khusus, fokus yang terlihat tercakup dalam Kriteria Sukses WCAG 2.4.11: Penampilan Fokus (Minimum).

Kelas semu :focus-visible dimaksudkan untuk hanya menampilkan cincin fokus ketika agen pengguna menentukan melalui heuristik bahwa cincin itu harus terlihat. Dengan kata lain: browser akan menentukan kapan harus menerapkan :focus-visible berdasarkan hal-hal seperti metode input, jenis elemen, dan konteks interaksi. Untuk tujuan pengujian melalui komputer desktop dengan input keyboard dan mouse, Anda akan melihat :focus-visible gaya terpasang saat Anda tab ke elemen interaktif tetapi tidak saat Anda mengkliknya, dengan pengecualian input teks dan area teks yang seharusnya menunjukkan :focus-visible untuk semua jenis input fokus.

Catatan : Untuk detail lebih lanjut, tinjau draf kerja dari spesifikasi :focus-visible .

Versi terbaru browser Firefox dan Chromium tampaknya sekarang menangani :focus-visible pada input formulir sesuai dengan spesifikasi yang mengatakan bahwa UA harus menghapus :focus gaya ketika :focus-visible cocok. Safari belum mendukung :focus-visible sehingga kami perlu memastikan gaya :focus disertakan sebagai fallback untuk menghindari penghapusan outline untuk aksesibilitas.

Lebih banyak setelah melompat! Lanjutkan membaca di bawah ini

Diberikan tombol dan input teks dengan kumpulan gaya berikut, mari kita lihat apa yang terjadi:

 input:focus, button:focus { outline: 2px solid blue; outline-offset: 0.25em; } input:focus-visible { outline: 2px solid transparent; border-color: blue; } button:focus:not(:focus-visible) { outline: none; } button:focus-visible { outline: 2px solid transparent; box-shadow: 0 0 0 2px #fff, 0 0 0 4px blue; }

Chromium dan Firefox

  • input
    Hapus dengan benar :focus ketika elemen difokuskan melalui input mouse demi :focus-visible yang menghasilkan perubahan border-color dan menyembunyikan outline pada input keyboard
  • button
    Tidak hanya menggunakan :focus-visible tanpa aturan tambahan untuk button:focus:not(:focus-visible) yang menghilangkan garis luar pada :focus , tetapi akan memungkinkan visibilitas box-shadow hanya pada input keyboard

Safari

  • input
    Terus menggunakan hanya :focus
  • button
    Ini tampaknya sekarang sebagian menghormati maksud dari :focus-visible pada tombol dengan menyembunyikan :focus gaya pada klik, tetapi masih menampilkan :focus gaya pada interaksi keyboard

Jadi untuk saat ini, rekomendasinya adalah untuk terus memasukkan :focus gaya dan kemudian secara bertahap meningkatkan hingga menggunakan :focus-visible yang memungkinkan kode demo. Inilah CodePen bagi Anda untuk melanjutkan pengujian:

Lihat Pena [Pengujian aplikasi :focus-visible](https://codepen.io/smashingmag/pen/MWJZbew) oleh Stephanie Eckles.

Lihat aplikasi Pen Testing dari :focus-visible oleh Stephanie Eckles.

:focus-within

Kelas semu :focus-within memiliki dukungan di antara semua browser modern, dan bertindak hampir seperti pemilih induk tetapi hanya untuk kondisi yang sangat spesifik. Saat dilampirkan ke elemen yang mengandung dan elemen anak cocok untuk :focus , gaya dapat ditambahkan ke elemen yang mengandung dan/atau elemen lain di dalam wadah.

Peningkatan praktis untuk menggunakan perilaku ini adalah menata label formulir saat input terkait memiliki fokus. Agar ini berfungsi, kami membungkus label dan memasukkannya ke dalam wadah, dan kemudian melampirkan :focus-within ke wadah itu serta memilih label:

 .form-group:focus-within label { color: blue; }

Hal ini menyebabkan label berubah menjadi biru saat input memiliki fokus.

Demo CodePen ini juga termasuk menambahkan garis besar langsung ke wadah .form-group :

Lihat Pena [Pengujian aplikasi :focus-within](https://codepen.io/smashingmag/pen/xxgmREq) oleh Stephanie Eckles.

Lihat aplikasi Pen Testing dari :fokus-dalam oleh Stephanie Eckles.

:is()

Juga dikenal sebagai pseudo-class "cocok dengan semua", :is() dapat mengambil daftar pemilih untuk dicoba dicocokkan. Misalnya, alih-alih mencantumkan gaya heading satu per satu, Anda dapat mengelompokkannya di bawah pemilih :is(h1, h2, h3) .

Beberapa perilaku unik tentang daftar pemilih :is() :

  • Jika pemilih yang terdaftar tidak valid, aturan akan terus cocok dengan pemilih yang valid. Mengingat :is(-ua-invalid, article, p) aturan akan cocok dengan article dan p .
  • Spesifisitas yang dihitung akan sama dengan pemilih yang lulus dengan spesifisitas tertinggi. Misalnya, :is(#id, p) akan memiliki spesifisitas #id — 1.0.0 — sedangkan :is(p, a) akan memiliki spesifisitas 0,0.1.

Perilaku pertama mengabaikan pemilih yang tidak valid adalah manfaat utama. Saat menggunakan pemilih lain dalam grup di mana satu pemilih tidak valid, browser akan membuang seluruh aturan. Ini berperan untuk beberapa contoh di mana prefiks vendor masih diperlukan, dan pengelompokan pemilih dengan prefiks dan non-prefiks menyebabkan aturan gagal di antara semua browser. Dengan :is() Anda dapat dengan aman mengelompokkan gaya tersebut dan gaya tersebut akan diterapkan saat cocok dan diabaikan saat tidak cocok.

Bagi saya, mengelompokkan gaya heading seperti yang disebutkan sebelumnya sudah merupakan kemenangan besar dengan pemilih ini. Ini juga jenis aturan yang saya rasa nyaman untuk digunakan tanpa fallback saat menerapkan gaya non-kritis, seperti:

 :is(h1, h2, h3) { line-height: 1.2; } :is(h2, h3):not(:first-child) { margin-top: 2em; }

Dalam contoh ini (yang berasal dari gaya dokumen di proyek saya SmolCSS), memiliki tinggi line-height yang lebih besar yang diwarisi dari gaya dasar atau kekurangan margin-top sebenarnya bukan masalah bagi browser yang tidak mendukung. Ini hanya kurang dari ideal. Apa yang tidak ingin Anda gunakan :is() untuk waktu yang lama adalah gaya tata letak kritis seperti Grid atau Flex yang secara signifikan mengontrol antarmuka Anda.

Selain itu, ketika dirantai ke pemilih lain, Anda dapat menguji apakah pemilih dasar cocok dengan pemilih turunan dalam :is() . Misalnya, aturan berikut hanya memilih paragraf yang merupakan turunan langsung dari artikel. Selektor universal sedang digunakan sebagai referensi ke pemilih basis p .

 p:is(article > *)

Untuk dukungan terbaik saat ini, jika Anda ingin mulai menggunakannya, Anda juga ingin menggandakan gaya dengan menyertakan aturan duplikat menggunakan :-webkit-any() dan :matches() . Ingatlah untuk membuat aturan individual ini, atau bahkan browser pendukung akan membuangnya! Dengan kata lain, sertakan semua hal berikut:

 :matches(h1, h2, h3) { } :-webkit-any(h1, h2, h3) { } :is(h1, h2, h3) { }

Patut disebutkan pada titik ini adalah bahwa bersama dengan pemilih yang lebih baru itu sendiri adalah variasi terbaru dari @supports yaitu @supports selector . Ini juga tersedia sebagai @supports not selector .

Catatan : Saat ini (dari browser modern), hanya Safari yang tidak mendukung aturan ini.

Anda dapat memeriksa dukungan :is() dengan sesuatu seperti berikut ini, tetapi Anda sebenarnya akan kehilangan dukungan untuk Safari karena Safari mendukung :is() tetapi tidak mendukung @supports selector .

 @supports selector(:is(h1)) { :is(h1, h2, h3) { line-height: 1.1; } }

:where()

Kelas semu :where() hampir identik dengan :is() kecuali untuk satu perbedaan kritis: ia akan selalu memiliki spesifisitas nol. Ini memiliki implikasi yang luar biasa bagi orang-orang yang sedang membangun kerangka kerja, tema, dan sistem desain . Menggunakan :where() , seorang penulis dapat mengatur default dan pengembang hilir dapat menyertakan penggantian atau ekstensi tanpa bentrokan spesifik.

Pertimbangkan kumpulan gaya img berikut. Menggunakan :where() , bahkan dengan pemilih spesifisitas yang lebih tinggi, spesifisitas tetap nol. Dalam contoh berikut, batas warna mana yang menurut Anda akan dimiliki gambar?

 :where(article img:not(:first-child)) { border: 5px solid red; } :where(article) img { border: 5px solid green; } img { border: 5px solid orange; }

Aturan pertama tidak memiliki kekhususan karena sepenuhnya terkandung dalam :where() . Jadi langsung melawan aturan kedua, aturan kedua menang. Memperkenalkan pemilih elemen-saja img sebagai aturan terakhir, itu akan menang karena kaskade. Ini karena ia akan menghitung ke spesifisitas yang sama dengan aturan :where(article) img karena bagian :where() tidak meningkatkan spesifisitas.

Menggunakan :where() bersama fallback sedikit lebih sulit karena fitur nol-spesifisitas karena fitur itu mungkin mengapa Anda ingin menggunakannya di atas :is() . Dan jika Anda menambahkan aturan fallback, aturan tersebut kemungkinan akan mengalahkan :where() karena sifatnya. Dan, ia memiliki dukungan keseluruhan yang lebih baik daripada @supports selector , jadi mencoba menggunakannya untuk membuat fallback tidak akan memberikan banyak (jika ada) keuntungan. Pada dasarnya, waspadai ketidakmampuan untuk membuat fallback dengan benar untuk :where() dan periksa dengan cermat data Anda sendiri untuk menentukan apakah aman untuk mulai digunakan untuk audiens unik Anda.

Anda dapat menguji lebih lanjut :where() dengan CodePen berikut yang menggunakan pemilih img dari atas:

Lihat Pena [Menguji kekhususan `:where()`](https://codepen.io/smashingmag/pen/jOyXVMg) oleh Stephanie Eckles.

Lihat Pen Testing :where() spesifisitas oleh Stephanie Eckles.

Ditingkatkan :not()

Pemilih dasar :not() telah didukung sejak Internet Explorer 9. Tetapi Selektor Level 4 meningkatkan :not() dengan mengizinkannya mengambil daftar pemilih, seperti :is() dan :where() .

Aturan berikut memberikan hasil yang sama dalam mendukung browser:

 article :not(h2):not(h3):not(h4) { margin-bottom: 1.5em; } article :not(h2, h3, h4) { margin-bottom: 1.5em; }

Kemampuan :not() untuk menerima daftar pemilih memiliki dukungan browser modern yang hebat.

Seperti yang kita lihat dengan :is() , Enhanced :not() juga dapat berisi referensi ke pemilih dasar sebagai turunan menggunakan * . CodePen ini menunjukkan kemampuan ini dengan memilih tautan yang bukan turunan dari nav .

Lihat Pena [Menguji :not() dengan pemilih turunan](https://codepen.io/smashingmag/pen/BapvQQv) oleh Stephanie Eckles.

Lihat Pengujian Pena :not() dengan pemilih turunan oleh Stephanie Eckles.

Bonus : Demo sebelumnya juga menyertakan contoh chaining :not() dan :is() untuk memilih gambar yang bukan saudara kandung yang berdekatan dari elemen h2 atau h3 .

Diusulkan tetapi "berisiko" — :has()

Kelas semu terakhir yang merupakan proposal yang sangat menarik tetapi tidak memiliki browser saat ini yang mengimplementasikannya bahkan dalam cara eksperimental adalah :has() . Bahkan, tercantum dalam Draft Editor Selector Level 4 sebagai “berisiko” yang berarti diakui mengalami kesulitan dalam menyelesaikan implementasinya sehingga dapat dikeluarkan dari rekomendasi.

Jika diterapkan, :has() pada dasarnya akan menjadi "pemilih induk" yang telah lama ingin dimiliki oleh banyak orang CSS. Ini akan bekerja dengan logika yang mirip dengan kombinasi keduanya :focus-within dan :is() dengan pemilih keturunan, di mana Anda mencari keberadaan keturunan tetapi gaya yang diterapkan akan menjadi elemen induk.

Mengingat aturan berikut, jika navigasi berisi tombol, maka navigasi akan mengalami penurunan padding atas dan bawah:

 nav { padding: 0.75rem 0.25rem; nav:has(button) { padding-top: 0.25rem; padding-bottom: 0.25rem; }

Sekali lagi, ini saat ini tidak diterapkan di browser mana pun bahkan secara eksperimental — tetapi ini menyenangkan untuk dipikirkan! Robin Rendle memberikan wawasan tambahan tentang pemilih masa depan ini di CSS-Tricks.

Honorable Mention dari Level 3: :empty

Kelas semu yang berguna yang mungkin Anda lewatkan dari Selectors Level 3 adalah :empty yang cocok dengan elemen ketika tidak memiliki elemen anak, termasuk node teks.

Aturan p:empty akan cocok dengan <p></p> tetapi tidak cocok dengan <p>Hello</p> .

Salah satu cara Anda dapat menggunakan :empty adalah dengan menyembunyikan elemen yang mungkin merupakan placeholder untuk konten dinamis yang diisi dengan JavaScript. Mungkin Anda memiliki div yang akan menerima hasil pencarian, dan saat diisi, ia akan memiliki batas dan beberapa bantalan. Tetapi tanpa hasil, Anda tidak ingin itu menghabiskan ruang di halaman. Menggunakan :empty Anda dapat menyembunyikannya dengan:

 .search-results:empty { display: none; }

Anda mungkin berpikir untuk menambahkan pesan dalam keadaan kosong dan tergoda untuk menambahkannya dengan pseudo-element dan content . Perangkapnya di sini adalah bahwa pesan mungkin tidak tersedia untuk pengguna teknologi bantu yang tidak konsisten pada apakah mereka dapat mengakses content . Dengan kata lain, untuk memastikan jenis pesan “tidak ada hasil” dapat diakses , Anda ingin menambahkannya sebagai elemen nyata seperti paragraf ( aria-label tidak lagi dapat diakses untuk div tersembunyi).

Sumber Daya untuk Mempelajari Tentang Selector

CSS memiliki lebih banyak pemilih termasuk kelas semu. Berikut adalah beberapa tempat untuk mempelajari lebih lanjut tentang apa yang tersedia:

  • Dokumentasi pemilih CSS MDN mencakup daftar kategori yang komprehensif;
  • Saya telah menulis panduan dua bagian untuk pemilih CSS tingkat lanjut, Anda dapat mulai dengan bagian satu;
  • Bersenang-senang belajar tentang pemilih CSS dengan game CSS Diner;
  • Kitty Giraudel membuat alat penjelasan pemilih yang akan memecah dan menjelaskan bagian dari pemilih yang disediakan.