Bloga geri dön
Günümüzde kullanıcı arayüzü (UI) tasarımı ve stil oluşturma süreçleri hızla değişmekte ve gelişmektedir. Bu gelişmelerden biri de Tailwind CSS, "utility-first" felsefesiyle geleneksel CSS'in aksine, Tailwind CSS doğrudan HTML işaretlemesi içinde modern web tasarımları oluşturmaya olanak tanır.
Tailwind CSS, doğrudan HTML işaretlemelerine uygulanabilen, önceden tanımlanmış küçük ve tek amaçlı CSS sınıflarından oluşan bir "utility-first" CSS çatısıdır (framework). Geleneksel CSS'te bir tasarım için HTML kodları dışında CSS bölümü oluşturulur. Kullanımını daha iyi anlamak için bir navigasyon barını önce geleneksel CSS ile tasarlayalım:
nav{
height: 30px;
background-color: #261A0F;
}
nav ul{
margin: 0px;
padding: 0px;
list-style-type: none;
}
nav ul li {
float: left;
width: 160px;
text-align: center;
line-height: 30px;
}
nav ul li a {
color: #D9BBA0;
text-decoration: none;
font-size: 18px;
font-family: 'Times New Roman', Times, serif;
}
nav li a:hover {
background-color: #D9BBA0;
color:#261A0F;
border-radius: 20%;
padding: 5px;
box-sizing: content-box;
}
Ve CSS’e bağlı geleneksel HTML çağrısı:
<nav>
<ul>
<li><a href="">Anasayfa</a></li>
<li><a href="">Tarihçe</a></li>
<li><a href="">Eserler</a></li>
<li><a href="">Galeri</a></li>
<li><a href="">İletişim</a></li>
</ul>
</nav>
Tailwind CSS'te ise bir navbar HTML kodları içinde daha iyi bir işlevsellikle şöyle tasarlanabilir:
<div className="hidden sm:ml-auto py-8 sm:block">
<div className="flex space-x-4">
{navigation.map((item) => {
const isActive = item.href = = = '/'
? location.pathname = = = '/'
: location.pathname.startsWith(item.href);
return (
<Link
key={item.name}
to={item.href}
aria-current={isActive ? 'page' : undefined}
className={classNames(
isActive ? 'bg-sky-500 text-white' : 'text-sky-500 font-semibold hover:bg-sky-500/50 hover:text-white',
'rounded-md px-3 py-2 font-semibold',
)}
>
{item.name}
</Link>
);
})}
</div>
</div>
İlk bakışta daha uzun gibi görünen bu kodlarda hem HTML ve CSS bir arada kullanılarak barın tasarımına yer verilmiş hem de JavaScript mantığı (örneğin aktif linkin belirlenmesi) doğrudan ilgili elementin className özelliği içinde yönetilmiştir. Bu sayede, geleneksel CSS'te ayrı bir JavaScript dosyasında tanımlanması gereken dinamik stil değişiklikleri, doğrudan işaretleme içinde kontrol edilebilir hale gelmiştir.
Görüleceği üzere, Tailwind CSS'te her bir CSS özelliği için ayrı bir sınıf bulunur (bg-sky-500 arka plan rengi, text-white yazı rengi, py-2 dikey padding, hover:bg-sky-500/50 hover:bg-sky-500/50 hover arka plan rengi ve opaklığı vb.). Bu sınıflar doğrudan HTML elementine eklenerek stil oluşturulur.
Temelde CSS ile Tailwind’in farkı felsefelerinde gizlidir. Geleneksel CSS "ne" sorusunun cevabı iken Tailwind sınıfları "nasıl" sorusunun cevabıdır. Yani, CSS’te bir kart tasarlanırken sözel ifadeye çevirirsek “bu bir karttır ve 4 px, gri sınırları olmak, beyaz arka planlı olmak, sans font ailesinden metin barındırmak özelliklerine sahiptir” şeklinde tanımlanırken, Tailwind ile “bu, beyaz arka planlı, 4 birim dolgulu, yuvarlak köşeli, gölgeli bir karttır” tanımlaması yapılır. Dolayısıyla, ayrı bir yerde betimlemeye ihtiyaç duymaz. Buna artı olarak, tasarımcılar ve geliştiriciler arasında daha hızlı bir iletişim kurulabilir, çünkü herkes aynı "nasıl" dilini konuşur. Bir "kart" sınıfının ne anlama geldiği tartışması yerine, doğrudan "bu kartın gölgesi daha büyük olsun" diyebilir ve shadow-lg sınıfı eklenebilir.
Tailwind CSS'in sağladığı sınıfı doğrudan HTML'e yazma özelliğinin sunduğu temel avantajlar:
Bir .css dosyasına geçiş yapmaya gerek kalmadan prototipleme ve UI bileşenleri oluşturma süreçlerinde inanılmaz bir hız sağlar.
Tailwind, önceden tanımlanmış bir tasarım sistemi (renk paletleri, boşluk ölçekleri, yazı tipleri vb.) ile gelir. Bu, projedeki tüm stillerin tutarlı olmasını sağlar ve büyük ekiplerde, uzun sürece yayılan projelerde tasarım tutarsızlıklarını büyük ölçüde engeller. Projelerde margin-top: 15px; yazmak yerine, mt-4 (16px) gibi standart sınıfları kullanılması teşvik edilir.
Geleneksel CSS'te, global yapı sebebiyle, bir sınıfı değiştirildiğinde, bu değişikliğin uygulamanın başka yerlerinde beklenmedik yan etkilere yol açıp açmayacağını düşünmek gerekir. Tailwind CSS ise, bir elementin stili sadece o elementin class listesini belirtilerek etkilendiği için stilin kapsamının doğrudan elementin kendisiyle sınırlı kalmasını sağlar. Bir bileşen silindiğinde, ona ait tüm stiller de onunla birlikte gider, geride kullanılmayan CSS kalmaz.
Farklı IDE’lerde farklı çatılarla (React, Vue, Angular) ve şablon motorlarıyla (Blade) kullanılabilir. Aynı yardımcı programlar tekrar tekrar kullanılacaksa, bunlar bir bileşene veya şablon parçasına çıkartılarak tek bir yerde değişiklik yapabilir hale gelir. Ancak elbette proje büyüdükçe aynı stil kombinasyonları birçok farklı yerde tekrar kullanılacaksa, bu sınıfları yeniden kullanılabilir React bileşenlerine (veya diğer çatılardaki karşılıklarına) ayırmak, kod tekrarını daha da azaltır ve bakımı kolaylaştırır.
Tailwind CSS kendi sitesinde buton, kart, header gibi unsurlar için örnek tasarımlar ve şablonları kodlarıyla birlikte sunar. Kaynakça bölümünde resmi adresi vardır. Ayrıca geniş renk ve biçimlendirme sınıflarıyla büyük ölçüde kullanıcının kendi kodlarını yaratmasına sıklıkla ihtiyaç kalmaz. Bununla birlikte, renk kodları, boşluk ve yerleştirme tercihleri sınıflara manuel olarak da uygulanabilir.
Tailwind CSS, React gibi bileşen tabanlı kütüphanelerle mükemmel bir uyum içindedir. Her bir React bileşeninde, elementlere doğrudan Tailwind sınıfları uygulanarak stil oluşturulur.
İşte basit bir buton örneği:
<button
type="button"
className={`mt-4 w-full flex items-center justify-center rounded-md border border-transparent px-4 py-2 text-base font-medium text-white shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 mt-auto
${isProductFavorite ? 'bg-red-500 hover:bg-red-600' : 'bg-sky-500 hover:bg-sky-300'}`}
onClick={() => {
if (isProductFavorite) {
alert(`${product.name} already exists.`);
} else {
addFavorite(product);
}
}}
>
{isProductFavorite ? 'In Favorite List' : 'Add Favorite'}
</button>
Yukarıdaki örnekte sınıflar şu şekilde işler:
className => bu prop, butona uygulanacak CSS sınıflarını tanımlar.
mt-4 => margin-top: 16px (üstten boşluk bırakır)
w-full => width: 100% (kapsayıcısının tüm genişliğini kaplar)
flex => display: flex (içeriğini flexbox olarak düzenler)
items-center => align-items: center (flex öğelerini dikeyde ortalar)
justify-center => center (flex öğelerini yatayda ortalar)
rounded-md => border-radius: 6px (köşeleri hafifçe yuvarlar)
border-transparent => border-color: transparent (kenarlığı şeffaf yapar, böylece varsayılan kenarlık görünmez)
px-4 => yatayda 16 px dolgu (padding)
py-2 => dikeyde 8px dolgu
text-base => yazı boyutunu 16px olarak ayarlar
focus:outline-none => Odaklandığında tarayıcı tarafından eklenen varsayılan dış hattı kaldırır
focus:ring-2 => Odaklandığında 2px genişliğinde bir halka (ring) efekti ekler
Yaygın Tailwind Entegrasyonları
Yazının bu bölümüne Tailwind CSS ile yaygın olarak kullanılan iki build aracı Vite ve Zustand da kısaca bahsedilecek.
Fransızca “hızlı” anlamındaki kelimeden gelen Vite, modern web projeleri için daha hızlı ve daha yalın bir geliştirme deneyimi sağlamayı amaçlayan bir derleme aracıdır. Vite, modern bir tarayıcı kullanıldığını (JavaScript ve CSS özelliklerinin çoğunu destekleyen) varsayarak çalışır. Tailwind CSS ile birlikte kullanıldığında, geliştirme deneyimini daha da hızlandırır. Vite, Tailwind'i PostCSS aracılığıyla işler ve geliştirme sırasında anında JavaScript modüllerini güncelleyen bir yöntemle (Hot Module Replacement - HMR) sağlar. Üretim derlemesinde ise kullanılmayan CSS'i otomatik olarak kaldırarak optimize edilmiş bir çıktı sunar.
Zustand gibi durum yönetimi kütüphaneleri (Zustand zaten Almanca ‘durum’ demektir), geliştirilen uygulamanın verilerini merkezi bir yerde tutmayı sağlar. Global bir state yöneticisi olan Zustand, bileşen ağacından bağımsızdır. Zustand’da kancalara (hooks) bağlı kullanışlı bir API bulunur. React use ile başlayan isimlendirmelere dikkat ettiği için Zustand uyumlu çalışma sağlar. Tailwind CSS ile bu veriler kullanılarak bileşenlerin stili dinamik olarak değişebilir. Kavramsal açıdan Redux ile oldukça benzer olan Zustand, Redux, Valtio, Jotai, and Recoil gibi pek çok React için kullanılan durum yönetimi kütüphanelerinden biridir. Resmi sitesinden diğer durum yönetimi kütüphanelerine kıyasla kolaylaştırdığı uygulamaları ayrıntılı incelemek mümkündür. Hem kullanımını biraz anlamak için hem de yaygın olan Redux ile farkını biraz göstermek için bir örnek verelim:
Önce Zustand ile bir sayacı reducer kullanarak tanımlayalım:
import { create } from 'zustand'
type State = {
count: number
}
type Actions = {
increment: (qty: number) => void
decrement: (qty: number) => void
}
const useCountStore = create<State & Actions>((set) => ({
count: 0,
increment: (qty: number) => set((state) => ({ count: state.count + qty })),
decrement: (qty: number) => set((state) => ({ count: state.count - qty })),
}))
Redux ile:
import { createStore } from 'redux'
import { useSelector, useDispatch } from 'react-redux'
type State = {
count: number
}
type Action = {
type: 'increment' | 'decrement'
qty: number
}
const countReducer = (state: State, action: Action) => {
switch (action.type) {
case 'increment':
return { count: state.count + action.qty }
case 'decrement':
return { count: state.count - action.qty }
default:
return state
}
}
const countStore = createStore(countReducer)
Bu iki yapı temelde aynı “reducer” desenini kullanarak durum geçişlerini merkezi ve öngörülebilir hale getirir. Ancak belli başlı farkları var:
Redux daha katı, tek yönlü veri akışı sunarak büyük ve karmaşık uygulamalar için uygundur. Zustand ile tasarlanan ise minimalist, kanca-tabanlıdır. Kendi kancasıyla doğrudan duruma erişim sağlar. Ayrıca, Zustand, oluşturulan hook (useCountStore) aracılığıyla doğrudan erişim sağlar. Redux ise önce react-redux kütüphanesine erişerek dolaylı erişim sağlar. Reducer kullanımı Zustand'da isteğe bağlıdır, doğrudan eylemler de tanımlanabilir. Son olarak, Redux’ta asenkron eylemler için Redux Thunk veya Redux Saga gibi ara yazılımlara (middleware) gerekirken, Zustand bu tür ara yazılımlara ihtiyaç duymaz.
Sonuç
Geleneksel CSS tabanlı tasarımlar yerini farklı modern tasarım teknolojilerine bırakırken Tailwind CSS günümüzde kolay ve hızlı, modern web tasarımları için prototipleme, tutarlılık, bakım ve kullanım kolaylığı, tekrar kod kullanımının azaltılması ve hazır şablonlar gibi avantajlarıyla dikkat çekmektedir.
Kaynakça
https://tailwindcss.com/
https://tailwindcss.com/plus
https://vite.dev/guide/
https://zustand.docs.pmnd.rs/
https://github.com/BCemreD/ProductListingApp