CSS bizi dinliyor. Hayır, öyle değil. Aksine, CSS, JavaScript olaylarına yanıt vermemize yardımcı olmak için giderek daha fazla sözde sınıf biriktiriyor, böylece bunu JavaScript'in kendisiyle yapmak zorunda kalmıyoruz. Ancak sözde sınıflar olayları değil durumları izlerken, bazen kesinlikle olay dinleyicileri gibi hissedebilirler (CSS bağlamında gerçekten önemli olduğu söylenemez).
Sonra tekrar, bugünlerde CSS nedir? Örneğin, Animasyon Tetikleyicileri spesifikasyonunda, temel olarak olayları dinleyen ve animasyonları tetikleyen bir olay tetikleyici teklifi var. Yine de bana sorarsanız, sözdizimi bundan çok daha fazlasını yapabilir (düşünün: invoker komutları ancak CSS için).
Ancak günümüzün gerçekliğinde kalabilmek için, aynı şeyi event-trigger için yapmadan önce, size bir nevi olay dinleyicileri olan farklı CSS sözde sınıfları boyunca yol göstereceğim ve burada şu anda desteklenmeyen bu özelliğin nasıl çalışacağını (sanırım) göstereceğim.
Detaylar ve Etkileri
: üzerine gelin ve :aktif
:hover durumu, pointerenter olayının tetiklendiği andan pointerleave olayının tetiklendiği ana kadar olan anı yakalar; bu, sözde sınıfların neden olay değil de durum olduğunu mükemmel bir şekilde gösterir.
:active, o anda fare, parmak veya kalemle basılan hedefle (örneğin, bir bağlantı veya düğme) eşleşir; bu da onu pointerdown ve pointerup / pointercancel'e benzer hale getirir.
Bu arada, pointer-events: none CSS bildirimi, işaretçi olaylarının seçilen öğe üzerinde tetiklenmesini engeller!
Nasıl Önlem Alınmalı?
:odak ve :odak-görünür
:focus sözde sınıfı, odaklanma ve bulanıklaştırma (odaklanma) JavaScript olaylarına benzer, ancak :focus-visible biraz daha karmaşıktır. :focus-visible, :focus tetiklendiğinde tetiklenir, ancak buna ek olarak tarayıcı, bir odak göstergesinin gösterilip gösterilmeyeceğini belirlemek için çeşitli buluşsal yöntemler kullanır. Kullanıcı klavyeyle mi çalışıyor? Öğe bir form kontrolü mü? Bu gerçekten CSS'nin sunduğu şeyleri takdir etmemi sağlıyor. Aslında bunu JavaScript kullanarak halletmenin en iyi yolu CSS sözde sınıfını sorgulamaktır:
element.addEventListener("focus", (event) => { if (event.target.matches(":focus-visible")) { /* Bir şeyler yapın */ } });
Uzmanların Görüşleri
JavaScript, "Eğer A Y ise, o zaman Z'den B'ye yapın" türünden konularda çok başarılıdır. DOM'da geçiş yapabilir, olay yayılımından yararlanabilir ve çok daha fazlasını yapabiliriz. Bu bakımdan CSS biraz sınırlı gelebilir. Ancak CSS hızla gelişiyor. Kaydırmayla yönlendirilen animasyonlar gibi birçok yeni "şunu yap" özelliği var ve gelecekte daha fazlasına sahip olacak. HTML, tümü CSS özelliklerine sahip olan
Aslında bunların bir kısmına daha sonra değineceğim. Daha bütünsel bir anlamda elimizde, bir çocuğun odağı varsa eşleşen :focus-with ve geçerli herhangi bir seçiciyi kabul eden ve iki seçici arasında böyle bir ilişki varsa eşleşen :has() bulunur.
Örneğin, bu iki seçici tamamen aynı şeyi yapar:
Önemli Gelişmeler
form:focus-within { /* İçerideki bir şey odağa sahip olduğunda forma stil verin */ } form:has(:focus) { /* İçerideki bir şeye odaklandığında forma stil verin */ }
:checked'in ne yaptığı oldukça açık. Onunla en çok eşanlamlı olan JavaScript olayı, ,
Çeki dinlemek için şöyle bir şey yaparız:
checkbox.addEventListener("değiştir", (event) => { if (event.target.checked) { /* İşaretlendi */ } else { /* İşaretlenmedi */ } });
Teknik Analiz
CSS sözde sınıfları genellikle iki JavaScript olayı (örneğin, pointerenter ve pointerleave) arasındaki anı yakalar, ancak bunu yapmadıklarında yukarıdaki gibi mantığı ele alırlar.
Gizli mantık işlemenin birkaç örneğine daha bakalım.
Sonuç ve Değerlendirme
Geçerlilik hem :valid hem de :invalid sözde sınıfları kullanılarak kontrol edilebildiğinden, burada :not() sözde sınıf işlevine ihtiyacımız yok, ancak JavaScript tarafında geçerli bir olay yoktur (yalnızca geçersiz). Bununla birlikte, eğer JavaScript kullanıyorsanız, checkValidity() yöntemini (aslında false değerini döndürürse geçersiz olayı tetikleyen) checkValidity() yöntemini, giriş, değişiklik, bulanıklık (bir öğeden uzaklaşırken geçerliliği kontrol etmek için) veya gönder (aşağıdaki gibi gönderirken tüm formun geçerliliğini kontrol etmek için) için olay dinleyicisinin geri çağrısında çağırmak isteyeceksiniz.
form.addEventListener("submit", () => { if (form.checkValidity()) { /* Tüm form kontrolleri geçerlidir */ } else { /* Bir form kontrolü geçersiz (geçersiz olay tetiklenir) */ } });
Sistem Güvenliği
Bunu geçersiz olayı tetiklemeyen ancak bize bir form denetiminin neden geçerli veya geçersiz olduğunu söyleyen ValidityState nesnesiyle de yapabiliriz. HTML form doğrulamanın yaptığı gibi:
input.addEventListener("input", () => { if (input.validity.valid) { /* Giriş geçerlidir */ } else { /* Giriş geçersiz (geçersiz olay tetiklenmez) */ } });
Gelecekte Ne Bekleniyor?
HTML form doğrulamayla ilgili olan şey, ön ucun tamamıyla ilgilenmesidir, ancak ihtiyacınız olan varsayılan olmayan bir davranış varsa, aradığınız şey checkValidity() veya ValidityState'dir.
Sözde sınıflar her iki şekilde de çalışacaktır. Aslında biraz fazla iyi! Gözden kaçması kolay bir şey, form kontrollerinin :valid veya :invalid öğelerini hemen tetiklemesidir. Ancak :user-valid ve :user-invalid, tetiklemeden önce kullanıcıların bir değer sağlamasını ve odaklanmayı bırakmasını bekler. Bu aslında change olayının yaptığı şeydir (öğe bir onay kutusu, radyo düğmesi, açılır liste, renk seçici veya aralık kaydırıcısı olmadığı sürece) ve onu giriş olayından farklı kılan şeydir.
Otomatik doldurma için bir JavaScript olayı veya bunu JavaScript kullanarak algılamanın temiz bir yolu yoktur, ancak bir :autofill sözde sınıfı vardır.
Medya öğesi sözde sınıfları
Medya öğesi sözde sınıfları hala yenidir. Henüz Chrome tarafından desteklenmiyorlar ve Firefox'a yakın zamanda geldiler, ancak Interop 2026'nın bir parçası ve yakında
Sözde sınıf JavaScript olayı eşdeğeri :ara belleğe alma bekliyor :sessiz ses seviyesi değişimi (ancak aşağıya bakın) :duraklatıldı duraklatma :oynatılıyor oynatılıyor (oynatmıyor) :arıyor aranıyor :duraklatıldı durduruldu :ses-kilitlendi Yok, aşağıya bakın
Sessizliği algılamak için Volumechange olayını kullanın:
audio.addEventListener("ses değişimi", () => { if (audio.muted) { // Sessize alındı } else { // Sessize alınmadı } });
Ses seviyesi kilidini algılamak, ses seviyesini değiştirmeye çalışmak ve başarıyı kontrol etmek anlamına gelir. En iyi yaklaşım tamamen yeni bir öğe oluşturmaktır, böylece gerçek öğe üzerinde hacim değişikliğini tetiklememiş oluruz:
// Video oluştur const video = document.createElement("video"); // Sesi değiştir video.volume = 0,5; if (video.volume !== 0,5) { // Ses seviyesi kilitli } else { // Ses seviyesi kilitli değil }
(Veya CSS yazıyorsanız :volume-locked sözde sınıfını kullanmak için.)
Tahmin edebileceğimiz gibi, bir popover,
element.addEventListener("toggle", () => { if (element.open) { /* Popover/dialog/details açık */ } else { /* Popover/dialog/details açık değil */ } });
Ancak CSS, kutudan çıktığı gibi bu sözde sınıfları sunar:
:popover-open (popover'lar için)
(popover'lar için) :open (
(ve elemanları için) :modal (modal
Tam ekran öğelerinden bahsetmişken…
:fullscreen sözde sınıfı, içinde koşullu olarak hazırlanmış fullscreenchange JavaScript olayıyla eşanlamlıdır:
document.addEventListener("fullscreenchange", () => { if (document.fullscreenElement) { /* fullscreenElement tam ekrandır */ } else { /* Hiçbir şey tam ekran değildir (fullscreenElement is null) */ } });
Bir URL karması (örneğin, #contact ) bir öğenin kimliğiyle (örneğin,
window.addEventListener("hashchange", () => { const target = document.getElementById(window.location.hash.substring(1)); if (target) { /* Eşleşen öğe bulundu */ } else { /* Eşleşen öğe bulunamadı */ } });
Sonuç (ama aslında değil)
Bu bir "JavaScript kötü" rantından ziyade, JavaScript'in sunduğu cerrahi kontrolü unutmadan CSS'nin neleri basitleştirdiğine dair bir takdirdir. Bir şeyleri yapmanın daha fazla yolu asla kötü bir şey değildir.
Ve bu notta hızlıca event-trigger'dan bahsetmek istiyorum.
Gerçek olay dinleyicileri (olay tetikleyici)
Aynı modülde oldukları için Chrome kaydırmayla tetiklenen animasyonları uyguladığında etkinlik tetikleyicileriyle karşılaştım, ancak henüz herhangi bir web tarayıcısı tarafından desteklenmiyorlar, bu nedenle herhangi bir hata yaparsam özür dilerim. Hadi dalalım.
event-trigger-name basit bir kesikli kimliği kabul edecektir:
düğme { olay-tetikleyici-adı: --olay; }
event-trigger-source aslında olay dinleyicisi olacaktır.
Aşağıdaki anahtar kelimeleri kabul edecektir:
düğme { olay-tetikleyici-kaynak: tıklayın; }
İlgi anahtar sözcüğünün yaklaşmakta olan Interest Invoker API'sine atıfta bulunduğunu, oysa etkinleştirme anahtar sözcüğünün şunlara bağlı olabileceğini düşünüyorum: o eleman. Örneğin
Neyse, olaylar animasyonları tetikleyecek. Öncelikle bir @keyframes animasyonu oluşturuyorduk, ardından onu animasyon yapılacak öğeye ekliyorduk, ancak animasyon, etkinlik tarafından tetiklenene kadar çalışmazdı (oysa normalde hemen çalışırlardı).
@keyframes yavaş yavaş belirir { from { opaklık: 0; } ila { opaklık: 1; } } div { animasyon: her ikisi de 300 ms'de yavaş yavaş açılır; }
Daha sonra event tetiklendiğinde animasyonun da tetiklenmesini sağlıyoruz. Bunu, animasyonun yanında animasyon-tetikleyiciyi ayarlayarak, kesikli kimliğe ( --event ) atıfta bulunarak yaparız. Bunun, bir öğenin olayının diğerinin animasyonunu tetiklemesine izin verme gibi isteğe bağlı bir faydası vardır. İşte bu sefer olay tetikleyicinin kısaltmasını kullanan kısa bir örnek:
@keyframes yavaş yavaş belirir { from { opaklık: 0; } ila { opaklık: 1; } } butonu { /* Tıklandığında, --event animasyonunu tetikle */ event-trigger: --event click; } div { /* --event tetiklendiğinde, animasyonu ileriye doğru oynat */ Animation-trigger: --event play-forwards; /* Animasyon */ animasyon: her ikisi de 300 ms'de yavaş yavaş kaybolur; }
Durum bilgisi olmayan olay tetikleyicisi buna denir. Bir düşünün; bir tıklamanın tıklamasını kaldıramazsınız, değil mi? Ancak ilgimizi kaybedebiliriz, dolayısıyla durum dolu, olayla tetiklenen bir animasyon şöyle görünecektir (bir / ile ayrılmış iki olayın ve her durum için bir tane olmak üzere iki animasyon eyleminin sözdizimine dikkat edin):
@keyframes yavaş yavaş belirir { from { opaklık: 0; } ila { opaklık: 1; } } butonu { /* ilgi (giriş) / ilgi (çıkış) */ event-trigger: --event ilgi / ilgi; } div { /* İlgiyle ileri oynat, kaybettiğinde geri oynat */ Animation-trigger: --event play-forwards play-backwards; /* Animasyon */ animasyon: her ikisi de 300 ms'de yavaş yavaş kaybolur; }
Kabul edilebilir animasyon eylemleri şunları içerir:
İşe yaramayacak birçok etkinlik ve animasyon eylemi kombinasyonu vardır, ancak bunları kullanmak mantıklı olmayacağından bunlardan kaçınmak kolay olacaktır. Bununla birlikte, Animation-trigger yalnızca sıfırlanabilen bir animasyon alt özelliği olduğundan, birden fazla farklı animasyonu tetikleyebiliriz. İşte kaba bir örnek:
animasyon-adı: animasyonA, animasyonB; animasyon-tetikleyici: --eventA oynat, --eventB tekrar oynat;
W3C'nin bu özellikle nasıl ilerlediğine bağlı olarak olasılıklar sonsuzdur (özellik, olayın köpürmesine izin verildiğinden bahseder!), ancak keşke HTML'nin Invoker Komutları API'si ile yaptığı gibi olay tetikleyicileri ile JavaScript yöntemlerini çağırabilseydik.
Ne düşünüyorsun? Doğru yönde atılmış bir adım mı, yoksa CSS'nin kendi şeridinde kalması mı gerekiyor?