Tipografi çok önemli ve eski bir alan web’in bu konudaki gelişmeleri mevcut yazılı mecraya göre geride kalıyor. Tabi tarayıcı geliştiricileri olabildiğince bu alanın ihtiyaçlarını görmek için çabalıyor. Metinlerdeki dul (widow) ve yetim (orphan) sorunları tipografinin sorunları ve bunlara çeşitli çözümler üretiliyor. Web’de bu konuya el atma gerekiği hissederek bizlere yeni özellikler kazandırıyor.

Paragraf diziliminde yapılan yanlışlardan biri de dul (widow) ve yetim (orphan) sözcüklerdir. Paragraf veya kolon sonlarındaki oldukça kısa sözcüklere ya da hecelere dul sözcükler, paragraf veya kolonların başlangıç satırında görülen kısa sözcüklere ya da hecelere yetim sözcükler denilmektedir. Bu iki sorun da yarattıkları fazla boşluk nedeniyle okuyucunun gözünü rahatsız edip okumanın akışını bozmaktadır. - KİTAP ve e-KİTAP TASARIMININ TARİHSEL GELİŞİMİ ve GRAFİK TASARIM İLKELERİ ÜZERİNDEN İNCELENMESİ

text orpham & widow

Genelde bu sorunla tasarımcıların gönderdiği tasarımların güzel ancak kodladıktan sonra o kadar da güzel görünmeyen başlıklarında karşılaşıyorduk.

Tasarımcı sadece statik bir başlık ile tasarımı hazırladığı için orada sorun oluşmazken kod yazıp içerik dinamik hale gelince beklenenden farklı bir durumla karşılaşırız. Tabi gelen “acaba ne yapabiliriz?” sorusuna genelde yapacak bir şey yok CSS ve tarayıcıların bu konuda yetenekleri sınırlı deyip geçiyorduk.

Yazı alanlarının önemli olduğu projelerde ise eğer içerik statik ise <br> ile çözüm oluştururken dinamik çözümler için Javascript’i tercih ediyorduk.

Konuyu araştırırken React için React Wrap Balancer çözümü olduğunu gördüm. Mevcut durumda tarayıcı desteği gelene kadar kullanılabilir.

İşin geçmişi uzun hikaye okumak isteyen için kaynaklardaki https://www.ctrl.blog/entry/text-wrap-balance.html makalesine göz atabilirsiniz. Özetlersem; Adobe bir algoritma geliştiriyor, sonra New York Times’ın daha basit bir algoritma üretiyor. En son gördüğüm kadar Knuth-Plass‘ın algoritmasının daha iyi olduğu yazılıyor.

Tarayıcılar başta bu hesabın maliyetinden kaçınıyor ve kapsayıcı genişliğine kadar sığan kelimeleri sıralayıp sığmadığı yerden itibaren aşağı atıyor. (Bu şu anda text-wrap: auto davranışı) Tarayıcılar bu konuya eğiliyor ve text-wrap: balance; tanımı ortaya çıkıyor.

Yukarıdaki örnekte görüldüğü gibi eğer tarayıcınız destekliyorsa fark açık. Uygulamalarda ortalı başlıklarda güzel sonuçlar veriyor. Sola yaslı başlıklarda sağ taraf çok boş kalıyor bence çok hoş durmuyor.

6 satırlık bir kısıtlama var. En fazla 6 satıra kadar olan metinlerde çalışıyor. Bu sınırdan dolayı sadece başlıklarda kullanmak öneriliyor.

Başlıklar için ideal bir çözüm. Peki normal metinlerde nasıl bir çözüm olacak? Burada Chrome ekibinden bir çözüm önerisi olarak yeni bir tanım geldi.

text-wrap: pretty

Chrome ekibi text-wrap: pretty tanımını çıkardı. Çıkardı diyorum çünkü fırından yeni çıktı. Yazıyı yazdığımda Chrome 117 ile birlikte çıkan özellikler arasında. Bu özellikte aşağı kayan bir kelime sorunlarını çözüyor. Aşağıda bir kelime kaldığı durumlarda iki veya daha fazla kelime kalmasını sağlıyor.

text-wrap balance pretty Yukarıdaki örnekte normalde “çözüm” kelimesi aşağıda kalırken pretty tanımınlandığında “pratik çözüm” alt satıra atılarak bir denge sağlanmış.

Bu öğrendiklerimizden sonra aşağıdaki gibi kod önerisi mantıklı görünüyor.

* {
	text-wrap: pretty 
}

h1, h2, h3 {
	text-wrap: balance; 
}

Kaynak: https://x.com/belldotbz/status/1671545872838979586?s=20

Bu tanımların bize kazandırdıklarını sıralarsak;

  • Daha okunabilir başlıklar ve metinler oluşturmamızı sağlıyor.
  • Esnek yapılarda(responsive) metinlerimiz daha uyumlu davranmasını sağlıyor.
  • Bunu sadece bir satır CSS kodu ile yapma kolaylığını bize sunuyor

Bu konu için her ne kadar çözümler çıksa da tam net çözüm için biraz daha geliştirme gerekiyor. Tarayıcıların geliştirmelerini bekleyip göreceğiz.

Kalın sağlıcakla.

Kaynaklar

CSS’de en çok ihtiyaç duyduğumuz özelliklerden birisiydi ebeveyn (parent) seçicisi. Bir ögenin içindeki elemana olup bitene göre CSS tanımı yapma isteği uzun süredir beklenen bir özellikti. Daha önceleri şöyle bir savunma vardı: Tarayıcılar CSS’i yorumlarken dokümanı aşağı yönlü yorumluyor, bundan ötürü bir elemanın yukarı yönlü elemanını seçmesi için tüm ebeveynlere erişmesi gibi durumlar söz konusudur ve bu performans açısından sıkıntılara neden olur. Tabi tarayıcılar son yıllarda ciddi gelişim gösterdi ve bu kabulleri de aşacak çözümleri sunmaya başladılar.

Ebeveyn seçicisi aslında çoğu zaman ihtiyacımız olan bir seçici olmasa da lazım olduğunda ‘ah be olsaydı ne güzel olurdu’ diye içimizden geçirdiğimiz bir seçici.

Nasıl kullanılır?

:has() ebeveyn seçicisi nasıl kullanılır? Örnekle anlaşılması daha kolay olacak.

// cocuklu aile
<div class="aile">
	<div>
		<div class="cocuk"></div>
	</div>
</div>

// cocuksuz aile
<div class="aile"></div>

Yukarıdaki kodda çocuklu ailelere özel kampanya yapmak istersek :)

.aile:has(.cocuk) {
	animation: partiZamani 21s linear;
}

Yukarıdaki kodda hedef .aile elemanı koşul ise .cocukvar mı? yok mu? Koşulun gerçekleştiği durumda tanım uygulanacak.

Tablo örneği

:has() seçicisini duyalı çok oluyor ancak uygulama imkanı yakın zamanda oldu. Aşağıdaki örnekte gördüğünüze benzer bir tablo ihtiyacımız oldu. Burada javascript ile seçim yapıldığında o tablo satırına bir css sınıfı tanımlayarak olabilirdi. Tabi bir işi CSS ile yapmak daha kolay ve mantıklı.

Kodun can alıcı noktası

tbody tr:has(input:checked) td {
  background: #636363;
  color: #fff;
}

Burada input işaretlenmiş tablo satırına tanım yaparak ihtiyacımızı karşıladık.

<figure> örneği

:has() seçicisini anlatırken verilen en popüler örnek: Bir <figure> elemanımızın olduğunu düşünelim. Bu elemanın bazen sadece resim içerirken bazen resim ve <figcaption> içeren çeşitlerinin olduğu durumlar var. Biz <figcaption> olduğu durumlar için. stil tanımlaması yapmak istesek.

figure:has(figcaption) {
  background: white;
  padding: 10px;
}

Kodu ile <figcaption> içeriği olan <figure> elemanına beyaz ardalan ve padding veriyoruz.

Form doğrulama örneği

Bir diğer popüler örnekte form doğrulam için :has() seçicisinden yararlanma örnekleri. Form elemanlarının doğrulaması için CSS sözde sınıflarını :invalid ve :valid kullanıyoruz ancak bu seçicileri kullanarak üstündeki ve öncesindeki elemanlara erişemediğimiz için sorun yaşıyorduk. :has seçicisi burada yardımımıza koştu.

Burada daha önce :focus-within tanımı yazısındaki formu alalım ve buraya e-posta alanı ekleyelim. E-posta kontrolü sonucu hatalı ise farklı bg ve etiketin başına x işareti koyalım.

Burada dikkat etmemiz gereken kısım kodun sonu

label:has(+ input:invalid)::before {
  content: '✖ ';
  color: #ff0024;
}

Hatalı input öncesinde gelenlabel elemanına hata durumunda x işareti ekliyoruz.

Not: Ebeveyn seçicisi sadece üst elemana değil daha önce erişemediğimiz aynı seviye önceki kardeş seçiciye de erişme imkanı sağlıyor.

Bir diğer kod

form:has(input:invalid)::after {
  box-shadow: inset 0 0 60px whitesmoke, inset 20px 0 80px #ff0024, inset -20px 0 80px #ff8f00, inset 20px 0 300px #ff0058, inset -20px 0 300px #ffc200, 0 0 50px #fff, -10px 0 80px #ff004a, 10px 0 80px #ff5b00;
}

Hatalı input’un ebeveyni olan form elemanının ardalanına kırmızı tonlu bir ardalan tanımlıyoruz.

Izgara (grid) örneği

Grid özelliği tanımlanan bir elemanın birincil derecedeki tüm elemanları grid ögesi olur. Grid ögelerinin davranış ve durumuna göre kapsayıcı gride tanım yapmak :has() seçicisi çıkana kadar CSS ile yapmak imkansızdı.

:nth-child ve :nth-last-child sözde sınıfları yardımıyla ve de :has() seçicisinin gücüyle bir grid içeriğinde 2 adet eleman varsa ona göre kod, 3 tane eleman varsa ona göre kod yazabiliyoruz artık.

.grid:has(:nth-child(2):last-child) {
  grid-template-columns: 1fr 1fr;
}

İçinde iki adet öge bulunan bir kapsayıcı gridi yukarıdaki şekilde yakalayıp iki kolonlu bir yapı kurabiliriz. Aynı şekilde

.grid:has(:nth-child(3):last-child) {
  grid-template-columns: 1fr 1fr 1fr;
}

İçinde üç adet öge bulunan kapsayıcı elemana tanım yapabiliriz.

Dört ve fazlası için de

.grid:has(:nth-child(n+4)) {
  grid-template-columns: repeat(4, 1fr);
}

Gerçekten hayat kurtaracak özellik.

Örnekleri çoğaltmak gayet mümkün. Kaynakların altında farklı tip örnekleri paylaşıyorum. Bu örneklere bakarak ufkumuz açılıyor.

Sonuç

Tarayıcı desteği konusunda Firefox hariç tüm tarayıcıların desteği var. Firefox’un çalışmaları var ama henüz tam destek gelmedi. Bu sene sonuna kadar gelmesini bekliyorum.

CSS’in son senelerdeki gelişmelerini heyecanla takip ediyorum. Bayram çocuğu gibi mutlu hissettiriyor. :)

Kalın sağlıcakla.

Kaynaklar

Örnekler

Bir önceki yazımdan CSS iç içe (nesting) yazım sonra ilk akla gelen sorulardan bir tanesi acaba SASS ile yolları ayırma vakti geldi mi?

Yazı genelinde SASS olarak belirteceğim ancak benzer şeyler diğer CSS önişlemcileri (LESS, Stylus, PostCSS) için de geçerli. PostCSS belki bunlardan ayrı tutulabilir. PostCSS modüler olarak sadece istediğiniz özelliği kullanma imkanı sağlıyor.

CSS önişlemcilerinin bizlere sağladığı avantajları sıralarsak

  • Değişkenler: Değişkenlerden daha yetenekli Custom Properties CSS’e geldi. CSS Değişkenleri (Custom Properties)
  • İç içe yazım avantajı: Bir iki ufak dezavantajı olsa da avantajları ile CSS’e iç içe yazım geldi. CSS iç içe (nesting) yazım
  • Mixins ve placeholder: Yeterli olmasa da aşağıda bahsettiğim bir alternatif çözüm var.
  • Renk çözümleri: Yeni renk tanımı ve fonksiyonlarıyla bu özellikler CSS’e de geldi/geliyor. color-mix(), lch()
  • Matematiksel işlemler: Tümü olmasa da büyük çoğunluğu CSS’e de geldi. calc(), clamp(), min(), max(), vd.
  • Döngüler, koşul kullanımı ve map.get: Şuanlık eksik.

Mixin için alternatif çözüm Chris Coyier attığı örnek ile ufkumuzu açtı.

SASS ile aradaki farklar

SASS ile alıştığımız kullanımdan farklılıklar. Aradaki farkları bilirsek geçişlerde nasıl bir yol izlememiz gerektiğine daha doğru karar veririz.

1. HTML elementleri & ile kullanmak

HTML elementlerini iç içe kullanırken &kullanmak gerekiyor. Firefox’un da öncü olduğu yeni standartlar ile bu fark ortadan kalkacak.

2. BEM desteği

BEM gibi yapılarda kullanmaya alışık olduğumuz &__ gibi yapıları birleştirme desteği yok.

3. Etkinlik (Specifity) sorunu

CSS iç içe yazımının SASS’a göre bir başka farkı, iç içe kullanılan seçiçileri :is() ile sarması. Sass ise bu seçicileri kopyalayıp yapıştırılmış gibi ayrı ayrı kullanır.

4. Çoklu satır yorum

Önceki makaleyi yazdıktan sonra bir tane daha fark buldum SASS ile çoklu satır yorum yazılabilirken CSS’de tek satır yorum yazıla biliyor.

5. import

CSS’de import var ancak asenkron çalışmadığı için çok tercih edilmiyor. Ancak biz bu dosyaları genelde webpack, vite gibi araçlarla kullandığımız için çok aramıyoruz ancak böyle bir araç ile kullanmayanlar için sorun olabilir orada da ESBuild ile bir çözüm olduğundan bahsediliyor.

Sonuç

Genel hatlarıyla CSS önişlemcilerin (SASS, LESS, Stylus, PostCSS) sağladığı bir çok avantaj CSS’de bulunuyor artık. Ben yazdığım SASS kodlarını inceledim büyük çoğunluğunda değişken, iç içe tanım, matematiksel işlemler yer alıyor. mixin, for, if else ve map-get gibi kullanımlara çok nadiren başvuruyoruz.

Tabi burada mevcut projelerimizde SASS’dan CSS’e geçmenin bir maliyeti olacağını unutmayalım. Yukarıda yazdığım SASS ile farklar kısmındaki değişiklikleri tek tek düzenlemek gibi bir iş çıkacaktır.

Daha önce jQuery’nin sonu mu geldi? yazısında da bahsettiğim gibi teknolojilerin / araçların savunucusu olmayın bu araçlar sizin işlerinizi kolaylaştırmak için var. İşinizi gördüğü müddetçe kullanın, ihtiyaç kalmadığında ise bırakmasını da bilin.

SASS’ın bırakılması için erken bence iç içe kullanımın tüm tarayıcılarda tam desteği 4-5 ay alacaktır. O zaman değerlendirilebilir.

Kaynaklar