---
title: 'Biçem Başarımı'
source: 'https://academia.sh/tr/kurslar/duzen-ve-duyarli-tasarim/bicem-basarimi'
course: 'Düzen Sistemleri ve Duyarlı Tasarım'
language: tr
updated: '2026-08-17T18:09:29+00:00'
license: 'CC BY-SA 4.0'
---

# Biçem Başarımı

Seçici eşleştirmenin sağdan sola yapılması, geçersiz kılma kapsamının seçici biçimine bağlılığı, biçem dosyasının çizimi engellemesi ve kritik biçem alt kümesinin hesaplanması.

Önceki beş ders biçemin nasıl düzenleneceğini ele aldı ve her biri aynı soruyu farklı yerden
yanıtladı. Bir soru daha var ve onu tarayıcı sorar.

Biçem dosyası indirilir, ayrıştırılır, her ögeye hangi kuralların uyduğu bulunur ve
hesaplanmış değerler üretilir. Bu işin bir maliyeti vardır ve maliyetin nereden geldiği,
yazım kararlarını da etkiler. Bu ders o maliyeti kural olarak kurar ve kursu kapatır.

## Eşleştirme Sağdan Sola Yapılır

Bir seçicinin bir ögeye uyup uymadığı sorusu iki yönde yanıtlanabilir. Soldan sağa gitmek —
önce en dıştaki seçiciyi bulup alt ağaçta ilerlemek — okuma yönüne uyar. Tarayıcılar bunu
yapmaz; **sağdan sola** gider.

Nedeni şudur: soru "bu seçici hangi ögelere uyar" değil, "bu ögeye hangi kurallar uyar"dır.
Öge elde olduğunda, seçicinin en sağdaki bileşeni — **anahtar seçici** — ögeye uymuyorsa
kural hemen elenir. Uyuyorsa atalara doğru yürünür.

```js
// bicembasarim.mjs — secici eslestirme yonu ve kritik bicem alt kumesinin hesaplanmasi

// --- kucuk bir belge agaci ---
const yap = (tur, siniflar, cocuk = []) => ({ tur, siniflar, cocuk, ust: null });
const BELGE = yap("body", [], [
  yap("header", ["kunye"], [
    yap("h1", ["kunye__ad"]), yap("p", ["kunye__konum"]),
    yap("nav", ["gezinme"], [yap("ul", [], [yap("li", [], [yap("a", ["etkin"])]), yap("li", [], [yap("a", [])])])]),
  ]),
  yap("main", [], [
    yap("section", ["olcum-bolumu"], [
      yap("h2", ["baslik"]),
      yap("div", ["olcum-kartlari"], [
        yap("article", ["olcum-kart"], [yap("h3", ["olcum-kart__baslik"]), yap("p", ["olcum-kart__deger"])]),
        yap("article", ["olcum-kart"], [yap("h3", ["olcum-kart__baslik"]), yap("p", ["olcum-kart__deger"])]),
        yap("article", ["olcum-kart", "olcum-kart--genis"], [yap("h3", ["olcum-kart__baslik"]), yap("p", ["olcum-kart__deger"])]),
      ]),
    ]),
    yap("section", ["konum-bolumu"], [yap("h2", ["baslik"]), yap("p", []), yap("p", [])]),
  ]),
  yap("footer", ["kaynak-notu"], [yap("p", [])]),
]);

function bagla(dugum, ust = null) {
  dugum.ust = ust;
  for (const c of dugum.cocuk) bagla(c, dugum);
  return dugum;
}
bagla(BELGE);

const tumu = (d, liste = []) => { liste.push(d); for (const c of d.cocuk) tumu(c, liste); return liste; };
const DUGUMLER = tumu(BELGE);

// --- bilesik secici denetimi (tur ve sinif) ---
let denetim = 0;
function uyar(dugum, bilesik) {
  denetim++;
  const tur = bilesik.match(/^[a-z][\w-]*/);
  if (tur && dugum.tur !== tur[0]) return false;
  for (const s of bilesik.match(/\.[\w-]+/g) || []) if (!dugum.siniflar.includes(s.slice(1))) return false;
  return true;
}

// sagdan sola: once anahtar secici, sonra atalar
function sagdanSola(secici) {
  const p = secici.trim().split(/\s+/);
  denetim = 0;
  let eslesen = 0;
  for (const d of DUGUMLER) {
    if (!uyar(d, p[p.length - 1])) continue;
    let i = p.length - 2, ata = d.ust, tamam = i < 0;
    while (i >= 0 && ata) {
      if (uyar(ata, p[i])) i--;
      ata = ata.ust;
      if (i < 0) tamam = true;
    }
    if (tamam) eslesen++;
  }
  return { denetim, eslesen };
}

// soldan saga: once ilk secici, sonra alt agaclarda ilerle
function soldanSaga(secici) {
  const p = secici.trim().split(/\s+/);
  denetim = 0;
  let eslesen = 0;
  const ilerle = (dugum, i) => {
    for (const c of tumu(dugum).slice(1)) {
      if (!uyar(c, p[i])) continue;
      if (i === p.length - 1) eslesen++;
      else ilerle(c, i + 1);
    }
  };
  for (const d of DUGUMLER) {
    if (!uyar(d, p[0])) continue;
    if (p.length === 1) eslesen++;
    else ilerle(d, 1);
  }
  return { denetim, eslesen };
}

console.log(`belgedeki dugum sayisi: ${DUGUMLER.length}`);
console.log("\n--- ayni seciciyi iki yonde eslestirmenin denetim sayisi ---");
console.log("secici".padEnd(62) + "sagdan sola".padStart(13) + "soldan saga".padStart(13) + "  eslesen");
for (const s of [
  ".olcum-kart__baslik",
  ".olcum-bolumu .olcum-kartlari .olcum-kart .olcum-kart__baslik",
  "body main section div article h3",
  ".kunye__ad",
]) {
  const sa = sagdanSola(s), so = soldanSaga(s);
  console.log(s.padEnd(62) + String(sa.denetim).padStart(13) + String(so.denetim).padStart(13) + String(sa.eslesen).padStart(10));
}

// --- kritik bicem: ilk ekranda gorunen ogelere uyan kurallar ---
const KURALLAR = [
  { secici: ".kunye", bayt: 96 }, { secici: ".kunye__ad", bayt: 64 },
  { secici: ".gezinme", bayt: 88 }, { secici: ".gezinme a", bayt: 72 },
  { secici: ".olcum-kartlari", bayt: 120 }, { secici: ".olcum-kart", bayt: 148 },
  { secici: ".olcum-kart__baslik", bayt: 58 }, { secici: ".olcum-kart__deger", bayt: 86 },
  { secici: ".olcum-kart--genis", bayt: 44 }, { secici: ".konum-bolumu", bayt: 92 },
  { secici: ".konum-bolumu p", bayt: 60 }, { secici: ".kaynak-notu", bayt: 54 },
  { secici: ".olcum-suzgeci", bayt: 132 }, { secici: ".yan-bilgi", bayt: 104 },
];

// Ilk ekranda gorunen bolum: kunye ve olcum bolumu (belge sirasinda ilk 20 dugum).
const GORUNUR = new Set(DUGUMLER.slice(0, 20));
const uyanVar = (secici) => {
  const p = secici.trim().split(/\s+/);
  return [...GORUNUR].some((d) => {
    if (!uyar(d, p[p.length - 1])) return false;
    let i = p.length - 2, ata = d.ust;
    while (i >= 0 && ata) { if (uyar(ata, p[i])) i--; ata = ata.ust; }
    return i < 0;
  });
};

const kritik = KURALLAR.filter((k) => uyanVar(k.secici));
const toplam = KURALLAR.reduce((t, k) => t + k.bayt, 0);
const kritikBayt = kritik.reduce((t, k) => t + k.bayt, 0);

console.log("\n--- kritik bicem alt kumesi ---");
console.log(`  ilk ekranda gorunen dugum sayisi: ${GORUNUR.size} / ${DUGUMLER.length}`);
console.log(`  kritik kural: ${kritik.length} / ${KURALLAR.length}`);
console.log(`  kritik bayt : ${kritikBayt} / ${toplam}  (%${((kritikBayt / toplam) * 100).toFixed(1)})`);
console.log("  kritik olmayanlar:", KURALLAR.filter((k) => !kritik.includes(k)).map((k) => k.secici).join(", "));
```

```
belgedeki dugum sayisi: 29

--- ayni seciciyi iki yonde eslestirmenin denetim sayisi ---
secici                                                          sagdan sola  soldan saga  eslesen
.olcum-kart__baslik                                                      29           29         3
.olcum-bolumu .olcum-kartlari .olcum-kart .olcum-kart__baslik            38           55         3
body main section div article h3                                         44          102         3
.kunye__ad                                                               29           29         1

--- kritik bicem alt kumesi ---
  ilk ekranda gorunen dugum sayisi: 20 / 29
  kritik kural: 8 / 14
  kritik bayt : 732 / 1218  (%60.1)
  kritik olmayanlar: .olcum-kart--genis, .konum-bolumu, .konum-bolumu p, .kaynak-notu, .olcum-suzgeci, .yan-bilgi
```

Yirmi dokuz düğümlük bir belgede dört seçici deneniyor. Tek sınıflı seçicilerde iki yön aynı
sayıda denetim yapıyor: her düğüm bir kez sınanıyor.

Ayrım uzun seçicilerde çıkıyor. Dört bileşenli seçici sağdan sola 38, soldan sağa 55 denetim
istiyor; altı bileşenli tür seçicisi zinciri 44'e karşı 102. Sağdan sola yürüyüş, anahtar
seçici uymayan düğümleri **tek denetimde** eliyor; soldan sağa yürüyüş her uyan başlangıç
için alt ağacın tamamını geziyor.

Buradan çıkan yazım kuralı, anahtar seçicinin **ayırıcı** olmasıdır. `... h3` biçiminde biten
bir seçici, belgedeki bütün başlıklarda ata yürüyüşü başlatır; `... .olcum-kart__baslik`
biçiminde biten seçici yalnız üç düğümde başlatır.

Bir ölçü duygusu gerekir: seçici eşleştirme, yerleşim ve boyama aşamalarının yanında küçük bir
maliyettir. Uzun seçicilerin asıl bedeli eşleştirme sayısı değil, bir sonraki bölümdeki
geçersiz kılma kapsamıdır.

## Geçersiz Kılma Kapsamı

Bir ögenin sınıfı değiştiğinde, tarayıcı hangi ögelerin biçeminin yeniden hesaplanacağını
belirlemek zorundadır. Bu kümeye **geçersiz kılma kapsamı (invalidation scope)** denir ve
seçicilerin biçiminden çıkarılır.

Kural şudur: bir sınıf yalnız kendi ögesine uyan kurallarda geçiyorsa kapsam o ögedir. Aynı
sınıf bir alt öge birleştiricisinin **solunda** geçiyorsa, kapsam ögenin bütün alt ağacıdır.

```css
.olcum-kart--uyari { border-color: var(--uyari); }          /* kapsam: ögenin kendisi */
.olcum-kart--uyari .olcum-kart__deger { color: var(--uyari); }  /* kapsam: alt ağacın tamamı */
```

İkinci yazımda karta sınıf eklemek, kartın içindeki bütün ögelerin biçemini yeniden
hesaplatır. Önceki derste kurulan özel özellik yazımı bu maliyeti de düşürür: değiştirici
yalnız bir değer yazar, alt ögeler zaten o değeri okuyordur.

Ata yönünde çalışan seçiciler kapsamı yukarı doğru genişletir: bir ögenin durumunun ana
ögesini de etkilediği yazımlarda, değişimin sonucu ağacın üst kısmına taşınır. Bu tür
seçiciler güçlüdür ve gerektiğinde kullanılır; ölçüsüz kullanıldığında geçersiz kılma
kapsamını öngörülemez kılar.

## Biçem Dosyası Çizimi Engeller

Bir belgenin ilk çizimi, biçem dosyası indirilip ayrıştırılana kadar bekler. Bunun nedeni
belirlidir: biçem bilinmeden çizilen sayfa, biçem geldiğinde baştan çizilir ve kullanıcı
biçimsiz bir sayfa görür.

Üç sonucu vardır. Biçem dosyası belgenin baş kısmında bildirilir; sonda bildirilmesi
ayrıştırmanın ilerlemesini geciktirir. `media` özniteliği taşıyan ve koşulu sağlanmayan bir
dosya çizimi engellemez; yazdırma biçemi bu yolla ayrılır. Biçem dosyasının içinden başka bir
dosya çağıran `@import` kuralı ise iki indirmeyi **sıraya** sokar; ikinci istek ancak birinci
dosya ayrıştırıldıktan sonra başlar.

## Kritik Biçem

İlk çizim için gereken kurallar, dosyadaki kuralların tamamı değildir. Yalnız ilk ekranda
görünen ögelere uyan kurallar gerekir; kalanlar sonra yüklenebilir.

Çıktının ikinci bloğu bu alt kümeyi hesaplıyor: yirmi dokuz düğümün ilk yirmisi görünür
kabul edildiğinde, on dört kuralın sekizi gerekli çıkıyor. Bayt olarak toplamın yüzde 60'ı.

Kritik alt küme belgenin içine doğrudan yazılır; kalan kurallar çizimi engellemeyen bir
biçimde yüklenir. Bu yazımın iki bedeli vardır. Birincisi yinelemedir: kritik kurallar hem
belgenin içinde hem dosyada bulunur. İkincisi bayatlamadır; sayfa yapısı değiştiğinde kritik
küme yeniden hesaplanmalıdır, elle bakımı sürdürülemez.

Bu yüzden kritik biçem, elle yazılan değil **üretilen** bir çıktıdır — hesabı yukarıdaki
kadar mekaniktir: görünür öge kümesi ve kural listesi verildiğinde alt küme belirlidir.

## Katmanlar ve Bakım Maliyeti

`@layer` kuralının çalışma zamanı maliyeti küçüktür ama bir sıra kuralı vardır: katman
sırası, katman adlarının **ilk göründüğü** yerde belirlenir. Bu yüzden katman adları biçem
dosyasının başında tek satırda bildirilir:

```css
@layer taban, duzen, bilesen, yardimci;
```

Bu satır sıraları sabitler; hangi dosyanın hangi sırada yüklendiği artık sonucu değiştirmez.
Kazandırdığı şey bir başarım ölçüsü değil, ölçülemeyen bir maliyetin — özgüllük tırmanışının
ve `!important` zincirlerinin — önüne geçmesidir.

Yardımcı sınıflar en üst katmanda durur; böylece tek bildirimlik bir sınıf, bileşen kuralını
özgüllük hilesi olmadan ezebilir. Bu, beşinci dersteki karma kullanımın gerçekten çalışması
için gereken düzenlemedir.

## Özet

- Seçici eşleştirme sağdan sola yapılır; anahtar seçici uymayan düğümler tek denetimde
  elenir, bu yüzden ayırıcı bir anahtar seçici uzun seçicileri de ucuzlatır.
- Uzun seçicilerin asıl bedeli eşleştirme sayısı değil geçersiz kılma kapsamıdır: bir sınıf
  alt öge birleştiricisinin solunda geçiyorsa kapsam bütün alt ağaçtır.
- Biçem dosyası ilk çizimi engeller; koşulu sağlanmayan `media` bildirimi engellemez,
  `@import` ise indirmeleri sıraya sokar.
- Kritik biçem, ilk ekranda görünen ögelere uyan kuralların alt kümesidir; hesabı mekaniktir
  ve elle bakımı sürdürülemediği için üretilmelidir.
- Katman sırası adların ilk göründüğü yerde belirlenir; başta tek satırla bildirmek yükleme
  sırasını sonuçtan bağımsız kılar.

## Kurs Kapanışı

Bu kurs düzenle başladı. Esnek kutu tek eksende boş alanı bölüştürdü, ızgara iki eksende hat
tanımladı ve ikisi arasındaki seçim bir ölçüte bağlandı. Duyarlı tasarım, kesme noktalarını
aygıt listelerinden değil içeriğin kendisinden türetti; ortam sorguları görüntü alanını,
kapsayıcı sorguları bileşenin kendi bağlamını sordu ve kullanıcı tercihleri tasarımın girdisi
oldu.

Hareket konusu geometriyi ve zamanı ayırdı: dönüşüm matrisi neyin nereye taşındığını,
zamanlama eğrisi bunun ne kadar sürede olduğunu belirledi. Çizim hattı hangi bildirimin
hangi aşamayı çalıştırdığını gösterdi ve hareketin bir de kullanıcıya çıkan maliyeti olduğu
görüldü.

Son konu ise bütün bunların nereye yazılacağını sordu. Adlandırma yöntemi özgüllüğü düz
tuttu, özel özellikler bileşene bir arayüz verdi, derleme araçları kaynağı düzenledi,
kapsamlama adları sözleşmeden mekanizmaya taşıdı ve yardımcı sınıflar kısıtı sistemin
kendisine gömdü. Kuzey Yamaç Ölçüm İstasyonu sayfası bu derslerin her birinde bir adım daha
ilerledi ve sonunda bileşen dosyalarına, bir ölçek tanımına ve katman sırasına bölünmüş bir
biçem katmanına kavuştu.

Sayfanın hâlâ yapamadığı bir şey var: kendisi hiçbir şey yapmıyor. Ölçüm kartları belgede
yazılı olduğu için görünüyor, durum göstergesi bir öznitelik elle değiştirildiğinde
değişiyor, süzgeç hiçbir şeyi süzmüyor. Belge ağacının programla değiştirilmesi, kullanıcı
eylemlerinin olay olarak yakalanması ve tarayıcının sunduğu arayüzlerin kullanılması bir
sonraki kursun konusudur: **Tarayıcı ve Web Platformu**. Orada belge, bir biçim verilmiş
metin olmaktan çıkıp üzerinde çalışılan bir veri yapısına dönüşür.
