---
title: 'Çok Sütunlu Düzen'
source: 'https://academia.sh/tr/kurslar/duzen-ve-duyarli-tasarim/cok-sutunlu-duzen'
course: 'Düzen Sistemleri ve Duyarlı Tasarım'
language: tr
updated: '2026-08-17T18:09:25+00:00'
license: 'CC BY-SA 4.0'
---

# Çok Sütunlu Düzen

Metin akışının sütunlara bölünmesi, sütun sayısı ile sütun genişliği bildirimlerinin birlikte çözülmesi, dengeleme kuralı, kırılma denetimi ve çok sütunlu düzenin uygun olmadığı durumlar.

Buraya kadarki bütün düzenlerde birim bir kutuydu: kart, bölüm, düğme. Kutular hatlara
yerleştirildi ya da eksende dağıtıldı. Sayfadaki uzun açıklama metni ise tek bir kutudur ve
geniş bir kapsayıcıda tek bir satır dizisi olarak uzar.

Bu ders metnin kendisini bölen modeli ele alır. **Çok sütunlu düzen (multi-column layout)**,
bir kutunun içeriğini birden çok sütuna dağıtır; kutuyu bölmez, akışı böler. Ayrım küçük
görünür ama düzenin bütün davranışını belirler.

## Akışı Bölmek, Kutuyu Bölmek Değil

Bir kutuya `columns` bildirildiğinde kutunun kendisi tek bir kutu olarak kalır. Kenarlığı,
arka planı ve dış boşluğu bütüne uygulanır. Değişen, kutunun içindeki satırların
yerleştirilmesidir: satırlar birinci sütunu doldurur, dolduğunda ikinci sütuna geçer.

Bu, esnek kutu ve ızgaradan iki noktada ayrılır. Birincisi, sütunlar birer öge değildir;
seçiciyle hedeflenemez, sayıları belgede görünmez. İkincisi, tek bir paragraf iki sütuna
**bölünebilir**: metnin ilk üç satırı birinci sütunda, kalan iki satırı ikinci sütunda yer
alabilir. Izgarada bir öge iki şeride bölünmez, yayılır; burada içerik gerçekten parçalanır.

Bu yüzden çok sütunlu düzen bir sayfa düzeni aracı değildir. Sayfa bölümlerini yan yana
koymak için ızgara vardır; çok sütunlu düzen, tek bir sürekli metnin okunabilir genişlikte
kalması için kullanılır.

## Sayı mı, Genişlik mi

İki bildirim vardır ve ikisi de aynı hesaba girer. `column-count` kaç sütun olacağını,
`column-width` bir sütunun **en az** ne kadar geniş olacağını söyler. `columns` kısayolu
ikisini birlikte yazar.

Hangisi yazılırsa yazılsın, kullanılan sütun sayısı ve kullanılan sütun genişliği tek bir
kuralla türetilir.

```js
// sutun.mjs — cok sutunlu duzende kullanilan sutun sayisi ve genisligi
// CSS Multi-column sozde algoritmasi: sayi ve genislikten hangisi yazilmissa
// digeri kapsayicinin genisliginden turetilir.
const GAP = 32; // column-gap: 2rem (kok 16px)

function coz(W, { genislik, sayi }) {
  let kullanilanSayi;
  if (sayi === "auto") {
    kullanilanSayi = Math.max(1, Math.floor((W + GAP) / (genislik + GAP)));
  } else if (genislik === "auto") {
    kullanilanSayi = sayi;
  } else {
    kullanilanSayi = Math.min(sayi, Math.max(1, Math.floor((W + GAP) / (genislik + GAP))));
  }
  const kullanilanGenislik = (W - GAP * (kullanilanSayi - 1)) / kullanilanSayi;
  return { sayi: kullanilanSayi, genislik: kullanilanGenislik };
}

const durumlar = [
  ["column-width: 18rem", { genislik: 288, sayi: "auto" }],
  ["column-count: 3", { genislik: "auto", sayi: 3 }],
  ["columns: 18rem 3", { genislik: 288, sayi: 3 }],
];

console.log(`column-gap: 2rem = ${GAP}px   (18rem = 288px, kok 16px)`);
for (const [ad, bildirim] of durumlar) {
  console.log(`\n--- ${ad} ---`);
  console.log("kapsayici  sutun  sutun genisligi");
  for (const W of [320, 480, 640, 800, 1024, 1280]) {
    const { sayi, genislik } = coz(W, bildirim);
    console.log(
      `${String(W).padStart(9)}  ${String(sayi).padStart(5)}  ${genislik.toFixed(1).padStart(15)}`,
    );
  }
}

// column-width bir alt sinirdir: n sutun uretildiginde kullanilan genislik
// [U, ((n+1)U + G)/n) araliginda kalir. Aralik n buyudukce daralir.
console.log("\n--- column-width bir alt sinirdir: kullanilan genisligin araligi ---");
console.log("U = 288px (18rem), G = 32px");
console.log("sutun  en dar  en genis (sinira yaklasirken)  oran");
for (let n = 1; n <= 5; n++) {
  const U = 288;
  const enDar = U;
  const enGenis = ((n + 1) * U + GAP) / n;
  console.log(
    `${String(n).padStart(5)}  ${enDar.toFixed(1).padStart(6)}  ` +
      `${enGenis.toFixed(1).padStart(28)}  ${(enGenis / enDar).toFixed(2).padStart(4)}`,
  );
}
```

```
column-gap: 2rem = 32px   (18rem = 288px, kok 16px)

--- column-width: 18rem ---
kapsayici  sutun  sutun genisligi
      320      1            320.0
      480      1            480.0
      640      2            304.0
      800      2            384.0
     1024      3            320.0
     1280      4            296.0

--- column-count: 3 ---
kapsayici  sutun  sutun genisligi
      320      3             85.3
      480      3            138.7
      640      3            192.0
      800      3            245.3
     1024      3            320.0
     1280      3            405.3

--- columns: 18rem 3 ---
kapsayici  sutun  sutun genisligi
      320      1            320.0
      480      1            480.0
      640      2            304.0
      800      2            384.0
     1024      3            320.0
     1280      3            405.3

--- column-width bir alt sinirdir: kullanilan genisligin araligi ---
U = 288px (18rem), G = 32px
sutun  en dar  en genis (sinira yaklasirken)  oran
    1   288.0                         608.0  2.11
    2   288.0                         448.0  1.56
    3   288.0                         394.7  1.37
    4   288.0                         368.0  1.28
    5   288.0                         352.0  1.22
```

Üç bildirim biçimi, üç ayrı davranış.

`column-width` tek başına yazıldığında sütun sayısı kapsayıcıdan türetilir ve üst sınırı
yoktur: kapsayıcı genişledikçe sütun eklenir. Çok geniş bir ekranda beş, altı sütun oluşması
istenmiyorsa bu bildirim tek başına yetmez.

`column-count` tek başına yazıldığında sütun sayısı sabittir ve kapsayıcı daraldığında
sütunlar birlikte daralır. Çıktının ikinci bloğu bunun sonucunu gösteriyor: 320 birimlik bir
kapsayıcıda üç sütun, her biri 85 birim. Bir sütuna on karakter sığar; metin okunamaz hâle
gelir. Bu bildirim, dar kapsayıcıya uyarlanmak için tek başına kullanılamaz.

`columns: 18rem 3` ikisini birleştirir ve şu cümleyi yazar: "en fazla üç sütun, ama her sütun
en az 18 taban birim genişliğinde olsun." Sütun sayısı iki koşulun küçüğüdür; dar kapsayıcıda
genişlik koşulu, geniş kapsayıcıda sayı koşulu bağlayıcı olur. Uygulamada aranan davranış
çoğu zaman budur.

Son blok, sıkça yanlış anlaşılan bir noktayı sayıya döküyor. `column-width` bir hedef değil,
bir **alt sınırdır**. Kapsayıcı 18 taban birimden geniş olduğu sürece kullanılan genişlik bu
değerin altına inmez, ama üstüne çıkabilir: tek sütunlu durumda iki katından fazlasına kadar.
Sütun sayısı arttıkça bu oran daralır, çünkü yeni bir sütun daha erken eklenir. Bu yüzden
`column-width` değeri, kabul edilebilir **en dar** ölçüye göre seçilir; okumak için ideal olan
ölçüye göre değil.

Kapsayıcı `column-width` değerinden dar olduğunda alt sınır uygulanamaz. Sütun sayısı bire
düşer ve genişlik kapsayıcıya eşitlenir; taşma oluşmaz.

## İçerik Sütunlara Nasıl Dağılır

Sütunların ölçüsü belli olduğunda ikinci soru gelir: hangi satır hangi sütuna gider?
`column-fill` bunu bildirir. `balance` değeri sütun yüksekliklerini eşitlemeye çalışır, `auto`
değeri sütunları sırayla doldurur ve bunun için kutuya bir yükseklik verilmiş olmasını
gerektirir.

Dengeleme, bölünmez bloklar olmadığında yalnız bir bölmedir. Bölünmez bloklar girdiğinde
sonuç değişir.

```js
// denge.mjs — sutun dengeleme modeli: icerik sutunlara hangi yukseklikte boluniyor
// Olcu birimi satirdir. Bir blok "bolunmez" ise break-inside: avoid yazilmis demektir.
const SUTUN = 3;

const icerik = [
  { ad: "giris-p", satir: 6, bolunur: true },
  { ad: "yontem-p", satir: 5, bolunur: true },
  { ad: "olcu-listesi", satir: 7, bolunur: false },
  { ad: "ara-p", satir: 4, bolunur: true },
  { ad: "sekil", satir: 9, bolunur: false },
  { ad: "sonuc-p", satir: 8, bolunur: true },
  { ad: "not-p", satir: 3, bolunur: true },
];

// Verilen sutun yuksekligiyle icerigi sirayla sutunlara dagitir.
function paketle(H) {
  const sutunlar = [[]];
  let dolu = 0;
  const yeniSutun = () => { sutunlar.push([]); dolu = 0; };

  for (const blok of icerik) {
    if (!blok.bolunur) {
      if (dolu > 0 && dolu + blok.satir > H) yeniSutun();
      sutunlar[sutunlar.length - 1].push(`${blok.ad}(${blok.satir})`);
      dolu += blok.satir;
      continue;
    }
    let kalan = blok.satir;
    let parca = 0;
    while (kalan > 0) {
      if (dolu >= H) yeniSutun();
      const konan = Math.min(kalan, H - dolu);
      parca += 1;
      const etiket = kalan === blok.satir && konan === blok.satir
        ? `${blok.ad}(${konan})`
        : `${blok.ad}.${parca}(${konan})`;
      sutunlar[sutunlar.length - 1].push(etiket);
      dolu += konan;
      kalan -= konan;
    }
  }
  const yukseklikler = sutunlar.map((s) =>
    s.reduce((t, e) => t + Number(e.match(/\((\d+)\)/)[1]), 0));
  return { sutunlar, yukseklikler };
}

const toplam = icerik.reduce((t, b) => t + b.satir, 0);
console.log(`toplam ${toplam} satir, ${SUTUN} sutun, esit bolunme ${(toplam / SUTUN).toFixed(2)} satir`);
console.log("bolunmez bloklar: " + icerik.filter((b) => !b.bolunur).map((b) => `${b.ad}(${b.satir})`).join(", "));

// column-fill: balance — sutun sayisini asmayan en kucuk yukseklik aranir
let H = Math.ceil(toplam / SUTUN);
let sonuc = paketle(H);
while (sonuc.sutunlar.length > SUTUN) {
  H += 1;
  sonuc = paketle(H);
}
console.log(`\n--- column-fill: balance  (bulunan yukseklik: ${H} satir) ---`);
sonuc.sutunlar.forEach((s, i) => {
  console.log(`sutun ${i + 1} (${sonuc.yukseklikler[i]} satir): ${s.join(" | ")}`);
});
console.log(`en yuksek - en alcak fark: ${Math.max(...sonuc.yukseklikler) - Math.min(...sonuc.yukseklikler)} satir`);

// column-fill: auto — yukseklik disaridan verilir, sutunlar sirayla doldurulur
const SABIT = 12;
const oto = paketle(SABIT);
console.log(`\n--- column-fill: auto, block-size: ${SABIT} satir ---`);
oto.sutunlar.forEach((s, i) => {
  const tasma = i >= SUTUN ? "  <- tanimli sutun sayisini asti" : "";
  console.log(`sutun ${i + 1} (${oto.yukseklikler[i]} satir): ${s.join(" | ")}${tasma}`);
});

// bolunmez bloklar kaldirilirsa dengeleme ne kadar iyilesir
const eskiIcerik = icerik.map((b) => ({ ...b }));
for (const b of icerik) b.bolunur = true;
let H2 = Math.ceil(toplam / SUTUN);
let s2 = paketle(H2);
while (s2.sutunlar.length > SUTUN) { H2 += 1; s2 = paketle(H2); }
console.log(`\n--- ayni icerik, hicbir blokta break-inside: avoid yok ---`);
console.log(`bulunan yukseklik: ${H2} satir (bolunmez bloklarla: ${H} satir)`);
s2.sutunlar.forEach((s, i) => {
  console.log(`sutun ${i + 1} (${s2.yukseklikler[i]} satir): ${s.join(" | ")}`);
});
icerik.forEach((b, i) => { b.bolunur = eskiIcerik[i].bolunur; });
```

```
toplam 42 satir, 3 sutun, esit bolunme 14.00 satir
bolunmez bloklar: olcu-listesi(7), sekil(9)

--- column-fill: balance  (bulunan yukseklik: 18 satir) ---
sutun 1 (18 satir): giris-p(6) | yontem-p(5) | olcu-listesi(7)
sutun 2 (18 satir): ara-p(4) | sekil(9) | sonuc-p.1(5)
sutun 3 (6 satir): sonuc-p.2(3) | not-p(3)
en yuksek - en alcak fark: 12 satir

--- column-fill: auto, block-size: 12 satir ---
sutun 1 (11 satir): giris-p(6) | yontem-p(5)
sutun 2 (11 satir): olcu-listesi(7) | ara-p(4)
sutun 3 (12 satir): sekil(9) | sonuc-p.1(3)
sutun 4 (8 satir): sonuc-p.2(5) | not-p(3)  <- tanimli sutun sayisini asti

--- ayni icerik, hicbir blokta break-inside: avoid yok ---
bulunan yukseklik: 14 satir (bolunmez bloklarla: 18 satir)
sutun 1 (14 satir): giris-p(6) | yontem-p(5) | olcu-listesi.1(3)
sutun 2 (14 satir): olcu-listesi.2(4) | ara-p(4) | sekil.1(6)
sutun 3 (14 satir): sekil.2(3) | sonuc-p(8) | not-p(3)
```

Bu bir modeldir, tarayıcının çıktısı değil: satır sayıları varsayılmış, dengeleme araması
en küçük yüksekliği bulacak biçimde yazılmıştır. Modelin gösterdiği kısıt gerçektir.

Üçüncü blok, bölünmenin serbest olduğu durumu veriyor: 42 satır üç sütuna 14, 14, 14 olarak
dağılıyor. Eşit bölünmeden başka bir sonuç yok.

Birinci blokta iki blok bölünmez işaretli. Dengeleme, üçüncü bir sütun açmadan içeriği
sığdırabilen en küçük yüksekliği arıyor ve 14 yerine 18 buluyor. Sonuçtaki dağılım 18, 18, 6;
son sütun diğerlerinin üçte biri kadar dolu. Bölünmez bir blok, kendisinden küçük bir boşluğa
sığmadığında bir sonraki sütunun başına atlar ve arkasında kullanılamayan boşluk bırakır.
Dengeleme bu boşlukları geri kazanamaz.

İkinci blok `auto` değerini gösteriyor. Yükseklik dışarıdan verilmiş, sütunlar sırayla
doluyor ve içerik üç sütuna sığmıyor: dördüncü bir sütun oluşuyor. Tanımlı sütun sayısını
aşan bu sütunlara **taşan sütun (overflow column)** denir ve kutunun sınırının dışına çıkar.
`column-fill: auto` bu yüzden yalnız yüksekliği denetlenen kutularda anlamlıdır.

## Kırılma Denetimi

Metin sütunlar arasında bölündüğünde bazı bölünmeler istenmez: bir başlık sütunun en altında
tek başına kalmamalı, bir tablo ortadan ikiye ayrılmamalıdır. Bunu bildiren özellik ailesi
kırılma denetimidir.

`break-inside: avoid` bir kutunun içinden bölünmesini engeller. `break-before: column` ve
`break-after: column` bir kutunun önünde ya da arkasında sütun kırılmasını zorlar. Bu
bildirimler yalnız çok sütunlu düzende değil, sayfalanmış çıktıda (yazdırma) da aynı adlarla
çalışır; ikisi de içeriğin parçalara ayrıldığı bağlamlardır.

İki bildirim daha satır düzeyinde çalışır. `orphans` bir parçanın **sonunda** bırakılacak en
az satır sayısını, `widows` bir sonraki parçanın **başında** bulunacak en az satır sayısını
verir. Varsayılan değer ikisi için de 2'dir: bir paragrafın son satırı, tek başına yeni bir
sütunun başına düşmez.

Bu bildirimler istek bildirir, garanti vermez. İstek yerine getirildiğinde bir bedeli olduğu
yukarıdaki hesapta görüldü: bölünmez blok sayısı arttıkça dengeleme bozulur. Kırılma denetimi
seçici kullanılır; her bloğa `avoid` yazmak sütunları kullanılamaz hâle getirir.

## Ayıraç ve Yayılma

İki bildirim daha görsel düzenlemeyi tamamlar.

`column-rule`, sütunların arasına bir çizgi çizer ve yazımı kenarlık kısayoluyla aynıdır:
kalınlık, biçim, renk. Bu çizgi **yer kaplamaz**; sütun aralığının ortasına, ölçüye
katılmadan çizilir. Aralık çizgiden darsa çizgi sütunların üzerine taşar.

`column-span: all`, bir ögenin bütün sütunları kesmesini sağlar. Böyle bir öge akışı ikiye
böler: kendisinden önceki içerik sütunlara dağıtılır, öge tam genişlikte yerleşir, sonraki
içerik yeniden sütunlara dağıtılır. İki grup ayrı ayrı dengelenir. Bir bölüm başlığını
sütunların üzerinde tutmanın yolu budur.

```css
/* duzen.css — 6. adım: istasyon yöntem notları */
.istasyon-notlari {
  columns: 18rem 3;
  column-gap: var(--aralik-1);
  column-rule: 1px solid var(--cizgi);
}

.istasyon-notlari > h3 {
  column-span: all;
  margin-block-start: 0;
}

.istasyon-notlari figure,
.istasyon-notlari table,
.istasyon-notlari li {
  break-inside: avoid;
}

.istasyon-notlari p {
  orphans: 3;
  widows: 3;
}
```

Bildirim kümesi küçük ama her satırın gerekçesi ayrıdır. `columns` sütun sayısını iki koşulun
küçüğüne bağlar. `column-rule` ayrımı görünür kılar ve ölçüye karışmaz. `column-span: all`
başlığı sütunların üzerinde tutar. `break-inside: avoid` yalnız bölünmesi anlamı bozan üç öge
türüne yazılmıştır — paragraflara yazılmamıştır, çünkü paragrafın bölünmesi normaldir.
`orphans` ve `widows` değerleri varsayılanın bir üstüne çekilerek tek ve iki satırlık
artıklar engellenmiştir.

## Nerede Uygun Değil

Çok sütunlu düzenin bir sınırı vardır ve okuma yönünden gelir. Sütunlar dikey doldurulur:
okuyucu birinci sütunun altına iner, sonra ikinci sütunun başına döner. Bu, kâğıtta doğaldır
çünkü sütunun tamamı aynı anda görünür. Ekranda sütun, görüntü alanından uzunsa okuyucu
aşağı kaydırır, sonra yukarı geri kaydırır ve bir sonraki sütuna geçer.

Kural şudur: bir sütunun yüksekliği görüntü alanını aşıyorsa çok sütunlu düzen okumayı
zorlaştırır. Kısa metinlerde — bir yöntem notu, bir tanım listesi, bir kaynakça — kazanç
gerçektir; uzun bir makalede kayıptır.

İkinci sınır, sütunların belgede karşılığı olmamasıdır. Ekran okuyucu ve klavye odağı belge
sırasını izler; sütunlar bu sırayı değiştirmediği için ek bir erişilebilirlik sorunu doğmaz.
Ancak sütun içindeki bir bağlantıya odaklanıldığında sayfanın nereye kaydırılacağı, sütun
yüksekliğine bağlı olarak beklenmedik olabilir.

## Özet

- Çok sütunlu düzen kutuyu değil akışı böler; tek bir paragraf iki sütuna parçalanabilir,
  sütunlar ise belgede öge karşılığı olmayan yapılardır.
- Kullanılan sütun sayısı, yazılan `column-count` değeri ile kapsayıcıya sığan sütun
  sayısının küçüğüdür; kullanılan genişlik kalan alanın bu sayıya bölünmesiyle bulunur.
- `column-width` bir hedef değil alt sınırdır: kullanılan genişlik bu değerin üstüne, tek
  sütunlu durumda iki katından fazlasına çıkabilir.
- `column-fill: balance` sütun yüksekliklerini eşitlemeye çalışır; bölünmez bloklar
  dengelemeyi bozar ve son sütunun boş kalmasına yol açar.
- `column-span: all` akışı ikiye böler ve iki bölüm ayrı dengelenir; `column-rule` sütun
  aralığına yer kaplamadan çizilir.
- Bir sütunun yüksekliği görüntü alanını aşıyorsa okuyucu aşağı inip yukarı dönmek zorunda
  kalır; bu, düzenin uygun olmadığının ölçütüdür.

## Sonraki Adım

Bu ders bir ölçütü sessizce kullandı: sütun genişliği kapsayıcıya sığmadığında sütun sayısı
düşürüldü. Karar, bir ekran genişliği listesine değil, içeriğin okunabilir kaldığı en dar
ölçüye dayanıyordu. Aynı akıl yürütme sayfanın tamamı için geçerlidir. Sonraki konu bu
akıl yürütmeyi düzenin bütününe taşır: bir düzenin hangi genişlikte değişmesi gerektiği
hangi ölçüyle bulunur ve bu karar neden ekran listelerinden değil içerikten türetilir?
