Skip to content

Bölüm 9 / 20

Flexbox

Tek boyutlu yerleşim.

13 dakikalık okuma

Flexbox'tan önce yerleşim, aslında yerleşim için tasarlanmamış araçlarla yapılırdı: kayan ögeler (float), satır içi bloklar, negatif kenar boşlukları ve tablolar. Hepsinin ortak sorunu, dikey ortalamak ya da kalan boşluğu paylaştırmak gibi basit isteklerin hileye dönüşmesiydi. Flexbox bu işi doğrudan yapar: bir eksende ögeleri dizer, kalan boşluğu dağıtır, sığmayanı daraltır. Bu ders yalnız özellik listesi değil; hangi özelliğin hangi eksende çalıştığını, flex: 1 yazınca ne olduğunu ve Flexbox'ın en çok zaman kaybettiren üç tuzağını anlatıyor.

01Ne öğreneceksin

  • Ana eksen / çapraz eksen ayrımı — Flexbox'ın tamamı bu ikisine dayanır
  • Kapsayıcı özellikleri: flex-direction, flex-wrap, justify-content, align-items, align-content, gap
  • Öge özellikleri: flex-grow, flex-shrink, flex-basis, align-self, order
  • flex: 1 gerçekte ne demek; flex-basis ile width farkı
  • Tuzak 1: min-width: auto yüzünden daralmayan öge ve taşan metin
  • Tuzak 2: order DOM sırasını değiştirmez — klavye ve ekran okuyucu sırası bozulur
  • Tuzak 3: align-items ile align-content karışıklığı
  • margin: auto ile boşluk yutma; satır içi boşluk sorununun bitmesi
  • Gerçek kalıplar: üst bar, eşit yükseklikli kartlar, ekrana yapışan altbilgi
  • Flexbox mı Grid mi — karar ölçütü

02Tek boyut fikri ve iki eksen

Bir ögeye display: flex verdiğin anda o öge flex kapsayıcısı, doğrudan çocukları flex ögesi olur. Kapsayıcı çocukları tek bir eksende dizer. "Tek boyutlu" olması budur: Flexbox ya bir satırla ya bir sütunla ilgilenir; satırlar arası hizalamayı (yani ızgarayı) Grid yapar.

.kapsayici { display: flex; }        /* blok düzeyinde kapsayıcı */
.kapsayici { display: inline-flex; } /* metin akışında duran kapsayıcı */

Her şey iki eksene göre tanımlanır:

flex-directionAna eksenÇapraz eksen
row (varsayılan)Yatay →Dikey ↓
row-reverseYatay ←Dikey ↓
columnDikey ↓Yatay →
column-reverseDikey ↑Yatay →

Ezberlenecek tek kural: justify-content her zaman ana eksende, align-items her zaman çapraz eksende çalışır. Yani flex-direction: column yazdığın anda ikisinin yönü yer değiştirir — "neden ortalanmıyor" sorularının çoğunun cevabı budur.

/* Yatay dizilim: yatayda ortala, dikeyde ortala */
.a { display: flex; justify-content: center; align-items: center; }

/* Dikey dizilim: AYNI kod, artık justify DİKEYDE, align YATAYDA çalışır */
.b { display: flex; flex-direction: column; justify-content: center; align-items: center; }

Flexbox'ın hemen fark edilen bir yan faydası daha var: 2. derste gördüğün satır içi ögeler arasındaki gizemli boşluk (kaynak kodundaki satır sonunun görünür bir boşluğa dönüşmesi) flex kapsayıcısında ortadan kalkar. Flex ögeleri arasındaki mesafe yalnız gap ve kenar boşluklarıyla belirlenir; işaretlemedeki girintiler etkisizdir. Aynı şekilde flex çocuklarında kenar boşluğu çökmesi de olmaz (8. ders).

03Kapsayıcı özellikleri

.kapsayici {
  display: flex;
  flex-direction: row;          /* ana ekseni seç */
  flex-wrap: wrap;              /* sığmayanlar alt satıra geçsin */
  gap: 1rem;                    /* ögeler arası boşluk — satır ve sütun */
  gap: 1rem 2rem;               /* satır arası | sütun arası */

  justify-content: flex-start;  /* ANA eksende dağıtım */
  align-items: stretch;         /* ÇAPRAZ eksende hizalama (tek satır) */
  align-content: flex-start;    /* ÇAPRAZ eksende SATIRLARIN dağıtımı (çok satır) */
}
justify-contentNe yapar
flex-start / flex-endBaşa / sona yasla
centerOrtala
space-betweenİlk başta, son sonda; aralar eşit
space-aroundHer ögenin iki yanına eşit pay — kenarlar yarım görünür
space-evenlyKenarlar dâhil tüm boşluklar eşit
align-itemsNe yapar
stretch (varsayılan)Çapraz eksende kapsayıcıyı doldurur — kartların eşit yükseklikte olmasının sebebi budur
flex-start / flex-endÜste / alta yasla
centerOrtala
baselineMetin taban çizgilerini hizala — farklı yazı boyutlarında etiket–değer hizalamak için

align-items ile align-content ayrımı en sık karıştırılan konudur: align-items bir satırın içindeki ögeleri hizalar, align-content ise satırların kendisini dağıtır ve yalnızca flex-wrap: wrap varken ve birden çok satır oluştuğunda etkilidir. Tek satır varsa align-content yazmanın hiçbir etkisi olmaz.

gap, kenar boşluğuyla boşluk vermeye göre çok daha temizdir: son ögeden sonra fazladan boşluk kalmaz, :last-child istisnası yazmana gerek olmaz ve sarma olduğunda satır araları da otomatik ayarlanır.

04Öge özellikleri: flex kısayolu

.oge {
  flex-grow: 0;      /* kalan boşluktan pay al mı? kaç birim? */
  flex-shrink: 1;    /* yer yetmezse daralsın mı? ne oranda? */
  flex-basis: auto;  /* dağıtımdan ÖNCEKİ başlangıç boyutu */

  flex: 0 1 auto;    /* üçünün kısayolu — VARSAYILAN budur */
}

Üç yaygın kısayol ve gerçek karşılıkları:

YazımAçılımıAnlamı
flex: 11 1 0%Kalan boşluğu paylaş, başlangıç boyutunu yok say → eşit genişlikte sütunlar
flex: auto1 1 autoBüyü ve daral, ama içerik boyutundan başla → içeriği çok olan daha geniş olur
flex: none0 0 autoNe büyü ne daral — sabit ögeler (simge, logo)
flex: 0 0 200px—Sabit 200 px genişlik; kenar çubukları için

flex: 1 ile flex: auto farkı mülakat sorusudur ve pratikte görünür: üç kutuya flex: 1 verirsen içeriği ne olursa olsun tam eşit genişlikte olurlar (çünkü flex-basis: 0 ile herkes sıfırdan başlar, kalan boşluk eşit bölünür). flex: auto verirsen uzun metinli kutu daha geniş olur (herkes kendi içerik boyutundan başlar, yalnız kalan boşluk eşit bölünür).

flex-basis ana eksendeki boyutu belirler ve width'i ezer (dikey dizilimde height'ı). İkisini birden yazmak yaygın bir karışıklık kaynağıdır; flex-basis varsa width yalnızca flex-basis: auto olduğunda devreye girer.

/* Klasik üç sütun: kenar çubukları sabit, orta esner */
.duzen      { display: flex; gap: 1rem; }
.yan-menu   { flex: 0 0 240px; }
.icerik     { flex: 1; min-width: 0; }     /* min-width: 0 — aşağıdaki tuzak */
.yan-bilgi  { flex: 0 0 300px; }

05Üç tuzak

Tuzak 1: min-width: auto — daralmayan öge

Flex ögelerinin varsayılan min-width değeri auto'dur, yani içeriklerinden daha dar olamazlar. flex-shrink: 1 yazmış olsan bile bu sınır geçerlidir. Sonuç:

.kutu { flex: 1; }
/* İçinde uzun bir URL, geniş bir tablo ya da <pre> bloğu varsa
   kutu daralmaz — kapsayıcıyı zorlar ve SAYFADA YATAY KAYDIRMA çıkar. */

.kutu { flex: 1; min-width: 0; }        /* çözüm */
.kutu { flex: 1; overflow: hidden; }    /* alternatif (kırpar) */

Bu, Flexbox'ta en çok zaman kaybettiren tek satırdır. Belirtisi hep aynıdır: "yan yana iki kutum var, içine uzun bir şey koyunca düzen bozuluyor." Dikey dizilimde karşılığı min-height: 0'dır ve kaydırılabilir bir liste yaparken aynı biçimde gerekir.

Tuzak 2: order ile görsel sıra

.oge { order: 0; }   /* varsayılan; küçükten büyüğe dizilir, negatif olabilir */

order ögelerin görsel sırasını değiştirir; DOM sırasını değiştirmez. 5. derste "DOM sırası = okuma sırasıdır" demiştik — burası o kuralın kırıldığı yerdir:

  • Klavye hâlâ DOM sırasını izler. Gözle 1-2-3 gördüğün düğmeler arasında Tab ile 3-1-2 sırasıyla gezersin.
  • Ekran okuyucu hâlâ DOM sırasını okur; görsel sırayla anlatılan bir içerik (önce başlık, sonra açıklama) sesli olarak ters gelir.
  • Metin seçme ve kopyalama da DOM sırasına göre çalışır.

Bu WCAG 1.3.2 ("anlamlı sıra") ve 2.4.3 ("odak sırası") ölçütlerini ihlal edebilir. Kural: order ve row-reverse yalnız görsel önemi olmayan, sırası anlam taşımayan durumlarda kullanılır. İçerik sırası önemliyse çözüm işaretlemeyi doğru sırada yazmak ve gerekiyorsa Grid ile yerleştirmektir — Grid'de de aynı tuzak grid-area ile mevcuttur (10. ders).

Tuzak 3: margin: auto boşluğu yutar

Flex kapsayıcısında auto kenar boşluğu kalan tüm boşluğu emer. Bu bir hile değil, tanımlı davranıştır ve justify-content'ten daha esnektir:

/* Üst barda: logo solda, GERİSİ sağda */
.ustbar { display: flex; align-items: center; gap: 1rem; }
.logo   { margin-right: auto; }

/* Bir ögeyi hem yatay hem dikey ortala */
.oge { margin: auto; }

Dikkat: margin: auto boşluğu emdiği için justify-content'in etkisini ortadan kaldırır — dağıtılacak boşluk kalmaz. İkisini birlikte kullanıp "çalışmıyor" demek yaygındır.

06Gerçek kalıplar

/* 1. Üst bar: marka solda, menü sağda, dikey ortalı */
.ustbar { display: flex; align-items: center; gap: 1rem; }
.marka  { margin-right: auto; }

/* 2. Ekrana yapışan altbilgi: içerik azken bile altbilgi en altta */
body    { min-height: 100dvh; display: flex; flex-direction: column; }
main    { flex: 1; }

/* 3. Eşit yükseklikli kartlar + alta yaslı düğme */
.liste  { display: flex; flex-wrap: wrap; gap: 1rem; }
.kart   { flex: 1 1 260px; display: flex; flex-direction: column; }
.kart p { flex: 1; }                 /* metin büyür, düğmeyi aşağı iter */

/* 4. Medya nesnesi: solda simge, sağda esneyen metin */
.medya      { display: flex; gap: .75rem; align-items: flex-start; }
.medya img  { flex: none; width: 48px; }
.medya div  { flex: 1; min-width: 0; }

/* 5. Etiket-değer hizalama: farklı yazı boyutlarında taban çizgisi */
.olcum { display: flex; align-items: baseline; gap: .5rem; }

Üçüncü kalıptaki flex: 1 1 260px özellikle işe yarar: kartlar en az 260 px olmaya çalışır, sığmazsa alt satıra geçer, kalan boşluğu paylaşır. Bu, medya sorgusu yazmadan duyarlı bir kart ızgarası verir — ama son satırdaki kartlar geride kalanları paylaştığı için farklı genişlikte olur. Son satırın da eşit olmasını istiyorsan Flexbox yetmez; Grid gerekir.

Flexbox mı, Grid mi

Flexbox içerikten yerleşime, Grid yerleşimden içeriğe çalışır. Ölçüt: ögelerin boyutunu içerikleri belirlesin ve tek bir eksende dizilsinler istiyorsan Flexbox; satır ve sütun hizalaması gereken, hücre boyutlarını sen belirlediğin bir düzen istiyorsan Grid. Pratik ayrım: üst bar, düğme grubu, etiket-değer satırı, bir kartın iç dizilimi → Flexbox. Sayfa iskeleti, kart ızgarası, form etiket-alan hizalaması, gerçekten iki boyutlu her şey → Grid. İkisi rakip değildir; tipik bir sayfada dış iskelet Grid, iç bileşenler Flexbox olur ve bu en yaygın birleşimdir.

07Mini alıştırma — Flexbox'ı sınırlarına kadar zorla

Yaklaşık 20 dakika · tek HTML dosyası + DevTools flex denetleyicisi

  1. Kur: beş kutulu bir flex kapsayıcısı yaz. DevTools'ta kapsayıcının yanındaki flex rozetine tıklayıp görsel denetleyiciyi aç.
  2. Eksen değişimi: justify-content: center; align-items: center ver; sonra flex-direction: column ekle. Ne değişti, neden?
  3. Dağıtım: space-between, space-around ve space-evenly arasında geçiş yap. Kenarlardaki boşlukları ölç.
  4. Varsayılan stretch: kutuların içine farklı uzunlukta metin koy — yükseklikleri neden eşit? align-items: flex-start yapıp farkı gör.
  5. flex: 1 vs auto: üç kutuya farklı uzunlukta metin koy, sırayla flex: 1 ve flex: auto uygula. Genişlikleri ölç.
  6. Sabit + esnek: flex: 0 0 240px bir kenar çubuğu ve flex: 1 bir içerik alanı yap. Pencereyi daralt — hangisi daraldı?
  7. Tuzak 1: içerik alanına çok uzun bir URL yapıştır. Yatay kaydırma çıktı mı? min-width: 0 ekleyip tekrarla.
  8. Sarma: flex-wrap: wrap ve flex: 1 1 260px ile kart listesi yap. Pencereyi daraltıp kaç sütuna düştüğünü izle. Son satırdaki kartlar diğerleriyle aynı genişlikte mi?
  9. align-content: çok satırlı sarmalı listede align-content: center dene (kapsayıcıya yükseklik vererek). Tek satıra düşürdüğünde etkisi kayboluyor mu?
  10. margin: auto: üst bar kalıbını kur; logoya margin-right: auto ver. Sonra kapsayıcıya justify-content: space-between ekle — bir şey değişti mi?
  11. Tuzak 2: üç düğmeye order: 3, 1, 2 ver. Gözle sırayı doğrula, sonra yalnız klavyeyle Tab'la. Odak hangi sırayla gezdi?
  12. Eşit yükseklikli kart + alta yaslı düğme: 3. kalıbı uygula; bir kartın metnini uzatıp düğmelerin hizada kaldığını doğrula.
  13. Yapışan altbilgi: 2. kalıbı kur ve sayfada tek bir paragrafla test et. Altbilgi ekranın altında mı?
  14. Satır içi boşluk: üç <span>'i alt alta satırlara yazıp normal akışta göster — aralarında boşluk var mı? Kapsayıcıyı flex yapıp tekrar bak.

08Kendini sına

justify-content ile align-items farkı nedir? flex-direction: column olunca ne değişir?

justify-content ana eksende, align-items çapraz eksende hizalar. Ana ekseni flex-direction belirler: row'da ana eksen yatay, çapraz eksen dikeydir; column'da ikisi yer değiştirir — artık justify-content dikeyde, align-items yatayda çalışır. Bu yüzden aynı kodu column'a çevirdiğinde "ortalama bozuldu" hissi olur; bozulan bir şey yoktur, eksenler dönmüştür. Üçüncü bir özellik daha vardır ve karıştırılır: align-content tek tek ögeleri değil satırların kendisini çapraz eksende dağıtır ve yalnızca flex-wrap: wrap ile birden çok satır oluştuğunda etkilidir — tek satırda yazmanın hiçbir etkisi olmaz. Son olarak align-items'ın varsayılanı stretch'tir; yan yana kartların içerikleri farklı olduğu hâlde eşit yükseklikte görünmesinin sebebi budur.

flex: 1 ne anlama gelir? flex: auto'dan farkı nedir?

flex, üç özelliğin kısayoludur: flex-grow flex-shrink flex-basis. flex: 1 = 1 1 0% — "büyü, daral ve başlangıç boyutunu sıfır say". Herkes sıfırdan başladığı için kapsayıcının tüm genişliği eşit bölünür; içeriği uzun olan kutu da kısa olan kadar yer kaplar, yani tam eşit sütunlar elde edersin. flex: auto = 1 1 auto — "büyü, daral, ama içerik boyutundan başla". Önce her öge kendi doğal genişliğini alır, yalnız kalan boşluk eşit paylaşılır; sonuçta uzun metinli kutu daha geniş olur. flex: none = 0 0 auto ise ögeyi hiç esnetmez (logo, simge, sabit kenar çubuğu). Bir ayrıntı: flex-basis ana eksende width'i ezer, dolayısıyla ikisini birlikte yazmak karışıklık üretir. Ve dikkat: flex: 1 yazmak ögenin gerçekten daralacağını garanti etmez — varsayılan min-width: auto yüzünden öge içeriğinden dar olamaz; bunun için min-width: 0 gerekir.

Flexbox'ta bir öge flex-shrink: 1 olmasına rağmen daralmıyor. Neden?

Çünkü flex ögelerinin varsayılan min-width değeri auto'dur ve bu, ögenin kendi içeriğinin en küçük boyutundan daha dar olamayacağı anlamına gelir. İçeride kırılamayan uzun bir kelime, bir URL, geniş bir tablo ya da bir <pre> bloğu varsa taban boyut büyük olur ve daralma oradan sonra durur. Belirtisi tipiktir: yan yana iki kutu düzgün çalışırken içine uzun bir şey konduğunda kapsayıcı taşar ve sayfada yatay kaydırma çubuğu çıkar. Çözüm daraması gereken ögeye min-width: 0 yazmaktır (dikey dizilimde min-height: 0); alternatif olarak overflow: hidden ya da auto da taban boyutu sıfırlar ama içeriği kırpar ya da kendi kaydırma bağlamını açar. Metnin kendisi taşıyorsa ayrıca overflow-wrap: break-word eklenir. Bu, Flexbox'ta en çok zaman kaybettiren tek satırdır ve Grid'de de aynı davranış (minmax(0, 1fr) ihtiyacı) olarak karşına çıkar.

order özelliğini kullanmanın sakıncası nedir?

order yalnızca görsel sırayı değiştirir; DOM sırasına dokunmaz. Buna bağlı olan her şey eski sırada kalır: klavye odak sırası (gözle 1-2-3 gördüğün düğmeler arasında Tab ile başka bir sırayla gezersin), ekran okuyucu okuma sırası, metin seçme ve kopyalama sırası. Bu, WCAG 1.3.2 ("anlamlı sıra") ve 2.4.3 ("odak sırası") ölçütlerini ihlal edebilir — özellikle bir formda alanların ya da bir gezinmede bağlantıların sırası değiştirildiğinde kullanıcı ciddi biçimde kaybolur. Aynı sakınca row-reverse/column-reverse ve Grid'de grid-area ile yerleştirme için de geçerlidir. Kural: sırası anlam taşıyan içerikte kullanma; doğru çözüm işaretlemeyi baştan doğru sırada yazmak, gerekiyorsa yerleşimi Grid ile kurmaktır. order'ın meşru kullanımı, sırası önemsiz görsel ögelerde ya da dar ekranda tamamen dekoratif bir bloğu öne/arkaya almakta kalır — ve o durumda bile klavye turuyla doğrulanmalıdır.

09Sınav köşesi

Yazılıda nasıl sorulur

(1) Flexbox nedir, hangi problemi çözer? (2) Ana eksen ve çapraz eksen kavramları. (3) justify-content değerlerini sayınız. (4) align-items ile align-content farkı. (5) flex-grow, flex-shrink, flex-basis ne yapar; flex: 1 neye eşittir? (6) flex-wrap ne işe yarar? (7) Bir ögeyi yatay ve dikey ortalamanın yolları. (8) order özelliği ve sakıncası. (9) Flexbox ile Grid farkı, hangisi ne zaman? (10) gap ile margin ile boşluk vermenin farkı. (11) Uygulamalı: "üstte logo solda menü sağda bir bar yapınız."

Sözlüde nasıl anlatılır — 2 dakikalık taslak

Düzen: (1) Tanım — "Flexbox tek boyutlu yerleşim modelidir: ögeleri bir eksende dizer, kalan boşluğu dağıtır, sığmayanı daraltır. Ondan önce bu işler float ve negatif kenar boşluğu hileleriyle yapılıyordu." (2) Model — "her şey ana eksen ve çapraz eksene göre tanımlıdır; justify-content ana eksende, align-items çapraz eksende çalışır ve column yazdığın anda ikisi yer değiştirir." (3) Kısayol — "flex: 1 aslında 1 1 0%'tir; eşit sütunlar verir. flex: auto içerik boyutundan başladığı için eşit vermez — bu ikisini karıştırmak yaygın bir hatadır." (4) Kıdem vuruşu — "flex ögelerinin varsayılan min-width değeri auto'dur; içinde uzun bir URL ya da tablo olan kutu daralmaz ve sayfa yatay kayar. Bunu min-width: 0 ile çözerim; bu Flexbox'ta en çok zaman kaybettiren satırdır." (5) Erişilebilirlik ve karar — "order görsel sırayı değiştirir ama klavye ve ekran okuyucu DOM sırasını izler, bu yüzden sırası anlamlı içerikte kullanmam. Tek eksen ve içeriğe göre boyut varsa Flexbox, satır–sütun hizalaması gerekiyorsa Grid seçerim; tipik sayfada dış iskelet Grid, iç bileşenler Flexbox olur."