Ders 10 / 19
Kesme Noktaları ve Izgara
Kesme noktalarının düzen yapılandırması taşıyan belirteçlere dönüştürülmesi, sütun aritmetiğinin her kesme noktasında denetlenmesi, boşta kalan kesme noktasının saptanması ve sınırların içerik ölçütünden türetilmesi.
İçindekiler
Belirteçlerin şimdiye kadarki tamamı tek bir görüntü alanı varsayımıyla kuruldu. Renk rolleri genişlikten bağımsızdır, tipografi basamakları da öyle. Aralık ve boyut belirteçleri ise öyle değil: kenar boşluğu dar bir ekranda 16, geniş bir ekranda 24 piksel olur ve sütun sayısı tümüyle değişir.
Kesme noktası (breakpoint) bu değişimin nerede olacağını söyler. Duyarlı Tasarım İlkesi dersinde kesme noktası bir ortam sorgusu eşiği olarak tanıtılmıştı; sistem düzeyinde ondan fazlasıdır. Bir kesme noktası tek bir sayı değil, o eşikten sonra geçerli olan bütün düzen kararlarını taşıyan bir kayıttır: sütun sayısı, kenar boşluğu, oluk ve kapsayıcının üst sınırı. Bu ders o kaydı belirteç hâline getirir ve kayıtlar arasındaki aritmetiği denetler.
Kesme Noktası Bir Yapılandırma Taşır
Izgara Sistemleri dersinde sütun genişliğinin bağımlı bir büyüklük olduğu gösterilmişti:
Kesme noktası kümesi bu bağıntının girdilerini genişlik aralıklarına dağıtır. Denetimin işi her aralıkta bağıntının anlamlı bir sonuç verdiğini ve aralıkların birbirine göre tutarlı olduğunu göstermektir.
Denetim beş soruya yanıt arar. Sütun genişliği tam sayı mı çıkıyor? Kenar boşluğu ve oluk değerleri aralık ölçeğinden mi geliyor? Bir kesme noktası bir öncekinden farklı bir yapılandırma taşıyor mu? İçerik ölçütleri hangi genişlikten itibaren karşılanıyor? Kapsayıcının üst sınırı neye göre seçilmiş?
// kesme.mjs — kesme noktasi kumesinin sutun aritmetigiyle denetlenmesi const ARALIK_OLCEGI = [4, 8, 12, 16, 20, 24, 32, 48, 64, 96]; // Her kesme noktasi bir duzen yapilandirmasi tasir. ustSinir null ise kapsayici akiskandir. const KESME = [ { ad: "dar", alt: 320, sutun: 4, kenar: 16, oluk: 16, ustSinir: null }, { ad: "orta", alt: 640, sutun: 8, kenar: 24, oluk: 24, ustSinir: null }, { ad: "genis", alt: 1024, sutun: 12, kenar: 24, oluk: 24, ustSinir: null }, { ad: "cok-genis", alt: 1440, sutun: 12, kenar: 24, oluk: 24, ustSinir: 1200 }, { ad: "ultra", alt: 1920, sutun: 12, kenar: 24, oluk: 24, ustSinir: 1200 }, ]; const kapsayici = (k, gorusAlani) => (k.ustSinir === null ? gorusAlani : Math.min(gorusAlani, k.ustSinir)); const sutunGenisligi = (kapsayici, k) => (kapsayici - 2 * k.kenar - (k.sutun - 1) * k.oluk) / k.sutun; const acilim = (n, sutun, oluk) => n * sutun + (n - 1) * oluk; console.log("kesme alt sinir sutun kenar oluk ust sinir kapsayici sutun genisligi tam sayi"); for (const k of KESME) { const kap = kapsayici(k, k.alt); const s = sutunGenisligi(kap, k); console.log( `${k.ad.padEnd(10)} ${String(k.alt).padStart(9)} ${String(k.sutun).padStart(6)} ${String(k.kenar).padStart(6)} ` + `${String(k.oluk).padStart(5)} ${String(k.ustSinir ?? "-").padStart(10)} ${String(kap).padStart(10)} ` + `${s.toFixed(3).padStart(16)} ${(Number.isInteger(s) ? "evet" : "hayir").padStart(9)}` ); } // Aralik degerleri olcekten mi geliyor? console.log("\nkesme kenar olcekte oluk olcekte"); for (const k of KESME) { console.log( `${k.ad.padEnd(10)} ${(ARALIK_OLCEGI.includes(k.kenar) ? "evet" : "HAYIR").padStart(13)} ` + `${(ARALIK_OLCEGI.includes(k.oluk) ? "evet" : "HAYIR").padStart(13)}` ); } // Bosta kalan kesme noktasi: bir onceki ile ayni duzen yapilandirmasini tasiyor. const imza = (k) => `${k.sutun}/${k.kenar}/${k.oluk}/${k.ustSinir}`; console.log("\nkesme imza onceki ile ayni mi"); for (let i = 0; i < KESME.length; i++) { const ayni = i > 0 && imza(KESME[i]) === imza(KESME[i - 1]); console.log(`${KESME[i].ad.padEnd(10)} ${imza(KESME[i]).padEnd(18)} ${ayni ? "EVET (bosta)" : "hayir"}`); } // Akiskan aralikta sutun genisligi kac gorus alani genisliginde tam sayi cikiyor? console.log("\nkesme aralik ornek genislik tam sayi ciktigi genislik sayisi"); for (const k of KESME) { const ust = KESME[KESME.indexOf(k) + 1]?.alt ?? 2560; let tam = 0; let ornek = 0; for (let w = k.alt; w < ust; w++) { ornek++; if (Number.isInteger(sutunGenisligi(kapsayici(k, w), k))) tam++; } console.log( `${k.ad.padEnd(10)} ${(k.alt + " - " + (ust - 1)).padEnd(17)} ${String(ornek).padStart(14)} ` + `${(tam + " (" + ((100 * tam) / ornek).toFixed(1) + "%)").padStart(31)}` ); } // Icerik olcutu: suzgec paneli en az 270 px, sonuc listesi en az 480 px istiyor // (Izgara Sistemleri dersinde hesaplanan degerler). const SUZGEC_EN_AZ = 270; const LISTE_EN_AZ = 480; console.log("\nkesme bolunme suzgec (px) liste (px) suzgec >=270 liste >=480 karar"); for (const k of KESME) { const kap = kapsayici(k, k.alt); const s = sutunGenisligi(kap, k); let secilen = null; for (let a = 1; a < k.sutun; a++) { const suzgec = acilim(a, s, k.oluk); const liste = acilim(k.sutun - a, s, k.oluk); if (suzgec >= SUZGEC_EN_AZ && liste >= LISTE_EN_AZ) { secilen = { a, suzgec, liste }; break; } } if (secilen) { console.log( `${k.ad.padEnd(10)} ${(secilen.a + "+" + (k.sutun - secilen.a)).padEnd(9)} ${secilen.suzgec.toFixed(1).padStart(11)} ` + `${secilen.liste.toFixed(1).padStart(11)} ${"evet".padStart(13)} ${"evet".padStart(12)} iki sutun` ); } else { console.log( `${k.ad.padEnd(10)} ${"-".padEnd(9)} ${"-".padStart(11)} ${"-".padStart(11)} ${"-".padStart(13)} ${"-".padStart(12)} tek sutun` ); } } // Iki sutunlu duzenin acildigi en kucuk gorus alani genisligi const genis = KESME.find((k) => k.ad === "genis"); let esik = null; for (let w = 320; w <= 1600; w++) { const s = sutunGenisligi(kapsayici(genis, w), genis); const uygun = [...Array(genis.sutun - 1).keys()] .map((i) => i + 1) .some((a) => acilim(a, s, genis.oluk) >= SUZGEC_EN_AZ && acilim(genis.sutun - a, s, genis.oluk) >= LISTE_EN_AZ); if (uygun) { esik = w; break; } } console.log(`\n12 sutunlu yapilandirmayla iki sutunlu duzenin acildigi en kucuk genislik: ${esik} px`); console.log(`genis kesme noktasinin alt siniri: ${genis.alt} px -> ${genis.alt >= esik ? "icerik olcutunu karsiliyor" : "ERKEN"}`); // Ust sinirin gerekcesi: satir uzunlugu. 16 px metinde ortalama karakter genisligi 7.005 px // (Satir Uzunlugu ve Araligi dersinde olculdu); 75 karakter ust siniri 525 px eder. const KARAKTER_PX = 7.005; console.log("\nkapsayici 9 sutun acilimi karakter 45-75 araliginda mi"); for (const kap of [1024, 1200, 1440, 1920]) { const k = { sutun: 12, kenar: 24, oluk: 24 }; const s = sutunGenisligi(kap, k); const en = acilim(9, s, k.oluk); const karakter = en / KARAKTER_PX; console.log( `${String(kap).padStart(9)} ${en.toFixed(1).padStart(16)} ${karakter.toFixed(1).padStart(9)} ` + `${(karakter <= 75 ? "evet" : "HAYIR").padStart(20)}` ); }
kesme alt sinir sutun kenar oluk ust sinir kapsayici sutun genisligi tam sayi
dar 320 4 16 16 - 320 60.000 evet
orta 640 8 24 24 - 640 53.000 evet
genis 1024 12 24 24 - 1024 59.333 hayir
cok-genis 1440 12 24 24 1200 1200 74.000 evet
ultra 1920 12 24 24 1200 1200 74.000 evet
kesme kenar olcekte oluk olcekte
dar evet evet
orta evet evet
genis evet evet
cok-genis evet evet
ultra evet evet
kesme imza onceki ile ayni mi
dar 4/16/16/null hayir
orta 8/24/24/null hayir
genis 12/24/24/null hayir
cok-genis 12/24/24/1200 hayir
ultra 12/24/24/1200 EVET (bosta)
kesme aralik ornek genislik tam sayi ciktigi genislik sayisi
dar 320 - 639 320 80 (25.0%)
orta 640 - 1023 384 48 (12.5%)
genis 1024 - 1439 416 34 (8.2%)
cok-genis 1440 - 1919 480 480 (100.0%)
ultra 1920 - 2559 640 640 (100.0%)
kesme bolunme suzgec (px) liste (px) suzgec >=270 liste >=480 karar
dar - - - - - tek sutun
orta - - - - - tek sutun
genis 4+8 309.3 642.7 evet evet iki sutun
cok-genis 3+9 270.0 858.0 evet evet iki sutun
ultra 3+9 270.0 858.0 evet evet iki sutun
12 sutunlu yapilandirmayla iki sutunlu duzenin acildigi en kucuk genislik: 888 px
genis kesme noktasinin alt siniri: 1024 px -> icerik olcutunu karsiliyor
kapsayici 9 sutun acilimi karakter 45-75 araliginda mi
1024 726.0 103.6 HAYIR
1200 858.0 122.5 HAYIR
1440 1038.0 148.2 HAYIR
1920 1398.0 199.6 HAYIR
Boşta Kalan Kesme Noktası
Üçüncü tablo en doğrudan bulguyu veriyor. ultra kesme noktası, cok-genis ile aynı
yapılandırmayı taşıyor: 12 sütun, 24 kenar boşluğu, 24 oluk, 1200 piksel üst sınır. İkisi
arasında hiçbir düzen kararı değişmiyor.
Böyle bir kesme noktası bir kural üretmez, yalnız bir ad üretir. Bedeli üç yerde ödenir: biçem dosyası bir ortam sorgusu daha taşır, sınama listesi bir genişlik daha içerir ve yeni gelen biri bu genişlikte ne değiştiğini bulmaya çalışır. Boşta kalan kesme noktası, önceki derslerdeki boşta kalan belirtecin düzen tarafındaki karşılığıdır ve aynı biçimde kaldırılır.
Kesme noktalarının sayısı bir hedef değildir. Her kesme noktası bir düzen kararı değiştirmelidir; değiştirmiyorsa kesme noktası değil, bir sayıdır.
Tam Sayı Sütun Bir Kural Olamaz
Dördüncü tablo düzen aritmetiğinin en çok yanlış anlaşılan yanını ölçüyor. Akışkan aralıklarda sütun genişliği çok nadiren tam sayı çıkıyor: dar aralıkta genişliklerin yüzde 25’inde, orta aralıkta yüzde 12.5’inde, geniş aralıkta yalnız yüzde 8.2’sinde.
Kapsayıcının üst sınırla sabitlendiği iki aralıkta oran yüzde 100. Nedeni açıktır: kapsayıcı sabitlendiğinde sütun genişliği de sabitlenir ve tek bir değer hesaplanır.
Buradan çıkan sonuç, tam sayı sütun genişliğinin bir tasarım hedefi olamayacağıdır. Akışkan bir ızgarada sütun genişliği sürekli değişir; onu tam sayıya zorlamak, kapsayıcıyı tam sayı katlarına yuvarlamak demektir ve bu, kenarlarda düzensiz boşluklar bırakır. Doğru yaklaşım sütun genişliğini hiç yazmamaktır: ızgara pay birimleriyle tanımlanır, sütun genişliği çizim aşamasında hesaplanır ve hizalar ızgaranın kendisinden gelir.
Hesabın işlevi de burada netleşir. Sütun genişliği bir bildirim için değil, içerik ölçütlerini sınamak için hesaplanır: bir bloğun kaç piksel yer bulacağı ve bunun yeterli olup olmadığı.
Kesme Noktası İçerikten Türetilir, Aygıttan Değil
Beşinci ve altıncı bloklar kesme noktası değerlerinin nereden geleceğini yanıtlıyor. Süzgeç paneli en az 270, sonuç listesi en az 480 piksel istiyor; bu değerler Izgara Sistemleri dersinde içerik ölçütlerinden hesaplanmıştı.
Dar ve orta kesme noktalarında hiçbir bölünme iki ölçütü birden karşılamıyor; düzen tek sütunlu kalıyor. Geniş kesme noktasında 4+8 bölünmesi çalışıyor, çok geniş kesme noktasında 3+9.
Altıncı blok bir uyumsuzluk gösteriyor. 12 sütunlu yapılandırmayla iki sütunlu düzenin
açılabildiği en küçük genişlik 888 piksel; oysa genis kesme noktasının alt sınırı 1024.
Aradaki 136 piksellik bant boyunca düzen tek sütunlu kalıyor, ama içerik iki sütuna sığıyor.
Bu, kesme noktası değerlerinin nereden seçildiğine dair bir bulgudur. 1024 bir içerik ölçütü değil, bir aygıt genişliğidir; hesaptan değil alışkanlıktan gelir. İçerikten türetilen değer 888’dir ve aralık ölçeğine yakın bir yuvarlama ile 896 alınabilir. Beş Yıl testinin düzen tarafındaki karşılığı budur: aygıt genişliklerine bağlanan bir kesme noktası, aygıtlar değiştiğinde yanlış hâle gelir; içerik ölçütüne bağlanan kesme noktası, içerik değişmediği sürece doğru kalır.
Üst Sınır da Bir İçerik Kararıdır
Son tablo kapsayıcının üst sınırının gerekçesini arıyor ve beklenmedik bir sonuç veriyor. Dokuz sütunluk sonuç listesi alanı 1024 piksellik kapsayıcıda 726, 1200’de 858, 1920’de 1398 piksel genişliğinde. Satır Uzunluğu ve Aralığı dersinde ölçülen ortalama karakter genişliğiyle bu, sırasıyla 103.6, 122.5 ve 199.6 karakter eder. Dördü de 45–75 aralığının dışında.
Bu, üst sınırın satır uzunluğunu tek başına çözmediğini gösteriyor. 1200 piksellik üst sınır sonuç listesi alanını 858 piksele indiriyor ama 858 piksel hâlâ 122 karakterlik bir satır demektir.
Doğru okuma şudur: kapsayıcı üst sınırı düzenin üst sınırıdır, metnin değil. Metnin üst sınırı ayrı bir belirteçtir ve sütun sayısına değil karakter sayısına bağlıdır. Kayıt kartındaki özet paragrafı 9 sütunun tamamını değil, kendi ölçü sınırını kullanır. İki sınır karıştırıldığında ya düzen gereksiz yere daraltılır ya da metin okunamayacak kadar uzar.
Yazılı Biçim
Kesme noktaları belirteç olarak tanımlanır, ama ortam sorgusu koşullarında doğrudan kullanılamazlar: bir ortam sorgusu koşulu özel özellik okuyamaz. Bu, belirteç sisteminin biçemle olan sınırının ikinci örneğidir; birincisi kontrast sözleşmesiydi.
:root { --kesme-orta: 640px; --kesme-genis: 896px; --kesme-cok-genis: 1440px; --izgara-sutun: 4; --izgara-kenar: var(--adim-4); --izgara-oluk: var(--adim-4); --izgara-ust-sinir: none; } @media (min-width: 640px) { :root { --izgara-sutun: 8; --izgara-kenar: var(--adim-6); --izgara-oluk: var(--adim-6); } } @media (min-width: 896px) { :root { --izgara-sutun: 12; } } @media (min-width: 1440px) { :root { --izgara-ust-sinir: 1200px; } } .izgara { display: grid; grid-template-columns: repeat(var(--izgara-sutun), 1fr); gap: var(--izgara-oluk); padding-inline: var(--izgara-kenar); max-width: var(--izgara-ust-sinir); margin-inline: auto; }
Sorgu koşullarındaki sayılar elle yazıldığı için belirteç değerleriyle çakışma riski taşır. Çözüm, sorgu koşullarını belirteç dosyasından üreten bir derleme adımıdır: kesme noktası değerleri tek bir kaynakta durur, biçem dosyası oradan üretilir. Ön ve Son İşlemciler dersinde ayrılan iş bölümü burada uygulanır — sorgu koşulu derleme zamanına, sütun sayısı çalışma zamanına aittir.
Sütun genişliğinin hiçbir yerde yazmadığına dikkat edilmelidir. Izgara pay birimleriyle tanımlandığı için genişlik çizim aşamasında hesaplanır; bu dersteki hesap bildirim üretmek için değil, içerik ölçütlerini sınamak için yapıldı.
Özet
- Kesme noktası bir sayı değil, o eşikten sonra geçerli olan bütün düzen kararlarını taşıyan bir yapılandırma kaydıdır: sütun sayısı, kenar boşluğu, oluk ve kapsayıcı üst sınırı.
- Bir öncekiyle aynı yapılandırmayı taşıyan kesme noktası boştadır; kural üretmez, yalnız bakım yükü üretir ve kaldırılır.
- Akışkan aralıklarda sütun genişliği nadiren tam sayı çıkar — geniş aralıkta genişliklerin yalnız yüzde 8.2’sinde. Tam sayı sütun bir tasarım hedefi olamaz; ızgara pay birimleriyle tanımlanır. Hesabın amacı bildirim üretmek değil, içerik ölçütlerini sınamaktır.
- Kesme noktası değeri aygıt genişliğinden değil içerik ölçütünden türetilir; ölçülen kümede iki sütunlu düzen 888 pikselde açılabiliyorken kesme noktası 1024’te duruyor.
- Kapsayıcı üst sınırı düzenin sınırıdır, metnin değil; metin ölçüsü ayrı bir belirteçtir ve karakter sayısına bağlıdır.
- Ortam sorgusu koşulları özel özellik okuyamaz; kesme noktası değerleri tek kaynakta tutulup sorgu koşulları derleme zamanında üretilir.
Sonraki Adım
Temel katman burada tamamlanıyor: renk, tipografi, aralık, boyut ve düzen kararlarının hepsi adlandırılmış ve türetilebilir hâlde. Geriye tek bir eksik kalıyor. Renk Belirteçleri dersinde yirmi rolün yalnız sekizinin koyu tema karşılığı vardı; on iki hücre boştu. Bir sistemin birden çok temayı taşıması, her tema için ayrı bir değer listesi yazmak değil, temaları tek bir kuraldan türetmektir. Sonraki ders bu türetmeyi kurar: açık temadan koyu temayı ve bir marka temasını üretir, eksik belirteç raporunu kapatır ve belirteç kaynağından biçem çıktısını üretir.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.