CSS’de en çok ihtiyaç duyduğumuz özelliklerden birisiydi ebeveyn (parent) seçicisi. Bir ögenin içindeki elemana olup bitene göre CSS tanımı yapma isteği uzun süredir beklenen bir özellikti. Daha önceleri şöyle bir savunma vardı: Tarayıcılar CSS’i yorumlarken dokümanı aşağı yönlü yorumluyor, bundan ötürü bir elemanın yukarı yönlü elemanını seçmesi için tüm ebeveynlere erişmesi gibi durumlar söz konusudur ve bu performans açısından sıkıntılara neden olur. Tabi tarayıcılar son yıllarda ciddi gelişim gösterdi ve bu kabulleri de aşacak çözümleri sunmaya başladılar.

Ebeveyn seçicisi aslında çoğu zaman ihtiyacımız olan bir seçici olmasa da lazım olduğunda ‘ah be olsaydı ne güzel olurdu’ diye içimizden geçirdiğimiz bir seçici.

Nasıl kullanılır?

:has() ebeveyn seçicisi nasıl kullanılır? Örnekle anlaşılması daha kolay olacak.

// cocuklu aile
<div class="aile">
	<div>
		<div class="cocuk"></div>
	</div>
</div>

// cocuksuz aile
<div class="aile"></div>

Yukarıdaki kodda çocuklu ailelere özel kampanya yapmak istersek :)

.aile:has(.cocuk) {
	animation: partiZamani 21s linear;
}

Yukarıdaki kodda hedef .aile elemanı koşul ise .cocukvar mı? yok mu? Koşulun gerçekleştiği durumda tanım uygulanacak.

Tablo örneği

:has() seçicisini duyalı çok oluyor ancak uygulama imkanı yakın zamanda oldu. Aşağıdaki örnekte gördüğünüze benzer bir tablo ihtiyacımız oldu. Burada javascript ile seçim yapıldığında o tablo satırına bir css sınıfı tanımlayarak olabilirdi. Tabi bir işi CSS ile yapmak daha kolay ve mantıklı.

Kodun can alıcı noktası

tbody tr:has(input:checked) td {
  background: #636363;
  color: #fff;
}

Burada input işaretlenmiş tablo satırına tanım yaparak ihtiyacımızı karşıladık.

<figure> örneği

:has() seçicisini anlatırken verilen en popüler örnek: Bir <figure> elemanımızın olduğunu düşünelim. Bu elemanın bazen sadece resim içerirken bazen resim ve <figcaption> içeren çeşitlerinin olduğu durumlar var. Biz <figcaption> olduğu durumlar için. stil tanımlaması yapmak istesek.

figure:has(figcaption) {
  background: white;
  padding: 10px;
}

Kodu ile <figcaption> içeriği olan <figure> elemanına beyaz ardalan ve padding veriyoruz.

Form doğrulama örneği

Bir diğer popüler örnekte form doğrulam için :has() seçicisinden yararlanma örnekleri. Form elemanlarının doğrulaması için CSS sözde sınıflarını :invalid ve :valid kullanıyoruz ancak bu seçicileri kullanarak üstündeki ve öncesindeki elemanlara erişemediğimiz için sorun yaşıyorduk. :has seçicisi burada yardımımıza koştu.

Burada daha önce :focus-within tanımı yazısındaki formu alalım ve buraya e-posta alanı ekleyelim. E-posta kontrolü sonucu hatalı ise farklı bg ve etiketin başına x işareti koyalım.

Burada dikkat etmemiz gereken kısım kodun sonu

label:has(+ input:invalid)::before {
  content: '✖ ';
  color: #ff0024;
}

Hatalı input öncesinde gelenlabel elemanına hata durumunda x işareti ekliyoruz.

Not: Ebeveyn seçicisi sadece üst elemana değil daha önce erişemediğimiz aynı seviye önceki kardeş seçiciye de erişme imkanı sağlıyor.

Bir diğer kod

form:has(input:invalid)::after {
  box-shadow: inset 0 0 60px whitesmoke, inset 20px 0 80px #ff0024, inset -20px 0 80px #ff8f00, inset 20px 0 300px #ff0058, inset -20px 0 300px #ffc200, 0 0 50px #fff, -10px 0 80px #ff004a, 10px 0 80px #ff5b00;
}

Hatalı input’un ebeveyni olan form elemanının ardalanına kırmızı tonlu bir ardalan tanımlıyoruz.

Izgara (grid) örneği

Grid özelliği tanımlanan bir elemanın birincil derecedeki tüm elemanları grid ögesi olur. Grid ögelerinin davranış ve durumuna göre kapsayıcı gride tanım yapmak :has() seçicisi çıkana kadar CSS ile yapmak imkansızdı.

:nth-child ve :nth-last-child sözde sınıfları yardımıyla ve de :has() seçicisinin gücüyle bir grid içeriğinde 2 adet eleman varsa ona göre kod, 3 tane eleman varsa ona göre kod yazabiliyoruz artık.

.grid:has(:nth-child(2):last-child) {
  grid-template-columns: 1fr 1fr;
}

İçinde iki adet öge bulunan bir kapsayıcı gridi yukarıdaki şekilde yakalayıp iki kolonlu bir yapı kurabiliriz. Aynı şekilde

.grid:has(:nth-child(3):last-child) {
  grid-template-columns: 1fr 1fr 1fr;
}

İçinde üç adet öge bulunan kapsayıcı elemana tanım yapabiliriz.

Dört ve fazlası için de

.grid:has(:nth-child(n+4)) {
  grid-template-columns: repeat(4, 1fr);
}

Gerçekten hayat kurtaracak özellik.

Örnekleri çoğaltmak gayet mümkün. Kaynakların altında farklı tip örnekleri paylaşıyorum. Bu örneklere bakarak ufkumuz açılıyor.

Sonuç

Tarayıcı desteği konusunda Firefox hariç tüm tarayıcıların desteği var. Firefox’un çalışmaları var ama henüz tam destek gelmedi. Bu sene sonuna kadar gelmesini bekliyorum.

CSS’in son senelerdeki gelişmelerini heyecanla takip ediyorum. Bayram çocuğu gibi mutlu hissettiriyor. :)

Kalın sağlıcakla.

Kaynaklar

Örnekler

Avatar Popout Efekti

Avatar Popout Efekti uygulaması Devamını oku

Kapsayıcı sorguları (container query)

29 January 2024 tarihinde yayınlandı.

Renk geçişli ve Hareketli kenar çizgileri

22 January 2024 tarihinde yayınlandı.