İçeriğe geç
academia.sh

Ders 08 / 26

Kalıtım ve Varsayılan Değerler

Hiçbir bildirimin ulaşmadığı bir özelliğin değerinin nasıl belirlendiği; kalıtılan ve kalıtılmayan özellikler, başlangıç değeri ve inherit, initial, unset, revert anahtar sözcükleri.

İçindekiler

Basamaklama, bir ögeye uyan bildirimler arasından kazananı seçiyor. Bir sorun kaldı: hiçbir bildirim uymuyorsa ne olur? Ölçüm çizelgesindeki bir hücreye hiçbir kural color yazmamışsa o hücrenin metin rengi nedir?

Boşluk iki ayrı mekanizmayla doldurulur. Bazı özellikler değerlerini üst ögeden devralır; kalanlar tanımlı bir başlangıç değerine düşer. Bu ders iki mekanizmayı ayırır, hangi özelliğin hangisine tabi olduğunu gerekçelendirir ve ikisini açıkça çağıran anahtar sözcükleri tanımlar.

Kalıtım Ağaçta Aşağı Doğru İşler

Kalıtım (inheritance), bir özelliğin değerinin belge ağacında üst ögeden alt ögeye geçmesidir. Her özellik kalıtılmaz; hangi özelliğin kalıtıldığı özellik tanımının bir parçasıdır ve rastgele değildir.

Kabaca: metnin görünümünü belirleyen özellikler kalıtılır — color, font-family, font-size, font-weight, line-height, text-align, letter-spacing, visibility. Kutunun geometrisini belirleyen özellikler kalıtılmaz — margin, padding, border, width, height, background, display, position.

Ayrımın gerekçesi kullanışlılıktır. Bir bölümün yazı tipini bir kez ayarlayıp içindeki bütün metnin onu almasını istemek olağandır; bir bölüme kenarlık verip içindeki her paragrafın da kenarlık almasını istemek olağan değildir. Kalıtım, tekrarı olağan olan kararlarda açıktır.

Kalıtılan değer, üst ögenin hesaplanmış değeridir; kaynakta yazılan metin değil. Bir üst ögede font-size: 150% yazılıysa, çocuğa geçen şey 150% değil, o yüzdenin çözülmüş sonucudur. Bu ayrım birimler dersinde sayıyla ele alınacak.

Başlangıç Değeri Tarayıcı Varsayılanı Değildir

Kalıtılmayan bir özelliğe hiçbir bildirim ulaşmazsa başlangıç değeri (initial value) kullanılır. Bu değer, özelliğin tanımında yazılıdır ve gerçekleştirimden bağımsızdır.

Burada sık karıştırılan bir ayrım vardır. div ögesinin blok kutu üretmesi, display özelliğinin başlangıç değerinden gelmez — display özelliğinin başlangıç değeri inline ’dır. div ögesinin blok olması, tarayıcının kendi varsayılan biçem dosyasında div { display: block } yazdığı içindir.

Ayrım şöyle özetlenir: başlangıç değeri dilin tanımından, tarayıcı varsayılanı bir biçem dosyasından gelir. Birincisi hiçbir kural yazılmadığında değil, hiçbir kural kazanmadığında devreye girer; ikincisi ise kazanabilecek bir bildirimdir ve önceki derste gördüğümüz basamaklamada en zayıf kaynaktır.

Değer Çözümlemesinin Yürütülmesi

Aşağıdaki program, basamaklama sonucu kazanmış bildirimleri girdi alır ve ağaçta aşağı inerek her ögenin dört özellik için değerini çözer. Her satırın sonunda değerin nereden geldiği yazılıdır.

// kalitim.mjs — deger cozumlemesini agacta asagi dogru yurutur
const KALITILAN = new Set(["color", "font-family", "line-height", "text-align", "visibility"]);
const BASLANGIC = {
  "color": "canvastext", "font-family": "serif", "line-height": "normal",
  "text-align": "start", "visibility": "visible", "border-color": "currentcolor",
  "background-color": "transparent",
};

// kazanan bildirimler (basamaklama sonucu) — dugum yolu -> {ozellik: deger}
const kazananlar = {
  "body":                         { "color": "#1c2733", "font-family": "system-ui" },
  "body/main":                    {},
  "body/main/table":              { "text-align": "right", "border-color": "#d5dbe0" },
  "body/main/table/tr":           {},
  "body/main/table/tr/td.ad":     { "text-align": "start" },
  "body/main/table/tr/td.eksik":  { "color": "inherit", "text-align": "unset",
                                    "border-color": "unset", "font-family": "initial" },
};

const agac = { ad: "body", cocuk: [ { ad: "main", cocuk: [ { ad: "table", cocuk: [
  { ad: "tr", cocuk: [ { ad: "td.ad", cocuk: [] }, { ad: "td.eksik", cocuk: [] } ] },
] } ] } ] };

const OZELLIKLER = ["color", "font-family", "text-align", "border-color"];

function coz(dugum, yol, ustDegerler) {
  const tamYol = yol ? `${yol}/${dugum.ad}` : dugum.ad;
  const yazilan = kazananlar[tamYol] ?? {};
  const degerler = {};
  for (const oz of OZELLIKLER) {
    let d = yazilan[oz];
    let kaynak;
    if (d === undefined) {
      // bildirim yok: kalitilan ozellikse ustten al, degilse baslangic degeri
      if (KALITILAN.has(oz) && ustDegerler) { d = ustDegerler[oz]; kaynak = "kalitim"; }
      else { d = BASLANGIC[oz]; kaynak = "baslangic"; }
    } else if (d === "inherit") {
      d = ustDegerler ? ustDegerler[oz] : BASLANGIC[oz]; kaynak = "inherit";
    } else if (d === "initial") {
      d = BASLANGIC[oz]; kaynak = "initial";
    } else if (d === "unset") {
      if (KALITILAN.has(oz) && ustDegerler) { d = ustDegerler[oz]; kaynak = "unset->kalitim"; }
      else { d = BASLANGIC[oz]; kaynak = "unset->baslangic"; }
    } else {
      kaynak = "bildirim";
    }
    degerler[oz] = d;
    console.log(`  ${oz.padEnd(12)} = ${String(d).padEnd(12)} (${kaynak})`);
  }
  for (const c of dugum.cocuk) {
    console.log(`${tamYol}/${c.ad}`);
    coz(c, tamYol, degerler);
  }
}

console.log("body");
coz(agac, "", null);
body
  color        = #1c2733      (bildirim)
  font-family  = system-ui    (bildirim)
  text-align   = start        (baslangic)
  border-color = currentcolor (baslangic)
body/main
  color        = #1c2733      (kalitim)
  font-family  = system-ui    (kalitim)
  text-align   = start        (kalitim)
  border-color = currentcolor (baslangic)
body/main/table
  color        = #1c2733      (kalitim)
  font-family  = system-ui    (kalitim)
  text-align   = right        (bildirim)
  border-color = #d5dbe0      (bildirim)
body/main/table/tr
  color        = #1c2733      (kalitim)
  font-family  = system-ui    (kalitim)
  text-align   = right        (kalitim)
  border-color = currentcolor (baslangic)
body/main/table/tr/td.ad
  color        = #1c2733      (kalitim)
  font-family  = system-ui    (kalitim)
  text-align   = start        (bildirim)
  border-color = currentcolor (baslangic)
body/main/table/tr/td.eksik
  color        = #1c2733      (inherit)
  font-family  = serif        (initial)
  text-align   = right        (unset->kalitim)
  border-color = currentcolor (unset->baslangic)

Çıktıdan üç gözlem çıkar.

color ve font-family yalnızca body ögesinde bildirildi ve beş kuşak aşağı, hücrelere kadar taşındı. Bir bildirim, ağacın kökünde yazıldığında bütün alt ağacı etkiler.

border-color tabloda #d5dbe0 iken satırda yeniden currentcolor’a düştü. Kenarlık rengi kalıtılan bir özellik değildir; tabloya verilen kenarlık rengi hücrelere geçmez. Tabloda kenarlık kurmak için hücrelere ayrıca kural yazmak gerekmesinin sebebi budur.

text-align tabloda right oldu ve satır ile hücrelere kalıtımla indi; td.ad ögesinde bir bildirimle start’a çevrildi. Kalıtım, alt ögede bildirim varsa geçersizdir — kalıtım en zayıf kaynaktır, bir bildirimle her zaman bastırılır.

Dört Anahtar Sözcük

Her özelliğin değerine yazılabilen dört anahtar sözcük vardır. Çıktının son bloğu dördünden üçünü gösteriyor.

inherit — kalıtılmayan bir özelliği bile üst ögeden almaya zorlar. td.eksik ögesinde color: inherit yazıldı ve değer üstten geldi. Bu, kalıtılmayan bir özellikte anlamlıdır; border-color: inherit yazmak, kenarlık rengini üstten çekmenin yoludur.

initial — özelliğin başlangıç değerine döner. Çıktıda font-family: initial yazan hücre serif değerine düştü; üstteki system-ui kalıtımı kesildi. Bu sonuç sıklıkla istenmeyen bir sonuçtur: initial, dilin tanımına döner, sayfanın tasarımına değil.

unset — koşullu davranır: özellik kalıtılan bir özellikse inherit gibi, değilse initial gibi işler. Çıktıda text-align: unset kalıtıma, border-color: unset başlangıç değerine düştü. Bu, “bu bildirimi hiç yazmamış olsaydım ne olurdu” sorusunun yanıtıdır.

revert — dördüncüsüdür ve farklı bir soruya yanıt verir: değeri, daha zayıf bir kaynağın kazanacağı hâle döndürür. Yazar biçeminde revert yazmak, o özellikte tarayıcı varsayılanına dönmek demektir. initial ile farkı burada görülür: bir bağlantıda color: initial yazmak rengi dilin başlangıç değerine götürür, color: revert ise tarayıcının bağlantılar için tanımladığı renge götürür.

Dördü de all kısayoluyla bütün özelliklere birden yazılabilir. all: revert bir ögeyi yazar biçeminden yalıtır; all: unset ise kalıtılanları koruyup kalanları sıfırlar.

Değer Aşamaları

Bu bölümde geçen “hesaplanmış değer” terimi tanımlanmalıdır. Bir bildirimin yazımından ekrandaki sonuca kadar değer birkaç aşamadan geçer:

Aşama Ne olur
bildirilen değer Kaynakta yazılan metin
basamaklanmış değer Basamaklamayı kazanan bildirim
belirtilmiş değer Kazanan yoksa kalıtım veya başlangıç değeriyle doldurulmuş hâli
hesaplanmış değer Göreli birimlerin çözüldüğü, kalıtımla aktarılan hâli
kullanılan değer Yerleşim yapıldıktan sonra kesinleşen hâli

Kalıtımla aktarılan aşama hesaplanmış değerdir. Bir üst ögede font-size: 1.5em yazılıysa, çocuk 1.5em metnini değil, o ifadenin çözülmüş sonucunu devralır — aksi hâlde her kuşakta yeniden çarpılır ve yazı boyutu üstel büyürdü.

Kullanılan değer aşaması ise yerleşimi bekler. width: 50% bildiriminde hesaplanmış değer hâlâ yüzdedir; kesin sayı, kapsayan kutunun genişliği bilindikten sonra ortaya çıkar. Bu aşamayı kutu modeli konusunda ayrıntısıyla göreceğiz.

İstasyon Sayfasında Kalıtımın Kullanımı

/* istasyon.css — 7. adım: kalıtımı taban olarak kullanmak */
body {
  color: #1c2733;
  font-family: system-ui, sans-serif;
  line-height: 1.5;
}

/* form denetimleri tipografiyi kendiliğinden devralmaz */
input, select, textarea, button {
  font: inherit;
  color: inherit;
}

.olcum-cizelgesi { border-collapse: collapse; }
.olcum-cizelgesi th,
.olcum-cizelgesi td { border-block-end: 1px solid #d5dbe0; }

İkinci kural bir istisnayı kapatır. Form denetimleri tipografilerini belgeden almaz; kendi varsayılan yazı tiplerini taşırlar. font: inherit yazmak, bu istisnayı kaldırıp denetimleri belgenin tipografisine bağlar.

Üçüncü grup, kenarlık rengi kalıtılmadığı için kenarlığın hücrelere ayrı ayrı yazılması gerektiğini gösteriyor — çıktının dördüncü bloğunda gördüğümüz davranışın doğrudan sonucu.

Özet

  • Bir özellik ya kalıtılır ya da bildirim yoksa başlangıç değerine düşer; hangisinin geçerli olduğu özelliğin tanımında yazılıdır ve metin özellikleri kalıtılır, kutu geometrisi özellikleri kalıtılmaz.
  • Başlangıç değeri dilin tanımından gelir; tarayıcının varsayılan görünümü ise bir biçem dosyasından gelir ve basamaklamada en zayıf kaynaktır. display: block bir başlangıç değeri değil, o dosyada yazan bir bildirimdir.
  • Kalıtım en zayıf kaynaktır: alt ögede o özelliğe yazan bir bildirim varsa kalıtım geçersizdir.
  • inherit üstten almaya zorlar, initial dilin başlangıç değerine döner, unset ikisi arasında özelliğin türüne göre seçer, revert daha zayıf bir kaynağın değerine döner.
  • Kalıtımla aktarılan şey hesaplanmış değerdir; göreli birimler aktarılmadan önce çözülür, aksi hâlde her kuşakta yeniden çarpılırlardı.

Sonraki Adım

Bu konu boyunca kuralların hangi ögelere ulaştığı ve hangi değerin kazandığı çözüldü. Değer kesinleşti; ama o değerin ne anlama geldiği henüz kurulmadı. padding: 8px bir hücrenin neresine 8 piksel ekler? Genişlik verilen bir kutunun toplam eni ne olur? Sonraki konu her ögenin bir kutuya dönüştüğü modeli tanımlar ve bu kutunun bölümlerini aritmetikle 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