Ders 18 / 23
Adlandırma Yöntemleri
Blok–eleman–değiştirici yaklaşımı; özgüllüğün düz tutulması, adın sahipliği bildirmesi, değiştirici ile durum ayrımı ve kalıbın denetlenebilir olması.
İçindekiler
Bu kursta üç biçem dosyası birikti. Görsel bildirimler istasyon.css dosyasında, yerleşim
duzen.css dosyasında, hareket hareket.css dosyasında. Sınıf adları da çoğaldı:
.kart, .baslik, .genis, .ozet, .gosterge.
Bu adların hiçbiri kime ait olduğunu söylemiyor. .baslik ölçüm kartının başlığı mı, yan
bilginin başlığı mı? Sayfaya yeni bir bölüm eklendiğinde aynı adı kullanmak güvenli mi? Bir
kural silindiğinde başka nereyi bozar?
Bu konu bu soruların yanıtını bir mimariye bağlar. Bu ders ilk adımı atar: adların kendisi.
Adlandırma Neyi Çözer
Bir biçem dosyası büyüdükçe üç sorun ortaya çıkar.
Sahiplik. Bir sınıf adının hangi bileşene ait olduğu addan okunmuyorsa, o adı kimse güvenle değiştiremez. Değişiklik yapılacak yer bulunamaz.
Özgüllük tırmanışı. Bir bildirimi bastırmak için seçiciye bir sınıf daha eklenir; sonra
onu bastırmak için bir tane daha. Basamaklama ve Özgüllük dersinde tanımlanan üçlü büyümeye
başlar ve sonunda !important yazılır.
Silinebilirlik. Bir kuralın hangi belge parçasına uyduğu bilinmiyorsa o kural silinemez. Biçem dosyası yalnızca büyür.
Adlandırma yöntemi bu üçünü tek bir kararla ele alır: ad, ögenin belgedeki yerinden değil, ait olduğu bileşenden türetilir.
Blok, Eleman, Değiştirici
Yaygın yöntem adı üç parçaya ayırır.
Blok, kendi başına anlamlı ve taşınabilir bir bileşendir. Sayfanın neresine konursa konsun aynı şeydir: ölçüm kartı, gezinme çubuğu, ölçüm süzgeci.
Eleman, bloğun bir parçasıdır ve blok olmadan anlamı yoktur: kartın başlığı, kartın
değeri, kartın birimi. Ad, bloğun adıyla başlar ve iki alt çizgiyle ayrılır:
olcum-kart__baslik.
Değiştirici, bloğun ya da elemanın bir varyantıdır: geniş kart, uyarı kartı, kısa
başlık. İki tireyle ayrılır: olcum-kart--genis.
Bir terim ayrımı gerekir: burada eleman, bloğun parçası anlamındadır. HTML belgesindeki
düğümler bu kursta ve önceki kurslarda öge olarak anılır. İki sözcük farklı şeyleri
adlandırır; olcum-kart__baslik bir eleman adıdır ve bir h3 ögesine yazılabilir.
Özgüllüğün Düz Tutulması
Yöntemin kritik sonucu, her kuralın tek bir sınıf seçicisi olmasıdır. Aşağıdaki program seçicilerin özgüllük üçlülerini hesaplıyor ve iki yazımın dağılımını karşılaştırıyor.
// adlandirma.mjs — secici ozgullugu ve ad kaliplarinin denetimi // Ozgulluk uclusu (a, b, c): a=kimlik, b=sinif/oznitelik/sozde sinif, c=tur/sozde eleman // :where(...) icerigi ozgulluge katilmaz; :is(...) icindeki en ozgul secici katilir. function ozgulluk(secici) { let s = secici; let ek = [0, 0, 0]; s = s.replace(/:where\([^()]*\)/g, " "); // katkisi yok s = s.replace(/:is\(([^()]*)\)/g, (_, ic) => { // en ozgul dal sayilir const dallar = ic.split(",").map((d) => ozgulluk(d.trim())); dallar.sort((x, y) => y[0] - x[0] || y[1] - x[1] || y[2] - x[2]); ek = ek.map((v, i) => v + dallar[0][i]); return " "; }); const a = (s.match(/#[\w-]+/g) || []).length; const b = (s.match(/\.[\w-]+/g) || []).length + (s.match(/\[[^\]]+\]/g) || []).length + (s.match(/:(?!:)[\w-]+(\([^()]*\))?/g) || []).length; const c = (s.match(/::[\w-]+/g) || []).length + (s.replace(/::[\w-]+/g, " ").replace(/:(?!:)[\w-]+(\([^()]*\))?/g, " ") .match(/(^|[\s>+~(])([a-zA-Z][\w-]*)/g) || []).length; return [a + ek[0], b + ek[1], c + ek[2]]; } const SECICILER = [ "#icerik .olcum-bolumu ul li a.etkin", ".istasyon-duzeni .olcum-bolumu .olcum-kartlari .kart .baslik", "section.olcum-bolumu > ul > li", ".olcum-kart__baslik", ".olcum-kart--uyari", ".olcum-kart:hover", ".olcum-kart[data-durum='eksik']", ":where(.olcum-kartlari) .olcum-kart__baslik", ":is(h2, .baslik).olcum-kart__baslik", ]; console.log("--- secici ozgullukleri ---"); console.log("secici".padEnd(58) + "ozgulluk".padStart(12) + " derinlik"); for (const s of SECICILER) { const [a, b, c] = ozgulluk(s); const derinlik = s.split(/[\s>+~]+/).filter(Boolean).length; console.log(s.padEnd(58) + `(${a}, ${b}, ${c})`.padStart(12) + String(derinlik).padStart(10)); } // --- ad kalibinin denetimi: blok__eleman--degistirici --- const KALIP = /^[a-z][a-z0-9]*(-[a-z0-9]+)*(__[a-z][a-z0-9]*(-[a-z0-9]+)*)?(--[a-z][a-z0-9]*(-[a-z0-9]+)*)?$/; const ADLAR = [ "olcum-kart", "olcum-kart__baslik", "olcum-kart--genis", "olcum-kart__deger--eksik", "olcum-kart__govde__satir", "OlcumKart", "olcum_kart", "kart--", "olcum-kart__baslik--kisa", ]; console.log("\n--- ad kalibi denetimi ---"); for (const ad of ADLAR) { const parcali = ad.split("__"); const cokluEleman = parcali.length > 2; const uygun = KALIP.test(ad) && !cokluEleman; const neden = cokluEleman ? "ic ice eleman adi" : !KALIP.test(ad) ? "kalip disi yazim" : "-"; console.log(` ${ad.padEnd(28)} ${(uygun ? "uygun" : "uygun degil").padEnd(12)} ${neden}`); } // --- ayni bilesenin iki yazimla ureteceği ozgulluk dagilimi --- console.log("\n--- bir bilesenin butun kurallarinin ozgullugu ---"); const DERIN = [ ".olcum-kartlari .kart", ".olcum-kartlari .kart .baslik", ".olcum-kartlari .kart .baslik span", ".olcum-kartlari .kart.genis .baslik", ]; const DUZ = [".olcum-kart", ".olcum-kart__baslik", ".olcum-kart__birim", ".olcum-kart--genis .olcum-kart__baslik"]; const dagilim = (liste) => liste.map((s) => ozgulluk(s).join(".")); console.log(" ic ice yazim:", dagilim(DERIN).join(" ")); console.log(" duz yazim :", dagilim(DUZ).join(" "));
--- secici ozgullukleri --- secici ozgulluk derinlik #icerik .olcum-bolumu ul li a.etkin (1, 2, 3) 5 .istasyon-duzeni .olcum-bolumu .olcum-kartlari .kart .baslik (0, 5, 0) 5 section.olcum-bolumu > ul > li (0, 1, 3) 3 .olcum-kart__baslik (0, 1, 0) 1 .olcum-kart--uyari (0, 1, 0) 1 .olcum-kart:hover (0, 2, 0) 1 .olcum-kart[data-durum='eksik'] (0, 2, 0) 1 :where(.olcum-kartlari) .olcum-kart__baslik (0, 1, 0) 2 :is(h2, .baslik).olcum-kart__baslik (0, 2, 0) 2 --- ad kalibi denetimi --- olcum-kart uygun - olcum-kart__baslik uygun - olcum-kart--genis uygun - olcum-kart__deger--eksik uygun - olcum-kart__govde__satir uygun degil ic ice eleman adi OlcumKart uygun degil kalip disi yazim olcum_kart uygun degil kalip disi yazim kart-- uygun degil kalip disi yazim olcum-kart__baslik--kisa uygun - --- bir bilesenin butun kurallarinin ozgullugu --- ic ice yazim: 0.2.0 0.3.0 0.3.1 0.4.0 duz yazim : 0.1.0 0.1.0 0.1.0 0.2.0
Son blok yöntemin bütün gerekçesini iki satıra sığdırıyor. İç içe yazımda aynı bileşenin dört kuralı dört farklı özgüllükte; birini diğerinden bastırmak için hangi seçicinin ne kadar özgül olduğunu bilmek gerekir. Düz yazımda üç kural aynı özgüllükte ve aralarındaki sıralamayı yalnız yazım sırası belirler.
Aynı özgüllükteki kurallar arasında karar vermek, farklı özgüllüktekiler arasında karar vermekten kolaydır: sonra yazılan kazanır, başka bir hesap yoktur.
Üstteki tablo iki araç daha gösteriyor. :where() içine alınan seçici özgüllüğe hiç
katılmaz; kapsayıcıyı yazıp üçlüyü büyütmemenin yoludur. :is() ise içindeki en özgül dalı
sayar, dolayısıyla üçlüyü büyütür.
Kalıbın Denetlenebilir Olması
Bir adlandırma yöntemi, ancak makineyle denetlenebiliyorsa uygulanabilir kalır. İkinci blok dokuz adı tek bir düzenli ifadeyle sınıyor ve dördünü geri çeviriyor.
Geri çevrilenlerden üçü yazım kuralı hatası: büyük harf, alt çizgi ayracının yanlış
kullanımı, boş değiştirici. Dördüncüsü daha ilginçtir: olcum-kart__govde__satir yazım
kurallarına uygundur ama iki eleman adı içerir.
Bu yasak bilinçlidir. İç içe eleman adı, belgenin ağaç yapısını ada gömer; başlık kartın gövdesinden çıkarıldığında ad yanlış olur. Blok düzdür: bütün elemanlar doğrudan bloğa aittir, aralarındaki ağaç ilişkisi ada yazılmaz.
Aynı denetim, biçem dosyasında bulunup belgede kullanılmayan adları da bulur. Ad kalıbı belirli olduğu için iki kümenin karşılaştırılması bir dizgi işidir.
Değiştirici mi, Durum mu
Değiştirici, bileşenin tasarım zamanında bilinen bir varyantıdır: geniş kart, uyarı kartı. Belge üretilirken yazılır ve yaşam boyu değişmez.
Durum ise çalışma zamanında değişir: açık, seçili, yükleniyor, hatalı. İkisi aynı mekanizmayla yazılırsa, betiğin hangi sınıfı değiştirebileceği belirsizleşir.
Ayrımı korumanın yolu durumu ayrı bir mekanizmaya taşımaktır. İki seçenek vardır ve ikisi de
data- öznitelikleri ya da aria- öznitelikleriyle çalışır:
.olcum-kart[data-durum="eksik"] { border-color: var(--uyari); } .olcum-kart[aria-expanded="true"] .olcum-kart__govde { display: block; }
İkincisi yeğlenir. Durum zaten erişilebilirlik ağacına bildiriliyorsa, biçem o bildirimi okur; tek bir kaynak iki işi görür. Ayrı bir durum sınıfı yazmak, aynı bilgiyi iki yerde tutmak demektir ve ikisi ayrışabilir.
Katman Önekleri
Adlandırma yöntemleri bileşen içini düzenler; bileşenler arasını düzenlemek için ada bir katman öneki eklemek yaygındır. Önekler yaklaşımlara göre değişir ama işlev aynıdır: addan, kuralın hangi katmandan geldiği okunur.
Ayrılan katmanlar genellikle şunlardır: sayfa iskeletini kuran düzen kuralları, taşınabilir
bileşenler, tek bildirimlik yardımcı sınıflar ve çalışma zamanı durumları. Bu ayrım
@layer ile de kurulabilir ve o zaman ada yazmaya gerek kalmaz — basamaklama katmanları
kuralın sırasını da bildirir. Katmanlar bu konunun altıncı dersinde ele alınacaktır.
İstasyon Sayfasının Yeniden Adlandırılması
/* bilesenler/olcum-kart.css — 1. adım: bileşenin bütün kuralları tek dosyada */ .olcum-kart { display: grid; gap: var(--aralik-0); padding: var(--aralik-1); border: 1px solid var(--cizgi); transition: transform 240ms ease-out; } .olcum-kart__baslik { font-size: 1rem; color: var(--metin-soluk); } .olcum-kart__deger { font-size: 2rem; font-variant-numeric: tabular-nums; } .olcum-kart__birim { color: var(--metin-soluk); } .olcum-kart--genis { grid-column: span 2; } .olcum-kart--ozet { grid-column: 1 / -1; } .olcum-kart[data-durum="eksik"] .olcum-kart__deger { color: var(--uyari); } .olcum-kart:hover, .olcum-kart:focus-within { transform: translateY(-8px) scale(1.04); }
Bileşenin görsel, düzen ve hareket bildirimleri tek dosyada toplandı. Üç dosyaya bölünmüş hâlde bir kartın nasıl göründüğünü anlamak üç dosya okumayı gerektiriyordu; şimdi bileşen başına bir dosya var ve dosya adı sınıf adının kökünden okunuyor.
Kapsayıcının ızgara tanımı — kartların yan yana nasıl dizildiği — bu dosyada değildir.
Bileşen kendi içini bilir, dışını bilmez; dış yerleşim .olcum-kartlari kuralında kalır.
Özet
- Adlandırma yöntemi adı ögenin belgedeki yerinden değil ait olduğu bileşenden türetir; sahiplik, özgüllük tırmanışı ve silinebilirlik sorunlarını birlikte ele alır.
- Blok taşınabilir bileşendir, eleman bloğa ait parçadır, değiştirici varyanttır; eleman adları iç içe geçmez, çünkü ağaç yapısı ada yazılmaz.
- Düz yazımda bileşenin bütün kuralları aynı özgüllüktedir ve sıralamayı yalnız yazım sırası belirler; iç içe yazımda her kural farklı özgüllüğe düşer.
:where()özgüllüğe katılmaz,:is()içindeki en özgül dalı sayar; ikisi üçlüyü denetim altında tutmanın araçlarıdır.- Tasarım zamanı varyantı değiştiriciyle, çalışma zamanı durumu öznitelikle yazılır; erişilebilirlik öznitelikleri varsa biçem onları okur.
Sonraki Adım
Bileşen dosyasındaki her kural var(--cizgi), var(--uyari), var(--aralik-1) gibi
adlara başvuruyor. Bu adlar CSS ile Görsel Sunum kursunda tanımlandı ve kök ögede tutuluyor.
Bir bileşenin kendi ölçeğini kurması, bir bölümün kendi temasını taşıması ya da bir
değiştiricinin yalnız birkaç değeri değiştirmesi gerektiğinde bu tek merkezli yapı yetmez.
Sonraki ders özel özellikleri bir mimari araç olarak ele alır.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.