İçeriğe geç
academia.sh

Ders 06 / 26

Sözde Sınıflar ve Sözde Elemanlar

Belgede yazılı olmayan durumları seçen sözde sınıflar, nth-child aritmetiği, mantıksal seçiciler ve ağaçta bulunmayan içerik üreten sözde elemanlar.

İçindekiler

Şimdiye kadarki bütün seçiciler belgede yazılı olan bir şeye baktı: öge adı, sınıf, kimlik, öznitelik, ağaçtaki konum. Belgede yazılı olmayan bilgiler de vardır. Bir bağlantının üzerinde durulup durulmadığı, bir form alanının odakta olup olmadığı, bir satırın kaçıncı sırada bulunduğu — bunların hiçbiri işaretlemede geçmez, çünkü hiçbiri belgenin bir özelliği değildir.

Bu ders iki mekanizmayı tanımlar: belgede yazılı olmayan durumları seçen sözde sınıfları ve belge ağacında hiç bulunmayan parçaları hedefleyen sözde elemanları. İkisi farklı işler görür ve yazımdaki tek fark iki nokta üst üstenin sayısıdır.

Sözde Sınıf Bir Durumu Seçer

Sözde sınıf (pseudo-class) tek iki nokta üst üsteyle yazılır ve seçiciye, ögenin o andaki durumuna ilişkin bir koşul ekler. İki aileye ayrılır.

Birinci aile etkileşim durumunu sorar: :hover işaretleyici ögenin üzerindeyken, :focus öge klavye odağını taşırken, :active öge etkinleştirilirken, :disabled bir denetim devre dışıyken, :checked bir seçenek işaretliyken, :invalid bir alanın değeri kısıtları sağlamıyorken eşleşir. Bu durumların hiçbiri belgede yazılı değildir; kullanıcı etkileşimi ya da doğrulama sonucudur.

İkinci aile ağaçtaki konumu sorar: :first-child, :last-child, :only-child, :empty, :root ve sayılı bir ailenin başı olan :nth-child().

nth-child Bir Aritmetik İfadedir

:nth-child() bir sayı değil, bir formül alır: an+b. Burada n sıfırdan başlayarak artan bir tam sayıdır; formülün ürettiği ve 1 ile kardeş sayısı arasında kalan her değer bir sıraya karşılık gelir.

Aşağıdaki program bu formülü çözer ve dokuz satırlık bir ölçüm çizelgesinde hangi sıraların eşleştiğini listeler.

// nth-hesap.mjs — :nth-child(an+b) formulunu cozer ve eslesen siralari listeler
function ayristir(ifade) {
  const s = ifade.replace(/\s+/g, "").toLowerCase();
  if (s === "odd")  return { a: 2, b: 1 };
  if (s === "even") return { a: 2, b: 0 };
  const m = s.match(/^([+-]?\d*)n([+-]\d+)?$/);
  if (!m) return { a: 0, b: Number(s) };
  const aMetin = m[1];
  const a = aMetin === "" || aMetin === "+" ? 1 : aMetin === "-" ? -1 : Number(aMetin);
  return { a, b: m[2] ? Number(m[2]) : 0 };
}

// n = 0,1,2,... icin an+b degeri; 1 <= sira <= toplam olanlar eslesir
function eslesenler(ifade, toplam) {
  const { a, b } = ayristir(ifade);
  const c = [];
  for (let sira = 1; sira <= toplam; sira++) {
    if (a === 0) { if (sira === b) c.push(sira); continue; }
    const n = (sira - b) / a;
    if (Number.isInteger(n) && n >= 0) c.push(sira);
  }
  return { a, b, eslesen: c };
}

const TOPLAM = 9; // olcum cizelgesinde dokuz satir
for (const ifade of ["odd", "even", "3", "2n+1", "3n", "3n+1", "-n+3", "n+4", "5n-2"]) {
  const { a, b, eslesen } = eslesenler(ifade, TOPLAM);
  const formul = `${a}n${b >= 0 ? "+" : ""}${b}`;
  console.log(`:nth-child(${ifade.padEnd(5)}) = ${formul.padEnd(7)} -> ${eslesen.join(" ") || "(bos)"}`);
}
:nth-child(odd  ) = 2n+1    -> 1 3 5 7 9
:nth-child(even ) = 2n+0    -> 2 4 6 8
:nth-child(3    ) = 0n+3    -> 3
:nth-child(2n+1 ) = 2n+1    -> 1 3 5 7 9
:nth-child(3n   ) = 3n+0    -> 3 6 9
:nth-child(3n+1 ) = 3n+1    -> 1 4 7
:nth-child(-n+3 ) = -1n+3   -> 1 2 3
:nth-child(n+4  ) = 1n+4    -> 4 5 6 7 8 9
:nth-child(5n-2 ) = 5n-2    -> 3 8

Üç satır ayrıca okunmalıdır. odd ve even anahtar sözcükleri 2n+1 ve 2n formüllerinin adlarıdır; ayrı bir mekanizma değildir. Negatif katsayılı -n+3 “ilk üç” anlamına gelir: n büyüdükçe değer küçülür ve 1’in altına düştüğünde eşleşme biter. Karşıtı olan n+4 ise “dördüncüden sonuna kadar” demektir. Bu ikisi, bir aralığı seçmenin yoludur.

Bir uyarı: :nth-child() bütün kardeşleri sayar, türe bakmaz. Bir bölümde bir başlık ve ardından paragraflar varsa, ilk paragraf p:nth-child(1) ile eşleşmez — o sırada başlık durur. Türe göre saymak gerekiyorsa :nth-of-type() yazılır; bu, yalnızca aynı öge adını taşıyan kardeşleri sayar.

Mantıksal Seçiciler

Dört sözde sınıf, seçici listesi alır ve mantıksal işlem yapar.

:is() içindeki listeden herhangi biriyle eşleşen ögeleri döndürür; uzun seçicileri kısaltır. :where() aynı eşlemeyi yapar ama özgüllüğe sıfır katkı verir — bu ayrımın neden önemli olduğunu bir sonraki derste hesapla göreceğiz.

:is(h1, h2, h3) + p { margin-block-start: 0.5em; }

Bu kural, üç ayrı kural yazmakla aynı ögeleri seçer.

:not() listedeki hiçbiriyle eşleşmeyen ögeleri döndürür:

.olcum-cizelgesi td:not(.ad) { text-align: right; }

:has() ise yönü tersine çevirir: bir ögeyi, içeriğine göre seçer. tr:has(td.eksik) seçicisi, içinde eksik hücre bulunan satırları döndürür. Bu, birleştiricilerle yapılamayan bir şeydir; birleştiriciler yalnızca sağdaki ögeyi seçebiliyordu.

Bir seçicinin gerçekleştirimlerce tanınıp tanınmadığı sınanabilir. Önceki derslerde tanınmayan bir seçicinin kuralın tamamını düşürdüğünü görmüştük; bu, sınamanın da yolunu verir:

@supports selector(:has(*)) {
  tr:has(td.eksik) { background-color: #fbf4f4; }
}

@supports bloğu, içindeki koşul sağlanmazsa bloğun tamamını yok sayar. Özellik saptama yazmak, bir özelliğin desteklendiğini varsaymaktan farklıdır: koşul sağlanmadığında sayfanın hangi hâlde kalacağı yazar tarafından belirlenmiş olur.

Sözde Eleman Bir Parçayı Hedefler

Sözde eleman (pseudo-element) çift iki nokta üst üsteyle yazılır ve belge ağacında bulunmayan bir parçayı hedefler.

::first-line bir paragrafın ilk satırını, ::first-letter ilk harfini seçer. Bu ikisi belgede öge olarak yoktur; satır bölünmesi yerleşim sonucunda oluşur ve kutunun genişliği değişince ilk satırın kapsamı da değişir.

::marker liste madde işaretini, ::placeholder bir form alanının yer tutucu metnini, ::selection kullanıcının seçtiği metin aralığını hedefler.

::before ve ::after ise farklıdır: bir parçayı seçmezler, üretirler. İkisi de content özelliği yazılmadan var olmaz.

td.eksik::after { content: " —"; }

Bu kural, eksik ölçüm hücrelerinin içeriğinin sonuna bir tire ekler. Üretilen içerik ögenin içindedir, dışında değil: ::before ögenin ilk çocuğu, ::after son çocuğu gibi davranır.

Üretilmiş içeriğin iki sınırı vardır ve ikisi de tasarım gereğidir.

Birincisi, belgede yoktur. Metin olarak seçilip kopyalanması, arama motoru tarafından dizinlenmesi ya da yardımcı teknolojiye aktarılması güvence altında değildir. Bu yüzden anlam taşıyan hiçbir metin buraya yazılmaz. “Eksik” bilgisi belgede bir sınıf ve gerekiyorsa görünür bir metinle bildirilmeli; sözde eleman yalnızca görsel işaret eklemelidir.

İkincisi, seçilemez. Bir sözde elemanın içinde başka bir seçici çalışmaz; üretilen içeriğin kendi alt yapısı yoktur.

Yazım kuralına ilişkin bir not: çift iki nokta yazımı sözde elemanı sözde sınıftan ayırmak için tanımlanmıştır. Eski gerçekleştirimlerle uyum için :before yazımı da kabul edilir; ayrımı korumak adına bu kursta çift iki nokta kullanılır.

İstasyon Sayfasının Durum Biçemleri

/* istasyon.css — 5. adım: durumlar ve sıralar */
.olcum-cizelgesi tbody tr:nth-child(odd) { background-color: #f5f7f8; }
.olcum-cizelgesi tbody tr:last-child     { border-block-end: none; }
.olcum-cizelgesi td:not(.ad)             { text-align: right; }
.olcum-cizelgesi td.eksik::after         { content: " —"; color: #8a5b00; }

a:hover                { text-decoration-thickness: 2px; }
a:focus-visible        { outline: 3px solid #143a52; outline-offset: 2px; }
input:invalid          { border-color: #8a1c1c; }
input:disabled         { color: #6b767f; }

İkinci grubun ilk iki kuralı bir ayrımı taşır. :hover yalnızca işaretleyici aygıtlarda oluşan bir durumdur; klavyeyle gezen bir kullanıcı hiçbir zaman ona ulaşmaz. Bu yüzden :hover ile verilen her ipucunun bir odak karşılığı olmalıdır.

:focus-visible, :focus yerine kullanılır çünkü ikisi farklı kümeler döndürür: :focus bir alana işaretleyiciyle tıklandığında da eşleşir, :focus-visible odak göstergesinin gerekli olduğu durumlarda eşleşir. Odak çerçevesini büsbütün kaldırmak (outline: none yazmak) klavyeyle gezinmeyi olanaksızlaştırır; çerçeve kaldırılacaksa yerine görünür bir başkası konmalıdır.

Özet

  • Sözde sınıf tek iki nokta üst üsteyle yazılır ve belgede yazılı olmayan bir durumu seçer; iki aileye ayrılır — etkileşim durumu ve ağaçtaki konum.
  • :nth-child() bir an+b formülü alır; n sıfırdan başlar ve formülün ürettiği geçerli sıralar eşleşir. odd ve even bu formülün adlandırılmış hâlleridir.
  • :nth-child() bütün kardeşleri sayar, :nth-of-type() yalnızca aynı türdekileri; aradaki fark başlık gibi araya giren ögelerde ortaya çıkar.
  • :is(), :where(), :not() ve :has() seçici listesi alır; :has() bir ögeyi içeriğine göre seçer ve birleştiricilerin ters yönünü sağlar.
  • Sözde eleman çift iki nokta ile yazılır; ::before ve ::after belgede bulunmayan içerik üretir. Bu içerik metin olarak güvenilir biçimde erişilebilir değildir, bu yüzden yalnızca görsel işaret taşır.

Sonraki Adım

Artık aynı ögeye birden çok kural uyabiliyor: td bir kuralla, .eksik başka bir kuralla, .olcum-cizelgesi td:not(.ad) bir üçüncüsüyle eşleşiyor. Üçü de text-align özelliğine yazarsa hangisi kazanır? Sonraki ders bu soruyu bir sezgiyle değil, sayılabilir bir sıralamayla yanıtlar: özgüllük üçlüsünü hesaplar ve basamaklamanın adımlarını sırayla uygular.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat