İçeriğe geç
academia.sh

Ders 01 / 23

Esnek Kutu Modeli

Esnek kutu bağlamının kurulması, ana ve çapraz eksenin yön bildiriminden türetilmesi, boş alanın ana eksende dağıtılması ve çapraz eksende hizalama.

İçindekiler

CSS ile Görsel Sunum kursu normal akışın kurallarını kurdu: blok kutular blok ekseninde yığılır, satır içi kutular satır kutularına yerleştirilir. Kutuları yan yana dizmek için o kursta kaydırma ve konumlandırma gösterildi; ikisi de kutuyu akıştan çıkarır ve kapsayanının yüksekliğini hesaplayamaz duruma getirir.

Bu ders, kutuları yan yana dizmek için tanımlanmış olan düzen modelini (layout model) ele alır. Esnek kutu, akıştan çıkarma yoluna gitmez; kapsayanın içinde yeni bir yerleşim kuralı kurar ve boş alanı çocuklar arasında bölüştürür.

Esnek Kutu Bağlamı

Bir kutuya display: flex bildirildiğinde kutunun kendisi akışta blok kutu olarak kalır; değişen şey çocuklarının yerleştirilme kuralıdır. Bu kutu artık bir esnek kapsayıcıdır (flex container) ve doğrudan çocukları esnek ögelerdir (flex item).

Üç sonuç hemen doğar:

  1. Çocukların display değeri bloklaştırılır. Bir span çocuk, satır içi kutu olmaktan çıkar ve esnek öge olur; genişlik ve dikey dış boşluk alabilir.
  2. Kutular arasındaki dış boşluk çökmez. Akış Düzeni dersindeki çökme kuralı yalnızca blok düzeninde tanımlıdır; esnek kutu bağlamında iki komşu boşluk toplanır.
  3. Etiketle sarılmamış metin de bir esnek öge olur. Ögeye adı olmadığı için anonim kutu denir ve seçiciyle hedeflenemez.

Üçüncü madde, düzenin bozulduğu durumlarda ilk bakılacak yerlerden biridir: kapsayıcının içindeki bir satır sonu ve girinti boşluk üretmez, ama gerçek bir metin parçası öge sayılır.

İki Eksen

Esnek kutu tek eksenli bir modeldir. Ögeler tek bir doğrultuda dizilir ve boş alan o doğrultuda bölüştürülür. Bu doğrultuya ana eksen (main axis), ona dik olana çapraz eksen (cross axis) denir.

Ana ekseni flex-direction belirler:

Bildirim Ana eksen Ana başlangıç Çapraz eksen
row satır içi eksen satır içi başlangıç blok eksen
row-reverse satır içi eksen satır içi bitiş blok eksen
column blok eksen blok başlangıç satır içi eksen
column-reverse blok eksen blok bitiş satır içi eksen

Tablodaki adlandırma bilinçli olarak “yatay” ve “dikey” demiyor. Satır içi eksen, metnin aktığı doğrultudur ve belgenin yazma yönüne bağlıdır; sağdan sola yazılan bir belgede row yönündeki ilk öge sağda başlar. Esnek kutu bildirimleri bu doğrultuları soyut olarak adlandırdığı için aynı biçem dosyası yön değiştiğinde de doğru çalışır.

Ana eksenin iki ucu ana başlangıç ve ana bitiş, çapraz eksenin iki ucu çapraz başlangıç ve çapraz bitiş olarak anılır. Hizalama bildirimlerinin tamamı bu dört uca göre okunur.

Boş Alanın Dağıtımı

Ögelerin ana eksendeki ölçüleri toplandığında kapsayıcıdan küçük kalıyorsa geriye boş alan kalır. justify-content bildirimi bu alanın nereye konacağını söyler.

Aşağıdaki program, üç ögeli bir satırda altı dağıtım değerini hesaplar. Kapsayıcı 720 birim, aralar 16 birimdir.

// eksen.mjs — bir esnek satirda ana eksen dagitimi ve capraz eksen hizalamasi
const KAPSAYICI = 720;
const ARALIK = 16;
const kutular = [
  { ad: "arama", ana: 180, capraz: 40 },
  { ad: "tarih", ana: 140, capraz: 32 },
  { ad: "durum", ana: 120, capraz: 56 },
];

const toplamAna = kutular.reduce((t, k) => t + k.ana, 0);
const araToplam = ARALIK * (kutular.length - 1);
const bosAlan = KAPSAYICI - toplamAna - araToplam;
console.log(`kapsayici=${KAPSAYICI}  kutular=${toplamAna}  aralik=${araToplam}  bos alan=${bosAlan}`);

// ana eksende dagitim: her deger, bos alani farkli yerlere koyar
function anaEksen(deger) {
  const n = kutular.length;
  let bas = 0, ek = 0;
  if (deger === "flex-start") { bas = 0; ek = 0; }
  if (deger === "flex-end") { bas = bosAlan; ek = 0; }
  if (deger === "center") { bas = bosAlan / 2; ek = 0; }
  if (deger === "space-between") { bas = 0; ek = bosAlan / (n - 1); }
  if (deger === "space-around") { ek = bosAlan / n; bas = ek / 2; }
  if (deger === "space-evenly") { ek = bosAlan / (n + 1); bas = ek; }
  const yerler = [];
  let x = bas;
  for (const k of kutular) {
    yerler.push({ ad: k.ad, bas: x, son: x + k.ana });
    x += k.ana + ARALIK + ek;
  }
  return yerler;
}

console.log("\n--- ana eksen (justify-content) ---");
for (const d of ["flex-start", "flex-end", "center", "space-between", "space-around", "space-evenly"]) {
  const y = anaEksen(d);
  const metin = y.map((k) => `${k.ad} ${k.bas.toFixed(1)}..${k.son.toFixed(1)}`).join("  ");
  console.log(d.padEnd(14), metin);
}

// capraz eksende hizalama: satir yuksekligi en uzun kutuyla belirlenir
const SATIR = Math.max(...kutular.map((k) => k.capraz));
console.log(`\n--- capraz eksen (align-items), satir yuksekligi=${SATIR} ---`);
for (const d of ["flex-start", "flex-end", "center", "stretch"]) {
  const y = kutular.map((k) => {
    if (d === "stretch") return `${k.ad} 0..${SATIR}`;
    const bas = d === "flex-start" ? 0 : d === "flex-end" ? SATIR - k.capraz : (SATIR - k.capraz) / 2;
    return `${k.ad} ${bas.toFixed(1)}..${(bas + k.capraz).toFixed(1)}`;
  });
  console.log(d.padEnd(12), y.join("  "));
}
kapsayici=720  kutular=440  aralik=32  bos alan=248

--- ana eksen (justify-content) ---
flex-start     arama 0.0..180.0  tarih 196.0..336.0  durum 352.0..472.0
flex-end       arama 248.0..428.0  tarih 444.0..584.0  durum 600.0..720.0
center         arama 124.0..304.0  tarih 320.0..460.0  durum 476.0..596.0
space-between  arama 0.0..180.0  tarih 320.0..460.0  durum 600.0..720.0
space-around   arama 41.3..221.3  tarih 320.0..460.0  durum 558.7..678.7
space-evenly   arama 62.0..242.0  tarih 320.0..460.0  durum 538.0..658.0

--- capraz eksen (align-items), satir yuksekligi=56 ---
flex-start   arama 0.0..40.0  tarih 0.0..32.0  durum 0.0..56.0
flex-end     arama 16.0..56.0  tarih 24.0..56.0  durum 0.0..56.0
center       arama 8.0..48.0  tarih 12.0..44.0  durum 0.0..56.0
stretch      arama 0..56  tarih 0..56  durum 0..56

Boş alan 248 birimdir ve altı satır bu 248 birimi altı ayrı biçimde yerleştirir.

flex-start, flex-end ve center boş alanı tek parça bırakır; yalnızca yerini değiştirir. Kalan üçü boş alanı böler ve payların nereye düştüğü ayrışır:

  • space-between iki uca hiç pay ayırmaz, alanı ögeler arasına eşit böler: 248/2=124248 / 2 = 124 birim ek boşluk.
  • space-around her ögeye kendi payını verir, pay ögenin iki yanına yarımlanır: 248/382,67248 / 3 \approx 82{,}67; kenarlarda yarım pay 41,33\approx 41{,}33, aralarda iki yarım pay bitişir ve 82,67\approx 82{,}67 olur.
  • space-evenly bütün boşlukları eşitler: 248/4=62248 / 4 = 62 birim, kenarda da arada da aynı.

Üç değerin de orta ögeyi aynı yere koyması rastlantı değil: dağıtım simetriktir ve üç öge ortasında bir öge varsa o öge merkezde kalır. Ayrım kenarlardadır.

Sıra bir uyarı gerektirir: flex-start ve flex-end yerine start/end yazımı da tanımlıdır ve ikisi çoğu durumda aynı sonucu verir. Aynı biçem dosyası içinde tek bir yazım seçilir; bu kurs boyunca flex- önekli biçim kullanılacaktır.

Çapraz Eksende Hizalama

Çapraz eksende dağıtacak boş alan yoktur; her öge kendi başına hizalanır. align-items kapsayıcıda tüm ögeler için, align-self tek bir ögede yazılır ve kapsayıcıdaki değeri ezer.

Çıktının ikinci bloğu dört değeri gösteriyor. Satır yüksekliği en uzun ögeyle belirleniyor (56 birim) ve diğer ikisi bu yüksekliğin içinde konumlanıyor. flex-start üste, flex-end alta, center ortaya çeker.

Dördüncü değer olan stretch diğerlerinden farklıdır ve varsayılandır: öge, çapraz eksendeki ölçüsü bildirilmemişse satırın tamamına gerdirilir. Çıktıda üç ögenin de 0..56 olması budur. Ögeye çapraz eksende bir ölçü bildirilirse gerdirme uygulanmaz; bildirilen ölçü korunur ve öge çapraz başlangıca hizalanır.

Gerdirmenin pratik değeri, yan yana duran kutuların eşit yükseklikte olmasıdır. Farklı uzunlukta metin taşıyan üç kart, hiçbir yükseklik bildirilmeden aynı boyda görünür; bu, akış düzeninde ancak sabit yükseklik yazarak elde edilebilirdi.

Beşinci bir değer olan baseline, ögeleri kendi ilk metin satırlarının taban çizgisine göre hizalar. Farklı yazı boyutlarındaki başlıkları yan yana koyarken üst kenar hizası yerine yazı hizası isteniyorsa bu değer kullanılır.

Aralık ve Otomatik Boşluk

Ögeler arasındaki mesafe iki yolla verilebilir. Birincisi ögelere dış boşluk yazmaktır ve ilk ile son ögede istenmeyen kenar boşluğu üretir. İkincisi kapsayıcıya aralık (gap) bildirmektir: gap yalnızca ögelerin arasına uygulanır, kenarlara dokunmaz.

Yukarıdaki hesapta ara toplamının 16×2=3216 \times 2 = 32 olması bundandır: üç öge, iki ara.

İkinci bir araç, ögeye margin değeri olarak auto yazmaktır. Otomatik dış boşluk, ana eksendeki boş alanın tamamını yutar ve justify-content uygulanmadan önce çalışır. Bir gezinme çubuğunda son ögeyi karşı uca itmenin en doğrudan yolu budur:

/* duzen.css — 1. adım: gezinme çubuğu tek eksende */
.gezinme > ul {
  display: flex;
  gap: 1.5rem;
  align-items: center;
}

.gezinme .istasyon-durumu {
  margin-inline-start: auto;
}

margin-inline-start: auto bildirimi, durum rozetinden önceki bütün boş alanı o ögeye verir ve rozet satırın sonuna yapışır. Aynı sonuç justify-content: space-between ile de elde edilebilir, ama o bildirim bütün aralara pay dağıtır; burada istenen tek bir noktada kırılmadır.

Bu dosya, CSS ile Görsel Sunum kursunda kurulan istasyon.css dosyasının yanına konur. Görsel bildirimler orada kalır, düzen bildirimleri burada toplanır; ayrımın gerekçesi kursun son konusunda ele alınacaktır.

Satır Kırma

Varsayılan olarak esnek ögeler tek satırda kalır; toplam ölçü kapsayıcıyı aşsa bile yeni satıra geçmez, ögeler daralır. flex-wrap: wrap bildirimi bu davranışı değiştirir ve sığmayan ögeler yeni bir satıra iner.

Satır kırma açıldığında üçüncü bir hizalama bildirimi anlam kazanır: align-content, satırların çapraz eksende nasıl dağıtılacağını söyler ve değer kümesi justify-content ile aynıdır. Tek satır varsa bu bildirimin etkisi yoktur.

Buradaki ayrım sık karıştırılır ve tek cümleyle özetlenebilir: align-items bir satırın içindeki ögeleri, align-content kapsayıcının içindeki satırları hizalar.

Özet

  • display: flex kutunun kendisini değil çocuklarının yerleştirilme kuralını değiştirir; çocuklar bloklaşır, dış boşlukları çökmez ve sarmalanmamış metin anonim öge olur.
  • Esnek kutu tek eksenlidir: flex-direction ana ekseni belirler, çapraz eksen ona diktir ve iki eksen de yazma yönüne göre soyut adlandırılır.
  • justify-content ana eksendeki boş alanı yerleştirir; flex-start, flex-end ve center alanı tek parça bırakır, space-between, space-around ve space-evenly onu farklı paylaşım kurallarıyla böler.
  • Çapraz eksende varsayılan stretch ögeleri satır yüksekliğine gerdirir; hizalama değerleri yalnızca çapraz ölçü bildirildiğinde ya da gerdirme kapatıldığında görünür.
  • gap yalnızca aralara uygulanır, margin: auto ana eksendeki boş alanın tamamını yutar ve dağıtım bildiriminden önce çalışır.

Sonraki Adım

Bu dersin hesabında ögelerin ana eksendeki ölçüleri sabit alındı ve boş alan hep artı çıktı. Gerçek bir düzende ölçüler içerikten gelir ve kapsayıcı daraldığında boş alan eksiye düşer. O durumda hangi öge ne kadar daralır, fazla alan hangi ögeye gider? Sonraki ders bu paylaşımı yöneten üç bildirimi ve aritmetiğini ele alır.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat