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

# Kapsamlı Biçem Yaklaşımları

Adların kapsamını gerçekten sınırlayan yaklaşımlar; üretilmiş yerel adlar, bildirim karmasına göre sınıf paylaşımı, belge kapsamı bildirimi, gölge ağaç kapsüllemesi ve yaklaşımların verdiği güvencelerin karşılaştırılması.

Önceki dersin sonunda bir sorun açıkta kaldı. Adlandırma yöntemi çakışmayı önler ama bunu
yalnız **sözleşmeyle** yapar: iki geliştirici aynı bloğa aynı adı verirse hiçbir araç
uyarmaz, kurallar sessizce birbirine karışır.

Bu ders adın kapsamını sözleşmeden çıkarıp mekanizmaya bağlayan yaklaşımları ele alır. Önce
"kapsam" sözcüğünün neyi güvenceye aldığını ayırmak gerekir.

## Kapsam Neyi Güvenceye Alır

Biçem sızıntısı tek bir olay değildir; üç ayrı olaydır.

**Ad çakışması.** İki ayrı bileşen aynı sınıf adını kullanır; birinin kuralları diğerinin
ögelerine de uyar.

**Dışarıdan sızma.** Bileşenin dışında yazılmış genel bir kural — `p`, `a`, `* + *` gibi —
bileşenin içindeki ögelere uyar.

**Dışarı sızma.** Bileşenin içinde yazılmış bir kural, bileşenin dışındaki ögelere uyar.
Alt öge birleştiricisiyle yazılmış her kuralın taşıdığı risktir.

Bir yaklaşımın "kapsamlı" sayılması, üçünü birden çözdüğü anlamına gelmez. Aşağıdaki program
önce iki üretim yöntemini hesaplıyor, sonra beş yaklaşımın hangi yönü engellediğini
karşılaştırıyor.

```js
// kapsam.mjs — yerel kapsamli ad uretimi ve bildirim karmasina gore sinif paylasimi
import { createHash } from "node:crypto";

const karma = (metin, uzunluk = 5) =>
  createHash("sha256").update(metin).digest("hex").slice(0, uzunluk);

// --- 1. yerel ad + dosya yolu -> benzersiz uretilmis ad ---
const uret = (yol, yerelAd) => `${yerelAd}_${karma(`${yol}#${yerelAd}`)}`;

const GIRDILER = [
  ["bilesenler/olcum-kart.css", "kart"],
  ["bilesenler/olcum-kart.css", "baslik"],
  ["bilesenler/yan-bilgi.css", "kart"],          // ayni yerel ad, baska dosya
  ["bilesenler/yan-bilgi.css", "baslik"],
  ["bilesenler/olcum-kart.css", "kart"],         // ayni girdi: ayni ad uretilmeli
];

console.log("--- yerel adlarin uretilmis adlara eslenmesi ---");
const uretilen = new Map();
for (const [yol, ad] of GIRDILER) {
  const u = uret(yol, ad);
  console.log(`  ${yol.padEnd(30)} .${ad.padEnd(10)} -> .${u}`);
  uretilen.set(`${yol}#${ad}`, u);
}
const cakisma = new Set([...uretilen.values()]).size !== uretilen.size;
console.log(`  ayri girdi sayisi: ${uretilen.size}, uretilen ad sayisi: ${new Set([...uretilen.values()]).size}, cakisma: ${cakisma}`);

// --- 2. bildirim kumesinin karmasina gore sinif paylasimi ---
const duzenle = (bildirimler) =>
  bildirimler.map((b) => b.replace(/\s+/g, " ").trim()).sort().join(";");
const sinif = (bildirimler) => "b" + karma(duzenle(bildirimler), 7);

const BILESENLER = {
  "olcum-kart":      ["padding: 1.5rem", "border: 1px solid #ccd", "border-radius: 4px"],
  "yan-bilgi-kutu":  ["border-radius: 4px", "padding:  1.5rem", "border: 1px solid #ccd"],  // ayni kume
  "kunye":           ["padding: 1.5rem", "border: 1px solid #ccd"],
  "konum-panosu":    ["padding: 1.5rem", "border: 1px solid #ccd", "border-radius: 4px"],
};

console.log("\n--- bildirim kumesi karmasina gore uretilen sinif ---");
const uretilenKural = new Map();
for (const [ad, bildirimler] of Object.entries(BILESENLER)) {
  const s = sinif(bildirimler);
  uretilenKural.set(s, duzenle(bildirimler));
  console.log(`  ${ad.padEnd(18)} -> .${s}`);
}
console.log(`  bilesen sayisi: ${Object.keys(BILESENLER).length}, uretilen kural sayisi: ${uretilenKural.size}`);
for (const [s, govde] of uretilenKural) console.log(`    .${s} { ${govde.replaceAll(";", "; ")} }`);

// --- 3. kapsamlama yaklasimlarinin verdigi guvenceler ---
console.log("\n--- hangi yaklasim neyi guvenceye alir ---");
const YAKLASIMLAR = [
  { ad: "yalniz adlandirma sozlesmesi", adCakismasi: false, disaridanSizma: false, disariSizma: false },
  { ad: "uretilmis yerel ad",           adCakismasi: true,  disaridanSizma: false, disariSizma: true },
  { ad: "calisma zamani uretimi",       adCakismasi: true,  disaridanSizma: false, disariSizma: true },
  { ad: "belge kapsami bildirimi",      adCakismasi: false, disaridanSizma: false, disariSizma: true },
  { ad: "golge agac kapsullemesi",      adCakismasi: true,  disaridanSizma: true,  disariSizma: true },
];
console.log("yaklasim".padEnd(30) + "ad cakismasi".padStart(14) + "disaridan sizma".padStart(18) + "disari sizma".padStart(15));
for (const y of YAKLASIMLAR) {
  const i = (v) => (v ? "engellenir" : "engellenmez");
  console.log(y.ad.padEnd(30) + i(y.adCakismasi).padStart(14) + i(y.disaridanSizma).padStart(18) + i(y.disariSizma).padStart(15));
}
```

```
--- yerel adlarin uretilmis adlara eslenmesi ---
  bilesenler/olcum-kart.css      .kart       -> .kart_39622
  bilesenler/olcum-kart.css      .baslik     -> .baslik_fc1e4
  bilesenler/yan-bilgi.css       .kart       -> .kart_28bdd
  bilesenler/yan-bilgi.css       .baslik     -> .baslik_4d665
  bilesenler/olcum-kart.css      .kart       -> .kart_39622
  ayri girdi sayisi: 4, uretilen ad sayisi: 4, cakisma: false

--- bildirim kumesi karmasina gore uretilen sinif ---
  olcum-kart         -> .b3fd5e52
  yan-bilgi-kutu     -> .b3fd5e52
  kunye              -> .bc3527a6
  konum-panosu       -> .b3fd5e52
  bilesen sayisi: 4, uretilen kural sayisi: 2
    .b3fd5e52 { border-radius: 4px; border: 1px solid #ccd; padding: 1.5rem }
    .bc3527a6 { border: 1px solid #ccd; padding: 1.5rem }

--- hangi yaklasim neyi guvenceye alir ---
yaklasim                        ad cakismasi   disaridan sizma   disari sizma
yalniz adlandirma sozlesmesi     engellenmez       engellenmez    engellenmez
uretilmis yerel ad                engellenir       engellenmez     engellenir
calisma zamani uretimi            engellenir       engellenmez     engellenir
belge kapsami bildirimi          engellenmez       engellenmez     engellenir
golge agac kapsullemesi           engellenir        engellenir     engellenir
```

## Üretilmiş Yerel Adlar

Birinci yaklaşımda kaynak dosyalarda kısa, okunur adlar yazılır: `.kart`, `.baslik`. Bir
derleme adımı bu adları dosya yoluyla birlikte karmalayarak benzersiz adlara çevirir ve
belgeyi üreten şablon da aynı eşlemeyi kullanır.

Çıktının ilk bloğu iki özelliği gösteriyor. İki ayrı dosyadaki `.kart` adı farklı adlara
çevriliyor — çakışma yapısal olarak olanaksız. Aynı girdi ise her zaman aynı adı üretiyor;
üretim **belirlenimcidir**, iki ayrı derlemede aynı çıktı verir.

Üretilen adın başına yerel adın konması bilinçlidir: geliştirici araçlarında `.kart_39622`
görüldüğünde kaynağın hangi ad olduğu okunur. Yalnız karmadan oluşan adlar bu okunurluğu
kaybeder.

Yaklaşımın sınırı, adın **çalışma zamanında birleştirilememesidir**. Ad bir dizgi
birleştirmesiyle üretiliyorsa derleyici o adı göremez ve eşleyemez; adlar kaynakta tam metin
olarak geçmelidir.

## Bildirim Karmasına Göre Paylaşım

İkinci yaklaşımda sınıf adı, bildirimlerin kendisinden türetilir. Bildirim kümesi
sıralanarak tek bir metne indirgenir ve o metnin karması sınıf adı olur.

Çıktının ikinci bloğu dört bileşen için iki kural üretiyor. Üç bileşenin bildirimleri aynı —
yazım sırası ve fazladan boşluk farklı olsa da düzenlenmiş metin aynı — ve üçü de aynı sınıfı
paylaşıyor. Bildirim kümesi farklı olan tek bileşen kendi sınıfını alıyor.

Sonuç, üretilen dosyanın bileşen sayısıyla değil **ayrı bildirim kümesi sayısıyla** büyümesidir.
Aynı gövdeyi kopyalayan önceki dersin yazımıyla karşılaştırıldığında yineleme kendiliğinden
ortadan kalkar.

Bedeli üç başlıkta toplanır. Üretim çalışma zamanında yapılıyorsa kuralların belgeye
eklenmesi ilk çizimden sonraya düşebilir. Kuralların basamaklamadaki sırası üretim sırasına
bağlıdır ve kaynağı okuyarak öngörülemez. Karma adlar okunur değildir; hata ayıklama aracı
kuralı gösterir ama hangi bileşenden geldiğini göstermez.

## Belge Kapsamı Bildirimi

CSS'in kendi aracı `@scope` kuralıdır. Bir **kapsam kökü** ve isteğe bağlı bir **kapsam
sınırı** alır; içindeki kurallar yalnız kökün alt ağacında, sınırın dışında kalan ögelere
uyar.

```css
@scope (.olcum-kart) to (.olcum-kart__govde) {
  p { margin-block: 0; }
  a { color: var(--marka-koyu); }
}
```

Buradaki `p` kuralı yalnız ölçüm kartının içinde ve kart gövdesine girmeden önce geçerlidir.
Aynı kural kapsamsız yazılsaydı sayfadaki bütün paragraflara uyardı.

`@scope` bir yenilik daha getirir: aynı özelliğe yazan iki kapsamlı kural arasında, kapsam
kökü ögeye **daha yakın** olan kazanır. Bu ölçüt özgüllükten önce değerlendirilir. İç içe
geçmiş iki tema kapsamında içteki temanın kazanması bundandır.

Tablonun gösterdiği sınır önemlidir: `@scope` dışarı sızmayı engeller, ad çakışmasını
engellemez. İki bileşen aynı sınıf adını kullanıyorsa ve ikisi de kapsamsız kural yazıyorsa
sorun sürer.

## Gölge Ağaç Kapsüllemesi

Üç yönü birden engelleyen tek yaklaşım gölge ağaçtır. Web Components ile kurulan bir gölge
kökün içindeki biçem dosyası yalnız o ağaca uygulanır; dışarıdaki seçiciler içeriye,
içerideki seçiciler dışarıya uymaz.

Kapsüllemenin bilinçli üç deliği vardır. Kalıtılan özellikler sınırı geçer: yazı tipi ve
renk dışarıdan içeriye akar. Özel özellikler de kalıtılır, dolayısıyla bileşenin biçem
arayüzü aynı mekanizmayla dışarıdan doldurulur. `::part` sözde elemanı ise bileşenin
dışarıya açtığı parçaları hedeflenebilir kılar.

Bu delikler kusur değil tasarımdır: tam yalıtım, bileşeni temaya kapatırdı.

## Seçim Ölçütü

Yaklaşımlar birbirini dışlamaz ve seçim üç soruya bağlıdır. Bileşenler ayrı takımlarca mı
yazılıyor — ad çakışması gerçek bir risk mi? Sayfaya dışarıdan biçem geliyor mu — dışarıdan
sızma korunması gerekiyor mu? Bir derleme adımı zaten var mı?

Küçük bir sayfada adlandırma sözleşmesi ile `@scope` birlikte yeterlidir; ikisi de derleme
adımı gerektirmez. Bileşenlerin bağımsız dağıtıldığı bir yerde üretilmiş adlar ya da gölge
ağaç gerekir.

## İstasyon Sayfasında

```css
/* bilesenler/olcum-kart.css — 4. adım: kapsamlı yazım */
@scope (.olcum-kart) {
  :scope {
    display: grid;
    gap: var(--aralik-0);
    background-color: var(--kart-zemin, var(--zemin));
  }

  .olcum-kart__deger { font-size: 2rem; font-variant-numeric: tabular-nums; }

  p  { margin-block: 0; }
  dt { color: var(--metin-soluk); }
}
```

`:scope` sözde sınıfı kapsam kökünün kendisini hedefler. Tür seçicileri artık güvenle
yazılabiliyor: `p` ve `dt` kuralları yalnız kartın içinde geçerli, sayfanın geri kalanına
sızmıyor.

Sınıf adları yine de yöntemli yazıldı. Kapsam dışarı sızmayı kesiyor, ama sayfada başka bir
`.olcum-kart__deger` tanımlanırsa iki kural yine yarışır.

## Özet

- Biçem sızıntısı üç ayrı olaydır: ad çakışması, dışarıdan sızma ve dışarı sızma; bir
  yaklaşım bunların hepsini birden engellemeyebilir.
- Üretilmiş yerel adlar, yerel adı dosya yoluyla karmalayarak çakışmayı yapısal olarak
  önler ve belirlenimcidir; adın çalışma zamanında birleştirilmemesi koşuluyla çalışır.
- Bildirim karmasına göre üretilen sınıflar aynı bildirim kümesini paylaştırır; üretilen
  dosya bileşen sayısıyla değil ayrı bildirim kümesi sayısıyla büyür.
- `@scope` bir kök ve sınır alır, dışarı sızmayı keser ve yakınlık ölçütünü özgüllükten
  önce uygular; ad çakışmasını engellemez.
- Gölge ağaç üç yönü de kapatır; kalıtılan özellikler, özel özellikler ve `::part` bilinçli
  olarak açık bırakılmış geçitlerdir.

## Sonraki Adım

Buraya kadarki yaklaşımların hepsi aynı varsayımı paylaşıyor: biçem bileşen başına yazılır
ve her bileşenin kendi kuralları vardır. Bunun tersini savunan bir yaklaşım daha vardır —
bileşene özel kural hiç yazmamak, belgeyi önceden tanımlı ve tek bildirimlik sınıflardan
kurmak. Sonraki ders bu yaklaşımı ve dayandığı kısıt düşüncesini ele alır.
