İçeriğe geç
academia.sh

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.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat