---
title: 'Izgara Modeli'
source: 'https://academia.sh/tr/kurslar/duzen-ve-duyarli-tasarim/izgara-modeli'
course: 'Düzen Sistemleri ve Duyarlı Tasarım'
language: tr
updated: '2026-08-17T18:09:24+00:00'
license: 'CC BY-SA 4.0'
---

# Izgara Modeli

Izgara bağlamının kurulması, şerit ile hat ayrımı, pay biriminin boş alanı bölmesi, en küçük içerik ölçüsünün pay üzerindeki gizli alt sınırı ve alanların adlandırılması.

Esnek kutu tek eksende dağıtır: bir doğrultuda paylaştırır, diğerinde yalnızca hizalar. Bir
süzgeç çubuğu için bu yeterlidir. Ölçüm sayfasının bütünü ise iki eksende hizalanmış
bölgeler ister: künye, ölçüm çizelgesi ve yan sütun birbirinin hem satırına hem sütununa
göre yerleşmelidir.

Bu ders, satır ve sütunları **önceden** tanımlayan düzen modelini kurar. Esnek kutuda
yerleşim ögelerin ölçülerinden doğar; ızgarada önce boş bir çizgi düzeni tanımlanır ve
ögeler bu düzene yerleştirilir.

## Izgara Bağlamı

Bir kutuya `display: grid` bildirildiğinde kutu **ızgara kapsayıcısı (grid container)**
olur; doğrudan çocukları **ızgara ögesi (grid item)** olarak yerleştirilir. Esnek kutudaki
gibi kapsayıcının kendisi akışta blok kutu olarak kalır, çocukların `display` değeri
bloklaşır ve dış boşlukları çökmez.

Ayrım, kapsayıcıya ne bildirildiğindedir. Esnek kutuda tek bir yön bildirilir; ızgarada iki
eksenin **şerit tanımı** yazılır:

```css
.istasyon-duzeni {
  display: grid;
  grid-template-columns: 240px 2fr 1fr;
  grid-template-rows: auto 1fr;
  gap: 24px;
}
```

## Şerit, Hat ve Hücre

Dört kavram birbirinden ayrı tutulur.

**Şerit (grid track)** iki komşu çizgi arasındaki bant: bir sütun ya da bir satır.
Yukarıdaki bildirim üç sütun şeridi ve iki satır şeridi tanımlar.

**Hat (grid line)** şeritleri ayıran çizgi. Üç sütun şeridi **dört** hat üretir; hatlar
başlangıçtan itibaren 1'den numaralanır. Aynı hatlar sondan başlayarak eksi değerlerle de
anılır: son hat $-1$, bir öncesi $-2$. Bir ögeyi ızgaranın sonuna kadar uzatmak için şerit
sayısını bilmek gerekmez, $-1$ yeterlidir.

**Hücre (grid cell)** bir satır şeridi ile bir sütun şeridinin kesişimi; ızgaranın en küçük
birimi.

**Alan (grid area)** dört hatla sınırlanan dikdörtgen bölge; bir ya da daha çok hücreyi
kapsar. Bir ögenin yerleşimi her zaman bir alandır.

Hatlara ad verilebilir ve ad, köşeli ayraç içinde şerit tanımının arasına yazılır:

```css
.istasyon-duzeni {
  display: grid;
  grid-template-columns: [kenar-bas] 240px [icerik-bas] 2fr 1fr [kenar-son];
}
```

Adlandırılmış hat, sayı yerine kullanılabilir ve şerit sayısı değiştiğinde yerleşim
bildirimlerinin yeniden yazılmasını gereksiz kılar.

## Pay Birimi Boş Alanı Böler

`fr`, ızgaraya özgü bir birimdir: **pay birimi (fractional unit)**. Bir uzunluk değildir;
sabit şeritler ve aralıklar düşüldükten sonra **kalan alanın** kaç paya bölüneceğini söyler.

```js
// serit.mjs — fr biriminin bos alani boluse ve gizli alt siniri
const ARALIK = 24;

// serit tanimi: sabit uzunluklar once ayrilir, kalan fr paylarina bolunur
const seritler = [
  { yazim: "240px", sabit: 240, fr: 0 },
  { yazim: "2fr", sabit: 0, fr: 2 },
  { yazim: "1fr", sabit: 0, fr: 1 },
];

const araToplam = ARALIK * (seritler.length - 1);
const sabitToplam = seritler.reduce((t, s) => t + s.sabit, 0);
const frToplam = seritler.reduce((t, s) => t + s.fr, 0);

function paylar(kapsayici) {
  const bos = kapsayici - sabitToplam - araToplam;
  return seritler.map((s) => s.sabit + (s.fr / frToplam) * bos);
}

const KAP = 960;
console.log(`grid-template-columns: ${seritler.map((s) => s.yazim).join(" ")}   gap: ${ARALIK}px   kapsayici: ${KAP}px`);
console.log(`sabit=${sabitToplam}  aralik=${araToplam}  bolunecek bos alan=${KAP - sabitToplam - araToplam}  fr toplami=${frToplam}`);
paylar(KAP).forEach((o, i) => console.log(`  ${seritler[i].yazim.padEnd(6)} -> ${o.toFixed(1)}px`));

console.log("\n--- fr, kapsayicinin degil bos alanin payidir ---");
for (const ekSabit of [0, 240, 480]) {
  const bir = (KAP - ekSabit - araToplam) / 3;
  console.log(`sabit serit ${String(ekSabit).padStart(3)}px -> 1fr = ${bir.toFixed(1)}px  (2fr = ${(2 * bir).toFixed(1)}px)`);
}

// dar kapsayicida fr payi, seridin en kucuk icerik olcusunun altina duser
const DAR = 600;
const enKucukIcerik = [90, 180, 160];   // her seridin en uzun bolunemez icerigi
console.log(`\n--- dar kapsayici (${DAR}px): 1fr = minmax(auto, 1fr) ---`);
let toplam = 0;
paylar(DAR).forEach((pay, i) => {
  const alt = seritler[i].fr > 0 ? enKucukIcerik[i] : 0;
  const uygulanan = Math.max(pay, alt);
  toplam += uygulanan;
  console.log(`  ${seritler[i].yazim.padEnd(6)} pay=${pay.toFixed(1).padStart(6)}  en kucuk icerik=${String(alt).padStart(3)}  uygulanan=${uygulanan.toFixed(1).padStart(6)}`);
});
console.log(`  seritler+aralik = ${(toplam + araToplam).toFixed(1)}px, kapsayici = ${DAR}px, tasma = ${(toplam + araToplam - DAR).toFixed(1)}px`);

console.log(`\n--- ayni kapsayicida minmax(0, 1fr) ---`);
let toplam2 = 0;
paylar(DAR).forEach((pay, i) => {
  toplam2 += pay;
  const ad = seritler[i].fr > 0 ? `minmax(0, ${seritler[i].fr}fr)` : seritler[i].yazim;
  console.log(`  ${ad.padEnd(16)} uygulanan=${pay.toFixed(1).padStart(6)}`);
});
console.log(`  seritler+aralik = ${(toplam2 + araToplam).toFixed(1)}px, tasma = ${(toplam2 + araToplam - DAR).toFixed(1)}px`);
```

```
grid-template-columns: 240px 2fr 1fr   gap: 24px   kapsayici: 960px
sabit=240  aralik=48  bolunecek bos alan=672  fr toplami=3
  240px  -> 240.0px
  2fr    -> 448.0px
  1fr    -> 224.0px

--- fr, kapsayicinin degil bos alanin payidir ---
sabit serit   0px -> 1fr = 304.0px  (2fr = 608.0px)
sabit serit 240px -> 1fr = 224.0px  (2fr = 448.0px)
sabit serit 480px -> 1fr = 144.0px  (2fr = 288.0px)

--- dar kapsayici (600px): 1fr = minmax(auto, 1fr) ---
  240px  pay= 240.0  en kucuk icerik=  0  uygulanan= 240.0
  2fr    pay= 208.0  en kucuk icerik=180  uygulanan= 208.0
  1fr    pay= 104.0  en kucuk icerik=160  uygulanan= 160.0
  seritler+aralik = 656.0px, kapsayici = 600px, tasma = 56.0px

--- ayni kapsayicida minmax(0, 1fr) ---
  240px            uygulanan= 240.0
  minmax(0, 2fr)   uygulanan= 208.0
  minmax(0, 1fr)   uygulanan= 104.0
  seritler+aralik = 600.0px, tasma = 0.0px
```

İlk blok hesabın sırasını gösteriyor: 960 birimlik kapsayıcıdan önce sabit şerit (240) ve
iki aralık (48) düşülür, kalan 672 birim üç paya bölünür. `2fr` iki pay alır (448), `1fr`
bir pay (224).

İkinci blok sık yapılan bir okuma hatasını düzeltiyor. `1fr` kapsayıcının üçte biri
değildir; **boş alanın** üçte biridir. Sabit şerit büyüdükçe aynı `1fr` bildiriminin
karşılığı 304'ten 144'e iner. Şerit tanımının kendisi değişmemiştir, bölünen değişmiştir.

Pay toplamı birden küçükse boş alanın tamamı dağıtılmaz: `0.5fr 0.5fr` yazımı boş alanın
yarısını kullanır, kalanı ızgaranın sonunda durur. Bu davranış, aynı bildirimin esnek
kutudaki karşılığıyla tutarlıdır.

## Payın Gizli Alt Sınırı

Üçüncü blok, ızgara tanımlarındaki en sık taşma nedenini gösteriyor. Kapsayıcı 600 birime
indiğinde son şeridin payı 104 birim hesaplanır, ama şeridin içinde bölünemeyen 160 birimlik
bir içerik vardır — uzun bir ölçüm kodu ya da bir tablo. Şerit 160'ta durur ve toplam
kapsayıcıyı 56 birim aşar.

Nedeni şudur: `1fr` yazımı, tam açılımıyla `minmax(auto, 1fr)` demektir. Alt sınır `auto`
olduğunda şerit, içeriğinin **en küçük içerik ölçüsünün** altına inemez. Pay bu sınırın
altına düşerse sınır kazanır.

Dördüncü blok çözümü veriyor: alt sınır açıkça sıfıra çekilirse şerit paya uyar ve taşma
ortadan kalkar. Bedeli, içeriğin şerit içinde taşabilmesidir; taşma yönetimi CSS ile Görsel
Sunum kursunda kurulan bildirimlerle o şeritte ayrıca ele alınır.

Bu, esnek kutudaki `min-width: auto` kısıtının ızgaradaki karşılığıdır. İki modelde de
sorunun kaynağı aynıdır: içerik ölçüsü, hesaplanan paydan büyük olduğunda kısıt kazanır.

## Yineleme ve Aralık

Aynı şerit tanımını elle tekrarlamak yerine `repeat()` yazılır. İlginç olan, yineleme
sayısının bir sayı yerine iki anahtar sözcükle verilebilmesidir: `auto-fill` ve `auto-fit`.
İkisi de kapsayıcıya sığan en çok şeridi üretir; ayrım, üretilen şeritlerin **boş kalması**
durumundadır.

```js
// yineleme.mjs — auto-fill ve auto-fit ile uretilen serit sayisi
const EN_KUCUK = 220;   // minmax(220px, 1fr)
const ARALIK = 24;
const OGE_SAYISI = 5;

// kapsayiciya sigan en cok serit: n*enKucuk + (n-1)*aralik <= genislik
function seritSayisi(genislik) {
  const n = Math.floor((genislik + ARALIK) / (EN_KUCUK + ARALIK));
  return Math.max(1, n);
}

const olcu = (genislik, n) => (genislik - ARALIK * (n - 1)) / n;

console.log("repeat(auto-fill | auto-fit, minmax(220px, 1fr))   gap: 24px   oge sayisi: 5");
console.log("genislik  serit  auto-fill olcu   dolu serit  auto-fit olcu");
for (const g of [320, 500, 760, 1000, 1240, 1600]) {
  const n = seritSayisi(g);
  const dolu = Math.min(n, OGE_SAYISI);
  const fill = olcu(g, n);
  const fit = olcu(g, dolu);
  console.log(
    String(g).padStart(8) +
    String(n).padStart(7) +
    (fill.toFixed(1) + "px").padStart(16) +
    String(dolu).padStart(12) +
    (fit.toFixed(1) + "px").padStart(15)
  );
}

console.log("\n--- sinir: serit sayisinin arttigi tam genislikler ---");
for (let n = 1; n <= 6; n++) {
  const esik = n * EN_KUCUK + (n - 1) * ARALIK;
  console.log(`${n} serit icin gereken en az genislik: ${esik}px`);
}

console.log("\n--- ayni hesap sabit serit sayisiyla: repeat(4, minmax(220px, 1fr)) ---");
for (const g of [500, 760, 1000]) {
  const n = 4;
  const pay = olcu(g, n);
  const uygulanan = Math.max(pay, EN_KUCUK);
  const tasma = uygulanan * n + ARALIK * (n - 1) - g;
  console.log(`genislik ${String(g).padStart(4)} -> pay ${pay.toFixed(1)}px, uygulanan ${uygulanan.toFixed(1)}px, tasma ${tasma.toFixed(1)}px`);
}
```

```
repeat(auto-fill | auto-fit, minmax(220px, 1fr))   gap: 24px   oge sayisi: 5
genislik  serit  auto-fill olcu   dolu serit  auto-fit olcu
     320      1         320.0px           1        320.0px
     500      2         238.0px           2        238.0px
     760      3         237.3px           3        237.3px
    1000      4         232.0px           4        232.0px
    1240      5         228.8px           5        228.8px
    1600      6         246.7px           5        300.8px

--- sinir: serit sayisinin arttigi tam genislikler ---
1 serit icin gereken en az genislik: 220px
2 serit icin gereken en az genislik: 464px
3 serit icin gereken en az genislik: 708px
4 serit icin gereken en az genislik: 952px
5 serit icin gereken en az genislik: 1196px
6 serit icin gereken en az genislik: 1440px

--- ayni hesap sabit serit sayisiyla: repeat(4, minmax(220px, 1fr)) ---
genislik  500 -> pay 107.0px, uygulanan 220.0px, tasma 452.0px
genislik  760 -> pay 172.0px, uygulanan 220.0px, tasma 192.0px
genislik 1000 -> pay 232.0px, uygulanan 232.0px, tasma 0.0px
```

`minmax(a, b)` bir şeridin alt ve üst sınırını verir: şerit `a` değerinin altına inmez, `b`
değerinin üstüne çıkmaz. `minmax(220px, 1fr)` yazımı "en az 220 birim, kalanı pay olarak
al" demektir ve yineleme sayısı bu alt sınırdan türetilir.

Şerit sayısı doğrudan çıkar: $n$ şerit için gereken en az genişlik
$n \times 220 + (n-1) \times 24$ birimdir ve kapsayıcı bu değeri aştıkça sayı artar. İkinci
blok bu eşikleri veriyor; birinci bloktaki sayılar tam olarak eşiklerle uyumludur — 1000
birimlik kapsayıcı dört şerit alır, çünkü dördüncü eşik 952'dir ve beşinci eşik 1196'dır.

Ayrım son satırda görünür. 1600 birimlik kapsayıcı altı şerit alacak kadar geniştir ama
yerleştirilecek beş öge vardır. `auto-fill` altıncı şeridi **boş olarak korur**; ögeler 246,7
birimde kalır ve sağda boş bir sütun durur. `auto-fit` boş şeridi **çökertir**; şerit ve
aralığı ortadan kalkar, beş öge kalan alanı paylaşır ve 300,8 birime çıkar.

Seçim ölçütü içerikle ilgilidir. Kart genişliğinin tutarlı kalması isteniyorsa ve ögeler
farklı sayfalarda değişiyorsa `auto-fill` doğrudur: aynı kart her sayfada aynı genişliktedir.
Ögelerin kapsayıcıyı her durumda doldurması isteniyorsa `auto-fit` doğrudur.

Üçüncü blok, sabit yineleme sayısının neden dar ekranlarda taştığını gösteriyor:
`repeat(4, …)` yazımı dört şeridi koşulsuz üretir, alt sınır 220 birimde tutar ve 500
birimlik bir kapsayıcıda 452 birim taşma verir. Yineleme anahtar sözcükleri bu koşulu
kapsayıcıdan okur; bir sonraki konuda ele alınacak ortam sorgularına gerek kalmadan şerit
sayısını uyarlarlar.

## Alanların Adlandırılması

Şerit tanımı ızgarayı kurar; ögelerin nereye düşeceği ayrı bir bildirimdir. En okunur yolu,
alanlara ad vermek ve yerleşimi kapsayıcıda metin olarak çizmektir:

```css
/* duzen.css — 3. adım: sayfa ızgarası */
.istasyon-duzeni {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  grid-template-rows: auto auto 1fr;
  grid-template-areas:
    "kunye     kunye"
    "olcumler  yan-bilgi"
    "konum     yan-bilgi";
  gap: var(--aralik-1);
}

.kunye        { grid-area: kunye; }
.olcum-bolumu { grid-area: olcumler; }
.konum-bolumu { grid-area: konum; }
.yan-bilgi    { grid-area: yan-bilgi; }
```

Dizgilerin her satırı bir satır şeridine, her sütunu bir sütun şeridine karşılık gelir. Aynı
adın iki hücrede geçmesi, alanın o hücreleri kapsadığını söyler; `yan-bilgi` iki satır
boyunca uzanır. Ad yerine nokta yazılırsa hücre boş bırakılır.

Bu yazımın değeri, düzenin biçem dosyasında **görünür** olmasıdır: satırların hizası
ızgaranın kendisini çizer. Ögelerin belgedeki sırası ile ızgaradaki yeri birbirinden
bağımsızdır — bu ayrımın erişilebilirlik sonuçları sonraki derste ele alınacaktır.

## Özet

- `display: grid` iki eksende şerit tanımı alır; şerit iki hat arasındaki bant, hücre iki
  şeridin kesişimi, alan ise dört hatla sınırlanan dikdörtgen bölgedir.
- Hatlar baştan 1'den, sondan $-1$'den numaralanır; ada bağlanabilir ve ad, şerit sayısı
  değiştiğinde yerleşim bildirimlerini korur.
- `fr` bir uzunluk değil pay birimidir: sabit şeritler ve aralıklar düşüldükten sonra kalan
  alanı böler, dolayısıyla kapsayıcının değil boş alanın oranını verir.
- `1fr` açılımıyla `minmax(auto, 1fr)` olduğu için şerit en küçük içerik ölçüsünün altına
  inmez; taşmayı önlemek için alt sınır `minmax(0, 1fr)` ile açıkça sıfırlanır.
- `repeat(auto-fill, …)` sığan bütün şeritleri üretir ve boş olanları korur, `auto-fit` boş
  şeritleri çökerterek kalan ögelere dağıtır.

## Sonraki Adım

Şerit tanımı ızgarayı kurdu, adlandırılmış alanlar da yerleşimi çizdi. Ama alan tanımı
yazılmamış ögeler nereye düşer? Kapsayıcının içinde tanımlanandan çok öge varsa ne olur?
Sonraki ders, ögeleri hatlara göre açıkça yerleştiren bildirimleri ve boşta kalanları
yerleştiren otomatik algoritmayı ele alır.
