İçeriğe geç
academia.sh

Ders 24 / 26

Kenarlık, Gölge ve Şekil

Kenarlık bileşenleri, köşe yarıçapının ölçeklenme kuralı, iç yarıçap hesabı ve gölge katmanlarının kapladığı alan.

İçindekiler

Kutuların içi ve arkası tamamlandı. Kenarları eksik kaldı: kenarlığın nasıl çizildiği, köşelerin nasıl yuvarlatıldığı ve kutunun dışına düşen gölgelerin nereye kadar uzandığı.

Bu üç konu bir arada ele alınır, çünkü aynı sınırı paylaşırlar: kenarlık kutusu. Kenarlık o sınırda çizilir, köşe yarıçapı o sınırı yuvarlatır, gölge o sınırın dışına düşer.

Kenarlığın Üç Bileşeni

border bir kısayoldur ve üç açılımı ayarlar: -width, -style, -color.

border-style yazılmadığında başlangıç değeri none’dır ve kenarlık çizilmez. Bir kenarlığın görünmemesinin en sık sebebi budur: kalınlık ve renk yazılmış ama stil yazılmamıştır.

Stil değerleri arasında solid, dashed, dotted, double, groove, ridge, inset, outset ve hidden bulunur. Son dördü kenarlığa hesaplanmış açık–koyu tonlar vererek kabartma etkisi üretir; renk denetimi ölçek dışına çıktığı için tasarımlı arayüzlerde kullanılmaz.

border-color yazılmadığında currentcolor kullanılır — yani ögenin metin rengi. Renk gösterimleri dersinde anılan bu davranış, kenarlığı metin rengine bağlı tutmanın varsayılan olduğu anlamına gelir.

Dört kenar ayrı ayrı ayarlanabilir ve mantıksal adlarla yazılır: border-block-end, border-inline-start ve akrabaları.

Köşe Yarıçapı Kutuya Sığmalıdır

border-radius köşeleri yuvarlatır. Değer, köşedeki yayın yarıçapıdır ve dört köşe için ayrı ayrı verilebilir.

Bir kısıt vardır: bir kenardaki iki köşenin yarıçapları toplamı o kenarın uzunluğunu aşamaz. Aşarsa bütün yarıçaplar aynı çarpanla küçültülür — yalnızca taşan köşe değil, hepsi. Böylece köşeler arasındaki oran korunur.

// kenarlik.mjs — kose yaricapi olceklemesi, ic yaricap ve golge kutusu hesabi
// kural: yaricap toplami kenardan buyukse hepsi ayni f carpaniyla kucultulur
function yaricapOlcek(kutu, r) {
  const { en, boy } = kutu;
  const f = Math.min(
    en  / (r.solUst + r.sagUst),
    en  / (r.solAlt + r.sagAlt),
    boy / (r.solUst + r.solAlt),
    boy / (r.sagUst + r.sagAlt),
    1
  );
  return Object.fromEntries(Object.entries(r).map(([k, v]) => [k, +(v * f).toFixed(2)]));
}

const durumlar = [
  { kutu: { en: 200, boy: 80 },  r: { solUst: 12, sagUst: 12, sagAlt: 12, solAlt: 12 } },
  { kutu: { en: 200, boy: 80 },  r: { solUst: 60, sagUst: 60, sagAlt: 60, solAlt: 60 } },
  { kutu: { en: 100, boy: 40 },  r: { solUst: 999, sagUst: 999, sagAlt: 999, solAlt: 999 } },
];
for (const d of durumlar) {
  const s = yaricapOlcek(d.kutu, d.r);
  console.log(`kutu ${d.kutu.en}x${d.kutu.boy}, istenen ${d.r.solUst} -> uygulanan ${s.solUst}`);
}

console.log("\n--- ic yaricap: kenarlik kalinligi kadar kucuk ---");
for (const [dis, kalinlik] of [[12, 1], [12, 4], [12, 16], [8, 8]]) {
  const ic = Math.max(0, dis - kalinlik);
  console.log(`dis yaricap=${String(dis).padStart(2)} kenarlik=${String(kalinlik).padStart(2)} -> ic yaricap=${ic}${ic === 0 ? "  (koseli ic kenar)" : ""}`);
}

console.log("\n--- box-shadow: golgenin kapladigi dikdortgen ---");
function golgeKutusu({ en, boy }, { x, y, bulanik, yayilma }) {
  // golge kutusu: yayilma kadar buyur, ofset kadar kay, bulanikligin yarisi kadar tas
  const tasma = bulanik / 2;
  return {
    sol:  x - yayilma - tasma,
    ust:  y - yayilma - tasma,
    sag:  en + x + yayilma + tasma,
    alt:  boy + y + yayilma + tasma,
  };
}
const kutu = { en: 200, boy: 80 };
for (const g of [
  { x: 0, y: 2,  bulanik: 4,  yayilma: 0 },
  { x: 0, y: 8,  bulanik: 24, yayilma: -4 },
  { x: 0, y: 0,  bulanik: 0,  yayilma: 3 },
]) {
  const k = golgeKutusu(kutu, g);
  console.log(`box-shadow: ${g.x}px ${g.y}px ${g.bulanik}px ${g.yayilma}px -> golge (${k.sol}, ${k.ust}) .. (${k.sag}, ${k.alt})`);
}
console.log(`kutunun kendisi: (0, 0) .. (${kutu.en}, ${kutu.boy})`);
kutu 200x80, istenen 12 -> uygulanan 12
kutu 200x80, istenen 60 -> uygulanan 40
kutu 100x40, istenen 999 -> uygulanan 20

--- ic yaricap: kenarlik kalinligi kadar kucuk ---
dis yaricap=12 kenarlik= 1 -> ic yaricap=11
dis yaricap=12 kenarlik= 4 -> ic yaricap=8
dis yaricap=12 kenarlik=16 -> ic yaricap=0  (koseli ic kenar)
dis yaricap= 8 kenarlik= 8 -> ic yaricap=0  (koseli ic kenar)

--- box-shadow: golgenin kapladigi dikdortgen ---
box-shadow: 0px 2px 4px 0px -> golge (-2, 0) .. (202, 84)
box-shadow: 0px 8px 24px -4px -> golge (-8, 0) .. (208, 96)
box-shadow: 0px 0px 0px 3px -> golge (-3, -3) .. (203, 83)
kutunun kendisi: (0, 0) .. (200, 80)

İlk blok üç durumu veriyor. 12 birimlik yarıçap 200×80 kutuya sığdı ve olduğu gibi uygulandı. 60 birimlik yarıçap dikey kenara sığmadı — iki köşe toplamı 120, kenar 80 — ve hepsi 40’a düşürüldü.

Üçüncü satır bir kalıbı açıklıyor. border-radius: 999px yazımı, kutuyu tam yuvarlak uçlu yapmanın standart yoludur: değer her zaman kutunun yarısına inecek kadar büyük seçilir ve kutunun ölçüsü ne olursa olsun sonuç bir hap biçimi olur. Örnekte 999 istendi, 20 uygulandı — 40 birimlik yüksekliğin yarısı.

İç Yarıçap

İkinci blok, iç içe geçmiş yuvarlak köşelerin neden bazen yanlış göründüğünü açıklıyor.

Kenarlığın kenarındaki yarıçap, dış yarıçaptan kenarlık kalınlığı kadar küçüktür. Kalınlık yarıçaptan büyükse iç yarıçap sıfırlanır ve iç kenar köşeli olur — dıştan yuvarlak, içten köşeli bir kenarlık ortaya çıkar.

Aynı hesap iç içe kutular için de geçerlidir. Bir kartın içine, iç boşluk kadar içeride duran ikinci bir yuvarlak kutu konursa, iç kutunun yarıçapı dış yarıçaptan iç boşluk kadar küçük olmalıdır; aksi hâlde iki yay birbirine koşut olmaz:

.kart       { border-radius: 12px; padding: 8px; }
.kart .alan { border-radius: 4px; }   /* 12 - 8 */

Gölge Katmanları

box-shadow dört uzunluk alır: yatay ofset, dikey ofset, bulanıklık yarıçapı ve yayılma. Son ikisi isteğe bağlıdır.

Üçüncü blok, bir gölgenin kapladığı dikdörtgeni hesaplıyor. Bulanıklık yarıçapı bb olan bir gölge, kutunun kenarından yaklaşık b/2b/2 kadar dışarı taşar; yayılma değeri ise gölge dikdörtgenini doğrudan büyütür ya da küçültür.

İkinci satırdaki negatif yayılma bir kalıptır: geniş bir bulanıklıkla yumuşak bir gölge istenirken gölgenin kutunun yanlarından taşması istenmiyorsa yayılma negatif verilir. Sonuç, gölgenin ağırlıklı olarak alta düşmesidir.

Üçüncü satır bulanıklıksız ve ofsetsiz bir gölge gösteriyor: yalnızca yayılma. Bu, kutunun çevresine keskin bir halka çizer ve yer kaplamayan bir kenarlık gibi davranır. outline ile farkı, gölgenin köşe yarıçapını izlemesidir.

Virgülle ayrılarak birden çok gölge yazılabilir; ilk yazılan en üstte çizilir. Katmanlı gölgeler, tek bir gölgeden daha yumuşak bir derinlik verir.

inset anahtar sözcüğü gölgeyi kutunun içine çevirir.

box-shadow ile filter: drop-shadow() arasında bir ayrım vardır: birincisi kenarlık kutusunun dikdörtgenini (ve yarıçapını) izler, ikincisi ögenin görünen biçimini izler ve saydam bölgeleri atlar. Saydamlığı olan bir simge için ikincisi doğru araçtır.

Şekil Vermek

clip-path kutunun çizilecek bölgesini bir geometrik şekle sınırlar:

.simge { clip-path: circle(50%); }
.etiket { clip-path: polygon(0 0, 100% 0, calc(100% - 12px) 100%, 0 100%); }

Kırpma yerleşimi etkilemez: kutu yine dikdörtgen ölçüsünde yer kaplar, yalnızca çizimi kırpılır. Kaydırılmış bir kutunun çevresinden akan metnin sınırını değiştirmek için shape-outside gerekir; iki özellik birlikte yazıldığında biçim ve akış sınırı örtüşür.

Kırpma, kutunun dışına düşen her şeyi keser — odak çerçevesi de dâhil. Kırpılmış bir denetimin odak göstergesi görünmez kalabilir; bu durumda gösterge kutunun içine alınmalıdır.

/* istasyon.css — 23. adım: kenarlık, köşe ve gölge */
.kart {
  border: 1px solid var(--cizgi);
  border-radius: 12px;
  padding: 16px;
  box-shadow:
    0 1px 2px rgb(28 39 51 / 0.06),
    0 8px 24px -4px rgb(28 39 51 / 0.08);
}

.kart .alan { border-radius: 4px; }

.durum-rozeti {
  border-radius: 999px;
  border: 1px solid currentcolor;
  padding-block: 2px;
  padding-inline: 8px;
}

.olcum-cizelgesi { border-collapse: collapse; }

a:focus-visible {
  outline: 3px solid var(--marka-koyu);
  outline-offset: 2px;
  border-radius: 2px;
}

Kartta iki gölge katmanı var: yakın ve keskin olan kenarı belirginleştirir, uzak ve yumuşak olan derinlik verir. İkincisinde negatif yayılma, gölgenin yanlara taşmasını sınırlar.

Rozetin kenarlık rengi currentcolor — metin rengi neyse kenarlık da o olur. Uyarı rozeti kırmızı metin taşıdığında kenarlığı da kırmızı olur; ayrı bir kural yazılmaz.

border-collapse: collapse bildirimi tablo hücrelerinin komşu kenarlıklarını tek bir çizgi hâline getirir. Bu kip, tablo köşelerine yarıçap uygulanmasını da engeller; yuvarlak köşeli bir çizelge isteniyorsa çizelgenin bir sarmalayıcıya alınması ve yarıçapın orada verilmesi gerekir.

Özet

  • border-style yazılmadığında kenarlık çizilmez; kalınlık ve renk yazılmış bir kenarlığın görünmemesinin en sık sebebi budur.
  • Bir kenardaki iki köşenin yarıçapları toplamı kenarı aşarsa bütün yarıçaplar aynı çarpanla küçültülür; border-radius: 999px yazımı bu kurala dayanarak hap biçimi üretir.
  • İç köşe yarıçapı dış yarıçaptan kenarlık kalınlığı kadar küçüktür ve fark sıfırın altına inince iç kenar köşeli olur; iç içe kutularda yarıçap iç boşluk kadar azaltılır.
  • box-shadow gölgesi bulanıklığın yarısı kadar taşar, yayılma değeri gölge dikdörtgenini doğrudan büyütür ya da küçültür; negatif yayılma taşmayı sınırlar.
  • clip-path yalnızca çizimi kırpar, yerleşimi ve kapladığı yeri değiştirmez; odak göstergesi de kırpılabileceği için gösterge kutunun içine alınmalıdır.

Sonraki Adım

Bu konu boyunca uzunluklar hep piksel ve rem olarak yazıldı, ch birimi tanımsız bırakıldı. Bir uzunluk kaç ayrı biçimde yazılabilir ve em ile rem arasındaki fark neden zincirleme bir hesap doğurur? Sonraki ders CSS birimlerini tanımlar ve dönüşümleri hesapla gösterir.

İ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