Bölüm 10 / 20
Grid
İki boyutlu yerleşim.
13 dakikalık okuma
Flexbox tek eksende çalışır: ya bir satır ya bir sütun. Sayfa
iskeleti, kart ızgarası ve form hizalaması gibi işlerde ise satır ve sütunun aynı anda
hizalanması gerekir. Grid bunun için tasarlanmış ilk gerçek CSS yerleşim sistemidir ve
Flexbox'tan farklı bir yönden çalışır: önce ızgarayı sen tanımlarsın, sonra içerik
hücrelere yerleşir. Bu ders fr biriminden grid-template-areas'a,
auto-fill ile auto-fit arasındaki gerçek farktan medya sorgusu
yazmadan duyarlı ızgara kurmaya kadar Grid'in tamamını ele alıyor.
01Ne öğreneceksin
- Izgara sözlüğü: hat (line), iz (track), hücre, alan
grid-template-columns/rowsvefrbirimi gerçekte nasıl hesaplanırrepeat(),minmax()veauto-fillileauto-fitfarkı- Medya sorgusu yazmadan duyarlı kart ızgarası
- Yerleştirme: hat numarası,
span, hat adları,grid-template-areas - Hizalama altı özelliği ve
place-*kısayolları - Örtük ızgara:
grid-auto-rows,grid-auto-flow,dense - Tuzak:
1fr'nin taban boyutuauto'dur —minmax(0, 1fr)ne zaman gerekir - Aynı hücrede üst üste bindirme (
position: absolute'a alternatif) subgridile iç ögelerin dış ızgaraya hizalanması- Grid ile tablo farkı ve erişilebilirlik sınırı
02Izgara sözlüğü
1 2 3 4 ← sütun hatları (grid line)
1 ┌────────┬────────┬────────┐
│ hücre │ │ │ ← iz (track) = iki hat arası
2 ├────────┼────────┼────────┤
│ │ alan (area) │ ← birden çok hücrenin dikdörtgeni
3 └────────┴────────┴────────┘
↑ satır hatları
Dikkat: numaralanan şey hücreler değil hatlardır. Üç sütunlu bir ızgarada
dört sütun hattı vardır. Yerleştirme yaparken grid-column: 1 / 3
yazdığında "1. hattan 3. hatta kadar", yani iki sütun genişliğinde demiş olursun.
Bu, Grid'i ilk öğrenirken en çok yanılgı üreten noktadır.
.kapsayici { display: grid; } /* blok düzeyinde ızgara */
.kapsayici { display: inline-grid; } /* metin akışında duran ızgara */
03İzleri tanımlamak
.izgara {
display: grid;
grid-template-columns: 200px 1fr 300px; /* üç sütun */
grid-template-rows: auto 1fr auto; /* üç satır */
gap: 1rem;
}
| Değer | Anlamı |
|---|---|
200px, 10rem | Sabit |
auto | İçeriğe göre; kalan boşluk varsa büyüyebilir |
min-content | En uzun kelime kadar |
max-content | Hiç sarmadan gereken genişlik |
fit-content(300px) | İçeriğe göre, ama en fazla 300 px |
1fr | Kalan boşluğun bir payı |
minmax(200px, 1fr) | En az 200 px, en çok bir pay |
fr birimi gerçekte ne yapar
fr "fraction" — kalan boşluğun kesridir. 1fr 2fr yazarsan kalan
boşluk 1:2 oranında bölünür. Ama bilinmesi gereken önemli bir ayrıntı vardır:
1fr aslında minmax(auto, 1fr) demektir. Yani izin taban
boyutu auto'dur ve içeriğinden daha dar olamaz. 9. derste Flexbox'ta
gördüğün min-width: auto tuzağının Grid'deki karşılığı budur:
.izgara { grid-template-columns: 1fr 1fr; }
/* İçlerinden birinde uzun bir URL ya da geniş bir tablo varsa,
o sütun "1fr"e rağmen daralmaz ve ızgara taşar. */
.izgara { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } /* çözüm */
/* ya da öge tarafında: .hucre { min-width: 0; overflow: hidden; } */
Kaydırılabilir bir bölgeyi bir ızgara hücresine koyduğunda da aynı şey gerekir; aksi hâlde hücre kaydırılmak yerine büyür.
repeat(), auto-fill ve auto-fit
grid-template-columns: repeat(4, 1fr); /* 1fr 1fr 1fr 1fr */
grid-template-columns: repeat(2, 200px 1fr); /* desen tekrarı */
grid-template-columns: 200px repeat(3, 1fr) 100px; /* karışık */
Asıl güç, repeat()'in sayı yerine anahtar kelime almasındadır:
/* MEDYA SORGUSU YOK — sütun sayısına tarayıcı karar verir */
.kartlar {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: 1rem;
}
Okunuşu: "en az 260 px, en çok bir pay olan sütunlardan sığdığı kadar aç." Pencere daraldıkça sütun sayısı 4 → 3 → 2 → 1'e düşer. Bu tek satır, eskiden beş medya sorgusu gerektiren işi yapar.
auto-fill | auto-fit | |
|---|---|---|
| Sığan sütun sayısı kadar iz açar | Evet | Evet |
| Boş kalan izler | Korunur — yer kaplar | Daraltılıp yok edilir |
| 3 kart, 5 sütunluk yer varsa | Kartlar solda kalır, sağda 2 boş sütun durur | Kartlar genişleyip tüm satırı doldurur |
| Ne zaman | Izgara hizası korunsun isteniyorsa (satırlar arası sütunlar hizalı kalsın) | Az sayıda öge boşluğu doldursun isteniyorsa — genelde istenen budur |
Fark yalnızca ögeler sütun sayısından az olduğunda görünür; eleman sayısı fazlaysa ikisi aynı sonucu verir. Bu, mülakatta bilgi derinliğini ölçen tipik bir ayrıntıdır.
04Ögeleri yerleştirmek
Bir şey yazmazsan ögeler hücrelere sırayla, soldan sağa ve yukarıdan aşağıya yerleşir. Yerleştirmeyi elle yapmanın üç yolu vardır.
1. Hat numarasıyla
.baslik { grid-column: 1 / 4; } /* 1. hattan 4. hatta → üç sütun */
.baslik { grid-column: 1 / -1; } /* -1 = SON hat → "tüm satırı kapla" */
.icerik { grid-column: span 2; } /* bulunduğu yerden iki sütun */
.kutu { grid-row: 2 / 4; } /* satırlarda aynı mantık */
.kutu { grid-area: 2 / 1 / 4 / 3; } /* satır-baş / sütun-baş / satır-son / sütun-son */
-1 kısayolu çok kullanılır: bir başlığın ya da tam genişlikte bir uyarı
kutusunun sütun sayısından bağımsız olarak satırı kaplaması için
grid-column: 1 / -1 yeterlidir.
2. Hat adlarıyla
.duzen {
display: grid;
grid-template-columns: [kenar-bas] 240px [icerik-bas] 1fr [icerik-son] 300px [kenar-son];
}
.icerik { grid-column: icerik-bas / icerik-son; }
3. Alan adlarıyla — en okunaklısı
.sayfa {
display: grid;
grid-template-columns: 240px 1fr;
grid-template-rows: auto 1fr auto;
min-height: 100dvh;
grid-template-areas:
"ustbar ustbar"
"yanmenu icerik"
"altbilgi altbilgi";
}
.ustbar { grid-area: ustbar; }
.yanmenu { grid-area: yanmenu; }
.icerik { grid-area: icerik; }
.altbilgi { grid-area: altbilgi; }
/* Dar ekranda yalnız haritayı değiştir — tek sütuna in */
@media (max-width: 700px) {
.sayfa {
grid-template-columns: 1fr;
grid-template-areas: "ustbar" "yanmenu" "icerik" "altbilgi";
}
}
grid-template-areas'ın değeri okunabilirliktir: yerleşimi CSS'te ASCII
çizimi gibi görürsün ve duyarlı düzende yalnızca haritayı değiştirirsin. Kurallar:
her alan dikdörtgen olmalıdır (L şeklinde alan tanımlanamaz), boş hücre için
. yazılır ve her satırda sütun sayısı eşit olmalıdır.
Erişilebilirlik uyarısı burada da geçerlidir: 9. derste order için
söylenen her şey grid-area için de doğrudur. Yukarıdaki dar ekran haritasında
yanmenu'yü icerik'ten sonraya almak görsel sırayı değiştirir
ama klavye ve ekran okuyucu hâlâ DOM sırasını izler. İçerik sırası anlamlıysa işaretlemeyi
doğru sırada yaz.
05Hizalama: altı özellik
| Özellik | Kim | Neyi hizalar |
|---|---|---|
justify-items | Kapsayıcı | Ögeleri hücreleri içinde, yatayda |
align-items | Kapsayıcı | Ögeleri hücreleri içinde, dikeyde |
justify-content | Kapsayıcı | Izgaranın tamamını kapsayıcı içinde, yatayda |
align-content | Kapsayıcı | Izgaranın tamamını, dikeyde |
justify-self / align-self | Öge | Tek bir ögeyi kendi hücresinde |
Ayrımı hatırlamanın yolu: -items hücrenin içi, -content
ızgaranın kendisi. justify-content yalnız izlerin toplamı kapsayıcıdan
küçükse (sabit genişlikli sütunlar varsa) fark yaratır; sütunlar fr ile
tanımlıysa boşluk zaten kalmaz.
place-items: center; /* align-items + justify-items */
place-content: center; /* align-content + justify-content */
place-self: center; /* align-self + justify-self */
/* Bir şeyi tam ortalamanın en kısa yolu */
.orta { display: grid; place-items: center; min-height: 100dvh; }
Flexbox'la karşılaştırıldığında Grid'in avantajı burada da görünür: Flexbox'ta
justify-items yoktur, çünkü tek eksende hücre kavramı yoktur.
06Örtük ızgara
Tanımladığından fazla öge gelirse Grid yeni izler üretir; bunlara örtük ızgara
denir ve boyutları varsayılan olarak auto'dur:
.izgara {
grid-template-columns: repeat(3, 1fr); /* açık: 3 sütun */
grid-auto-rows: minmax(120px, auto); /* örtük satırlar en az 120 px */
grid-auto-flow: row; /* varsayılan: satır satır doldur */
}
.galeri { grid-auto-flow: dense; } /* boşlukları geriye dönüp doldur */
dense farklı boyutlarda kartlar olan galerilerde delikleri kapatır ama
görsel sırayı DOM sırasından koparır — yine aynı erişilebilirlik ödünü.
grid-auto-flow: column ise ögeleri sütun sütun doldurur; sütun sayısı bilinmeyen
yatay listelerde işe yarar.
07Gerçek kalıplar
/* 1. Duyarlı kart ızgarası — medya sorgusu yok */
.kartlar { display: grid; gap: 1rem;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
/* 2. Form: etiket ve alan hizalı — 4. derste "tablo kullanma" dediğimiz iş */
.form {
display: grid;
grid-template-columns: max-content 1fr; /* etiketler kendi genişliğinde, hizalı */
gap: .75rem 1rem;
align-items: baseline;
}
.form .tam-satir { grid-column: 1 / -1; } /* açıklama ve düğmeler tüm satırı kaplar */
@media (max-width: 600px) { /* dar ekranda tek sütun */
.form { grid-template-columns: 1fr; }
}
/* 3. Aynı hücrede üst üste: position: absolute'a gerek yok */
.kapak { display: grid; }
.kapak > * { grid-area: 1 / 1; } /* hepsi aynı hücreye */
.kapak .yazi { place-self: end start; z-index: 1; }
/* 4. "Kutsal kâse": kenarlar sabit, orta esner, altbilgi yapışık */
.iskelet { display: grid; min-height: 100dvh;
grid-template: auto 1fr auto / 240px 1fr; }
/* 5. Kenarlıklı içerik hattı: içerik ortada, arka plan tam genişlikte */
.sayfa { display: grid; grid-template-columns: 1fr min(70ch, 100%) 1fr; }
.sayfa > * { grid-column: 2; }
.sayfa > .tam-genislik { grid-column: 1 / -1; }
İkinci kalıp, 4. derste "form yerleşimi için tablo kullanma" derken kastedilen doğru
araçtır: max-content 1fr ile etiketler en uzun etikete göre hizalanır, dar
ekranda tek satırla tek sütuna inersin ve işaretlemede hiçbir değişiklik gerekmez.
Üçüncü kalıp da pratik bir kazanç sağlar: üst üste bindirme için
position: absolute kullandığında kapsayıcının yüksekliği içerikten
bağımsızlaşır ve elle yükseklik vermen gerekir; Grid'de tüm katmanlar aynı hücrede
olduğu için en uzun olan yüksekliği belirler.
subgrid
Bir ızgara ögesinin kendi çocuklarını dış ızgaranın hatlarına hizalaması gerektiğinde kullanılır. Klasik sorun: kart listesinde her kartın başlığı, metni ve düğmesi kendi içinde hizalıdır ama kartlar arasında hizalı değildir.
.kartlar { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
grid-template-rows: auto 1fr auto; }
.kart { display: grid; grid-row: span 3; grid-template-rows: subgrid; }
/* Artık tüm kartların başlıkları, metinleri ve düğmeleri aynı hatta hizalanır. */
subgrid tarayıcılara geç geldi; destek durumunu kontrol etmek gerekir.
Desteklenmediğinde kartlar yine çalışır, sadece iç hizalama kaybolur — yani 7. derste
konuştuğumuz kademeli geliştirmeye uygun bir özelliktir.
Grid tabloyu değiştirir mi?
Görsel olarak evet, anlamsal olarak hayır. Grid ile bir tablo görünümü
çizebilirsin ama ekran okuyucu orada satır–sütun ilişkisi görmez: hangi değerin hangi
başlığa ait olduğu duyurulmaz, hücreler arasında ok tuşlarıyla gezilemez.
Veri tablosu tablodur (4. ders); Grid tabloyu değil, yerleşim tablosunu
ortadan kaldırır. Buna karşılık bir tablonun kendisine
display: grid vermek de yanlıştır — tablonun yerleşim semantiğini bozar ve
bazı ekran okuyucularda tablo olmaktan çıkarır. Dar ekranda tabloyu kart görünümüne
çevirme kararının bedeli buydu.
08Mini alıştırma — Izgarayı kur, kır, ölç
Yaklaşık 20 dakika · tek HTML dosyası + DevTools grid denetleyicisi
- Kur: dokuz kutulu bir ızgara yaz
(
grid-template-columns: repeat(3, 1fr)). DevTools'ta kapsayıcının yanındakigridrozetine tıkla; hat numaralarını ve alan adlarını ekranda göster. - Hat sayısı: üç sütunda kaç sütun hattı var?
grid-column: 1 / 3verdiğinde öge kaç sütun kapladı? -1: bir başlığagrid-column: 1 / -1ver ve sütun sayısını 3'ten 5'e çıkar. Başlık uyum sağladı mı?frhesabı:200px 1fr 2fryaz ve pencereyi daralt. Sabit sütun değişti mi, oran nasıl korundu?- Tuzak:
1fr 1frolan ızgaranın bir hücresine çok uzun bir URL yapıştır. Izgara taştı mı?minmax(0, 1fr)ile tekrarla. auto-fitvsauto-fill:repeat(auto-fit, minmax(200px, 1fr))ile üç kart göster; pencereyi genişlet. Sonraauto-fill'e çevir. Fark ne zaman görünüyor?- Alan haritası:
grid-template-areasile üst bar + yan menü + içerik + altbilgi iskeleti kur. Sonra yalnız medya sorgusunda haritayı değiştirerek tek sütuna in. - Dikdörtgen kuralı: haritada L şeklinde bir alan tanımlamayı dene. DevTools ne gösteriyor?
- Hizalama:
justify-items,align-items,justify-content,align-contentdeğerlerini tek tek değiştir. Sabit genişlikli sütunlarda ve1frsütunlarda hangileri etki etti? - Ortalama:
display: grid; place-items: center; min-height: 100dvhile bir kutuyu tam ortala. Flexbox'la aynı işi yapıp satır sayısını karşılaştır. - Örtük ızgara: üç sütunlu ızgaraya 10 öge koy. Dördüncü satır nereden geldi?
grid-auto-rows: minmax(120px, auto)ekleyip farkı gör. dense: bazı ögeleregrid-column: span 2ver, boşluk oluşsun.grid-auto-flow: denseekle — boşluk doldu mu? Şimdi Tab ile gez; odak sırası görsel sırayla aynı mı?- Form: 2. kalıptaki
max-content 1frformunu kur. En uzun etiketi uzat — sütun genişliği uyum sağladı mı? - Üst üste bindirme: 3. kalıpla bir görselin üzerine yazı koy. Kapsayıcının
yüksekliğini vermeden çalışıyor mu? Aynısını
position: absoluteile deneyip farkı gör.
09Kendini sına
Grid ile Flexbox arasındaki fark nedir? Hangisini ne zaman kullanırsın?
Flexbox tek boyutludur: ögeleri bir eksende dizer, kalan
boşluğu dağıtır. Grid iki boyutludur: satır ve sütunu aynı anda tanımlar ve ögeleri
hücrelere yerleştirir. Çalışma yönleri de terstir: Flexbox içerikten yerleşime
gider — ögelerin boyutunu içerikleri belirler; Grid yerleşimden içeriğe gider —
ızgarayı sen tanımlarsın, içerik ona uyar. Karar ölçütü: tek eksende dizilim ve içeriğe
göre boyut istiyorsan Flexbox (üst bar, düğme grubu, etiket–değer satırı, bir kartın iç
dizilimi); satır ve sütun hizalaması gerekiyorsa Grid (sayfa iskeleti, kart
ızgarası, form etiket–alan hizalaması). İkisi rakip değildir: tipik bir sayfada dış iskelet
Grid, iç bileşenler Flexbox olur. Grid'in Flexbox'ta bulunmayan yetenekleri:
grid-template-areas ile okunaklı harita, justify-items gibi hücre
içi hizalama, aynı hücrede üst üste bindirme ve auto-fit/minmax
ile medya sorgusuz duyarlı ızgara. Flexbox'ın avantajı ise bilinmeyen sayıda ve
değişken boyutlu ögeyi tek eksende dağıtmaktır.
auto-fill ile auto-fit arasındaki fark nedir?
İkisi de repeat() içinde "sığdığı kadar sütun aç" der ve
ögeler sütun sayısını dolduruyorsa aynı sonucu verir. Fark, ögeler açılan sütun
sayısından az olduğunda ortaya çıkar. auto-fill boş kalan izleri
korur: 5 sütunluk yerde 3 kart varsa kartlar solda kalır, sağda iki boş sütun
yer kaplar. auto-fit ise boş izleri sıfıra daraltır; kalan
1fr payları mevcut kartlara gider ve kartlar genişleyip satırı doldurur.
Pratikte genelde istenen auto-fit'tir
(repeat(auto-fit, minmax(260px, 1fr))) — az sayıda öge olduğunda düzen
boşluklu görünmez. auto-fill ise sütun hizasının korunması gerektiğinde
tercih edilir: farklı satırlardaki ögelerin aynı sütun hatlarında kalmasını istiyorsan ya
da ızgaraya sonradan öge eklendiğinde düzenin kaymamasını istiyorsan. Not: bu kalıp,
eskiden dört-beş medya sorgusu gerektiren duyarlı kart ızgarasını tek satıra
indirir.
1fr ile tanımladığın bir sütun neden içeriğinden daha dar olmuyor?
Çünkü 1fr aslında minmax(auto, 1fr)
anlamına gelir: izin en büyük boyutu bir paydır, ama en küçük boyutu
auto'dur — yani içeriğinin en küçük boyutundan (kırılamayan en uzun kelime,
geniş bir tablo, bir <pre> bloğu) daha dar olamaz. Sonuç: iki
1fr sütunlu bir ızgara, içine uzun bir URL konduğunda taşar ve sayfada yatay
kaydırma çubuğu çıkar. Çözüm izi minmax(0, 1fr) olarak tanımlamaktır;
alternatif olarak hücreye min-width: 0 ya da overflow: hidden
yazmaktır. Bu, 9. derste Flexbox'ta gördüğün min-width: auto tuzağının
Grid'deki tam karşılığıdır ve aynı belirtiyi verir. Kaydırılabilir bir bölgeyi hücreye
koyduğunda da gereklidir — aksi hâlde bölge kaydırılmak yerine hücreyi büyütür. Metnin
kendisi taşıyorsa ayrıca overflow-wrap: break-word eklenir.
grid-template-areas nedir, avantajı ve sınırları nelerdir?
Izgara alanlarına ad vererek yerleşimi CSS içinde bir harita
gibi çizmeyi sağlar: "ustbar ustbar" "yanmenu icerik" yazdığında düzeni
okurken görürsün. Ögeler grid-area: icerik ile yerlerine oturur.
Avantajı okunabilirlik ve duyarlı düzendir: dar ekranda yalnızca haritayı
değiştirerek tüm yerleşimi yeniden kurarsın, ne işaretlemeye ne öge kurallarına dokunursun.
Kuralları: her alan dikdörtgen olmalıdır (L şeklinde alan tanımlanamaz), her
satırda sütun sayısı eşit olmalıdır ve boş hücre için . yazılır.
Sınırları: (1) çok sayıda ve dinamik öge için uygun değildir — orada otomatik
yerleşim ya da auto-fit kullanılır; (2) alan adları CSS'te sabittir, bileşen
içeriği değişkense esnek olmaz; (3) en önemlisi, görsel sırayı DOM sırasından
koparabilir — dar ekranda yan menüyü içerikten sonraya almak gözle işe yarar ama klavye
ve ekran okuyucu hâlâ DOM sırasını izler, dolayısıyla sırası anlamlı içerikte
işaretlemeyi doğru yazmak gerekir.
10Sınav köşesi
Yazılıda nasıl sorulur
(1) CSS Grid nedir, Flexbox'tan farkı nedir? (2) grid-template-columns ve
grid-template-rows nasıl tanımlanır? (3) fr birimi nedir?
(4) repeat(), minmax(), auto-fit,
auto-fill kullanımı. (5) grid-template-areas ile yerleşim
kurunuz — genelde uygulamalı sorulur. (6) grid-column /
grid-row ve span. (7) Grid hizalama özellikleri;
justify-items ile justify-content farkı. (8) Örtük ve açık
ızgara. (9) Medya sorgusu kullanmadan duyarlı ızgara nasıl yapılır?
(10) Grid ile tablo arasındaki fark; hangisi ne zaman?
Sözlüde nasıl anlatılır — 2 dakikalık taslak
Düzen: (1) Tanım — "Grid iki boyutlu yerleşim sistemidir: satır ve sütunu birlikte
tanımlar. Flexbox içerikten yerleşime çalışır, Grid yerleşimden içeriğe."
(2) Temel araçlar — "izleri grid-template-columns ile tanımlarım;
fr kalan boşluğun payıdır, minmax ile alt ve üst sınır
koyarım." (3) Kıdem vuruşu — "repeat(auto-fit, minmax(260px, 1fr)) tek
satırla duyarlı kart ızgarası verir; medya sorgusu yazmam. auto-fill boş
izleri korur, auto-fit daraltır — fark yalnız öge sayısı sütun sayısından
azken görünür." (4) Tuzak bilgisi — "1fr aslında
minmax(auto, 1fr)'dir; içinde uzun bir URL olan sütun daralmaz ve ızgara
taşar, bunun için minmax(0, 1fr) yazarım."
(5) Pratik ve sınır — "sayfa iskeletini grid-template-areas ile kurarım,
dar ekranda yalnız haritayı değiştiririm. Ama görsel sırayı DOM sırasından kopardığım
yerde klavye ve ekran okuyucu eski sırayı izler; ayrıca Grid tabloyu anlamsal
olarak değiştirmez — veri tablosu tablodur, Grid yalnız yerleşim tablosunu ortadan
kaldırır."
