Ders 12 / 26
Akış Düzeni
Normal akışın blok ve satır içi yerleştirme kuralları; dış boşluk çökmesinin üç durumu ve çökmenin sayısal sonucu.
İçindekiler
Önceki ders kutuların türünü tanımladı: blok kutu kendi satırını kaplar, satır içi kutu metnin akışında kalır. “Akış” sözcüğü orada tanımsız kullanıldı. Bu ders onu tanımlar.
Normal akış (normal flow), hiçbir konumlandırma bildirimi yazılmadığında kutuların yerleştirilme biçimidir. Bütün yerleşim modellerinin varsayılanı budur ve bir kutunun akıştan çıkarılması ayrıca bildirilmesi gereken bir şeydir. Akışın kurallarını bilmek, çoğu yerleşim sorununun sanılandan az bildirimle çözülmesini sağlar.
Blok Yerleştirme
Bir blok kutu içindeki blok kutular, blok ekseninde arka arkaya yığılır. Kurallar üç maddedir:
- Her blok kutunun satır içi eksendeki ölçüsü, bildirilmediğinde kapsayan kutunun içerik kutusunu doldurur.
- Blok eksendeki ölçüsü, bildirilmediğinde içeriğine göre belirlenir.
- Bir sonraki kutu, bir öncekinin dış boşluk kenarından sonra başlar.
Üçüncü kural eksik yazılmıştır. İki kutunun karşılıklı dış boşlukları toplanmaz; çöker.
Dış Boşluk Çökmesi
Çökme (margin collapsing), blok eksendeki iki dış boşluğun tek bir boşluğa indirgenmesidir. Kural şudur:
- Her iki değer de pozitifse sonuç en büyüğüdür.
- Her iki değer de negatifse sonuç en küçüğüdür (mutlak değeri en büyük olanı).
- Biri pozitif biri negatifse sonuç ikisinin toplamıdır.
Aşağıdaki program bu kuralı uygular ve akışta üç paragrafın yerini hesaplar.
// cokme.mjs — dis bosluk cokmesi kurallarini uygular // kural: cokup birlesen bosluklarin sonucu // hepsi pozitifse en buyugu // hepsi negatifse en kucugu (mutlak degeri en buyugu) // karisiksa en buyuk pozitif + en kucuk negatif function cok(...bosluklar) { const p = bosluklar.filter((b) => b > 0); const n = bosluklar.filter((b) => b < 0); const enP = p.length ? Math.max(...p) : 0; const enN = n.length ? Math.min(...n) : 0; return enP + enN; } console.log("--- iki kardes arasi ---"); const durumlar = [[32, 16], [16, 32], [24, 24], [32, -8], [-8, -16], [0, 24]]; for (const [alt, ust] of durumlar) { console.log(`alt=${String(alt).padStart(3)} ust=${String(ust).padStart(3)} -> aralik=${String(cok(alt, ust)).padStart(3)} (toplasaydi ${alt + ust})`); } console.log("\n--- ust oge ile ilk cocuk (kenarlik/dolgu yoksa disari tasar) ---"); function ustCocuk({ ustMargin, cocukMargin, ustPadding, ustBorder }) { if (ustPadding > 0 || ustBorder > 0) { return { disari: ustMargin, iceride: cocukMargin, cokme: false }; } return { disari: cok(ustMargin, cocukMargin), iceride: 0, cokme: true }; } for (const d of [ { ustMargin: 16, cocukMargin: 32, ustPadding: 0, ustBorder: 0 }, { ustMargin: 16, cocukMargin: 32, ustPadding: 1, ustBorder: 0 }, { ustMargin: 16, cocukMargin: 32, ustPadding: 0, ustBorder: 1 }, ]) { const r = ustCocuk(d); console.log(`ustPadding=${d.ustPadding} ustBorder=${d.ustBorder} -> disari=${r.disari} iceride=${r.iceride} cokme=${r.cokme}`); } console.log("\n--- bos kutu kendi icinde coker ---"); console.log(`ust=20 alt=12, icerik yok -> kutunun toplam dikey yeri = ${cok(20, 12)}`); console.log("\n--- akista uc paragraf ---"); const p = [ { ad: "p1", mUst: 0, yukseklik: 24, mAlt: 16 }, { ad: "p2", mUst: 16, yukseklik: 48, mAlt: 16 }, { ad: "p3", mUst: 32, yukseklik: 24, mAlt: 0 }, ]; let y = 0; for (let i = 0; i < p.length; i++) { const aralik = i === 0 ? p[i].mUst : cok(p[i - 1].mAlt, p[i].mUst); y += aralik; console.log(`${p[i].ad}: aralik=${String(aralik).padStart(2)} ust=${String(y).padStart(3)} alt=${y + p[i].yukseklik}`); y += p[i].yukseklik; } console.log(`toplam yukseklik: ${y}`);
--- iki kardes arasi --- alt= 32 ust= 16 -> aralik= 32 (toplasaydi 48) alt= 16 ust= 32 -> aralik= 32 (toplasaydi 48) alt= 24 ust= 24 -> aralik= 24 (toplasaydi 48) alt= 32 ust= -8 -> aralik= 24 (toplasaydi 24) alt= -8 ust=-16 -> aralik=-16 (toplasaydi -24) alt= 0 ust= 24 -> aralik= 24 (toplasaydi 24) --- ust oge ile ilk cocuk (kenarlik/dolgu yoksa disari tasar) --- ustPadding=0 ustBorder=0 -> disari=32 iceride=0 cokme=true ustPadding=1 ustBorder=0 -> disari=16 iceride=32 cokme=false ustPadding=0 ustBorder=1 -> disari=16 iceride=32 cokme=false --- bos kutu kendi icinde coker --- ust=20 alt=12, icerik yok -> kutunun toplam dikey yeri = 20 --- akista uc paragraf --- p1: aralik= 0 ust= 0 alt=24 p2: aralik=16 ust= 40 alt=88 p3: aralik=32 ust=120 alt=144 toplam yukseklik: 144
İlk blokta üçüncü satır kuralı en açık gösteriyor: iki komşu 24’er birim boşluk verdiğinde aradaki mesafe 48 değil 24 oluyor. Toplansaydı, her paragrafa aynı boşluğu vermek paragraflar arasını iki katına çıkarırdı.
Çökmenin gerekçesi budur: bir metin belgesinde her bloka “benden önce ve sonra bu kadar boşluk olsun” denir ve komşu istekler birbirini iki katına çıkarmamalıdır. Çökme kuralı, her bloğun kendi isteğini bağımsız bildirmesini ve sonucun ikisinden büyüğü olmasını sağlar.
Çökmenin Üç Durumu
Çökme yalnızca kardeşler arasında olmaz.
Kardeşler arasında. Bir kutunun alt dış boşluğu ile sonrakinin üst dış boşluğu çöker. Çıktının ilk bloğu bunu gösterir.
Üst öge ile ilk/son çocuk arasında. Bir kutunun üst dış boşluğu ile ilk çocuğunun üst dış boşluğu çöker ve dışarı taşar. Çıktının ikinci bloğu bunu veriyor: 16 ve 32 birimlik boşluklar birleşip 32 olarak kutunun dışına çıktı, içeride sıfır kaldı. Alt tarafta aynı şey son çocukla olur.
Bu davranış çoğu zaman şaşırtıcıdır: bir bölüme arka plan verildiğinde çocuğun üst boşluğu renkli alanın içinde değil, dışında görünür. Aynı bloğun sonraki iki satırı çözümü de gösteriyor: üst ögeye bir birimlik iç boşluk ya da kenarlık eklendiğinde çökme durur ve boşluk içeride kalır.
Boş kutu kendi içinde çöker. İçeriği, yüksekliği, iç boşluğu ve kenarlığı olmayan bir kutunun kendi üst ve alt dış boşlukları birbiriyle çöker. Çıktının üçüncü bloğunda 20 ve 12 birimlik boşluklar tek bir 20 birime indi.
Çökme Ne Zaman Olmaz
Çökme evrensel değildir. Şu durumlarda olmaz:
- Satır içi eksende hiç olmaz. Yan yana duran iki kutunun yatay dış boşlukları her zaman toplanır. Çökme yalnızca blok eksende tanımlıdır.
- Kutular arasında kenarlık ya da iç boşluk varsa.
- Kutu akıştan çıkarılmışsa: mutlak konumlandırılmış ya da kaydırılmış kutular çökmeye katılmaz.
- Kutu bir bağımsız akış kökü ise:
display: flow-root,overflowdeğerivisibledışında olan kutular ve esnek kutu ya da ızgara düzeni içindeki çocuklar çökmez.
Son madde pratikte en çok kullanılanıdır. Bir düzen modelinde gap ile verilen aralıklar
çökmez; bildirilen değer olduğu gibi uygulanır. Bu, aralıkları öngörülebilir kılar ve bir
sonraki kursta düzen sistemlerinin çökme sorununu neden ortadan kaldırdığını açıklar.
Satır İçi Yerleştirme
Satır içi kutular blok eksende yığılmaz; satır kutularına (line box) yerleştirilir. Bir satır kutusu, kapsayan bloğun satır içi eksenini doldurur ve içine sığdığı kadar satır içi kutu alır. Sığmayan bir sonraki satır kutusuna geçer.
Satır kutusunun yüksekliği, içindeki kutuların yüksekliklerinden ve line-height
değerlerinden hesaplanır. Bu hesabın ayrıntısı tipografi dersinde ele alınacak; burada
önemli olan iki sonucudur.
Birincisi, bir satır içi kutuya dikey dış boşluk verilmesinin satır kutusunu büyütmemesidir — önceki derste çizelgede görülen davranışın sebebi budur.
İkincisi, satır kutuları arasındaki mesafeyi belirleyen şeyin dış boşluk değil,
line-height olmasıdır. Paragraf içi satır aralığı bu yüzden dış boşlukla ayarlanamaz.
Akışın Pratik Sonucu
Normal akışın kuralları, bir belgenin hiçbir düzen bildirimi olmadan okunabilir olmasını sağlar. Bloklar yığılır, metin satırlara bölünür, kutular kapsayanlarını doldurur. Web’in Temelleri ve HTML kursunda yazılan istasyon belgesi, tek bir CSS satırı olmadan da baştan sona okunabilirdi.
Buradan çıkan yazım disiplini şudur: bir yerleşim sorunu önce akışın kurallarıyla çözülmeye çalışılır. Kutuları akıştan çıkaran bildirimler — kaydırma ve konumlandırma — akışın veremediği bir şey gerektiğinde yazılır, akış bilinmediği için değil.
/* istasyon.css — 11. adım: akışa dayalı aralıklar */ main > * + * { margin-block-start: 1rem; } main > section { margin-block-start: 2.5rem; } .kunye > :first-child { margin-block-start: 0; }
İlk kural, ana içerikteki her kardeş çifti arasına bir aralık koyar ve ilk ögeye dokunmaz — kardeş birleştiricisinin doğal sonucu. İkinci kural bölümler arasını genişletir ve çökme sayesinde birinciyle toplanmaz: 1rem ve 2.5rem çöker, sonuç 2.5rem olur. Üçüncü kural, künyenin ilk çocuğunun boşluğunun dışarı taşmasını engellemek yerine sıfırlar.
Özet
- Normal akışta blok kutular blok ekseninde yığılır, satır içi kutular satır kutularına yerleştirilir; sığmayan bir sonraki satır kutusuna geçer.
- Blok eksendeki iki komşu dış boşluk toplanmaz, çöker: ikisi de pozitifse en büyüğü, ikisi de negatifse en küçüğü, karışıksa toplamı geçerlidir.
- Çökme üç durumda olur: kardeşler arasında, üst öge ile ilk/son çocuk arasında ve boş bir kutunun kendi içinde. İkincisinde boşluk üst kutunun dışına taşar.
- Çökme satır içi eksende hiç olmaz; araya kenarlık ya da iç boşluk girdiğinde, kutu akıştan çıktığında ya da bağımsız bir akış kökü olduğunda durur.
- Satır kutuları arasındaki mesafe dış boşlukla değil
line-heightile belirlenir; satır içi kutuya verilen dikey dış boşluk satır yüksekliğini değiştirmez.
Sonraki Adım
Akış kutuları tek yönde diziyor: bloklar alt alta, satır içi kutular yan yana. Bir görselin metnin yanında durup metnin çevresinden akmasını istemek bu iki kalıba da uymaz. Sonraki ders bu ihtiyaç için tanımlanmış olan kaydırmayı ve onun getirdiği yükseklik sorununu ele alır.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.