Günlük Utility Aileleri 2: Typography, Renk, Border, Shadow, Effect, Transform ve Form Utility'leri, typography ve forms Plugin'leri
Tailwind v4'te border ve ring varsayılan olarak currentColor kullanır, ring 1px'tir, scale/rotate/translate bağımsız transform property'lerine yazar ve @tailwindcss/forms eklendiğinde accent-* artık checkbox'ı boyamaz. Bookstore'un kitap kartında hover gölgesi ve kapak scale'i, stokta yok durumunda grayscale, checkout form'unda native kontrollerle forms plugin'ini ve CMS gövdesinde prose class'ını Playwright ile ölçüyoruz.
Sürüm notu: Bu yazıdaki örnekler Tailwind CSS 4.3.5, @tailwindcss/typography 0.5.20, @tailwindcss/forms 0.5.11, Node.js 24 ve Playwright 1.65 (Chromium 158) ile denenmiştir.
Önce Tahmin Et
Sitedeki serilerin ortak örnek uygulaması Bookstore (bir online kitapçı), checkout form'unda "Gift wrap" seçeneğini bir checkbox'la soruyor. Checkbox'ın rengi markanın indigo'su olsun diye accent-indigo-600 verdik:
<label class="flex items-center gap-2">
<input id="gift" type="checkbox" class="size-4 accent-indigo-600">
<span>Gift wrap</span>
</label>
Form'lar tarayıcıdan tarayıcıya farklı göründüğü için ekipten biri projeye @tailwindcss/forms plugin'ini ekledi; checkbox'ın class'larına dokunulmadı. Kullanıcı kutuyu işaretlediğinde kutunun içi hangi renkte olur?
Bu yazı serinin son yazısı ve günlük utility ailelerinin ikinci yarısını, görünüm tarafını anlatıyor: typography, renk ve opacity modifier'ı, gradient, border, shadow, ring ve outline, effect ve transform, form ve etkileşim utility'leri. Sonunda iki resmî plugin var: CMS'ten (içerik yönetim sistemi) gelen HTML için @tailwindcss/typography ve form'lar için @tailwindcss/forms. Önceki yazıdaki gibi her class'ın ürettiği CSS'e bakıyor, sonucu Playwright ile computed style'dan okuyoruz. Property'lerin kendisi CSS Property'leri: Uygulamalı Rehber serisinde.
Typography: Boyut, Satır Yüksekliği ve text-balance
node scripts/04-selectors.mjs 'text-sm' 'text-sm/6' 'leading-tight' 'text-balance'
text-sm
.text-sm {
font-size: var(--text-sm);
line-height: var(--tw-leading, var(--text-sm--line-height));
}
text-sm/6
.text-sm\/6 {
font-size: var(--text-sm);
line-height: calc(var(--spacing) * 6);
}
leading-tight
.leading-tight {
--tw-leading: var(--leading-tight);
line-height: var(--leading-tight);
}
text-balance
.text-balance {
text-wrap: balance;
}
text-* boyutları yalnız font-size değil, her boyuta eşlenmiş bir line-height da veriyor; theme yazısında --text-sm--line-height gibi çift tireli değişkenlerin bu eşleşmeyi taşıdığını görmüştük. leading-* bu değeri --tw-leading üzerinden eziyor, bu yüzden text-sm leading-tight class'larının sırası önemli değil. text-sm/6 ise ikisini tek class'ta veriyor ve satır yüksekliğini spacing ölçeğinden alıyor. tracking-* harf aralığını, font-* ağırlığı ve aileyi, tabular-nums ise rakamların eşit genişlikte olmasını sağlıyor; fiyat sütunlarında sayılar alt alta hizalı durur.
Kesme utility'lerini önceki yazıda kullandık: truncate tek satır, line-clamp-2 iki satır. Başlıklar için text-balance farklı bir şey yapıyor. Kurumsal Sipariş kampanyasının başlığını 320px'lik bir bantta iki kez yazdık, birinde text-balance var:
<h2 id="promo-plain" class="w-80 text-2xl font-bold">Institutional orders get a 10% discount</h2>
<h2 id="promo-balance" class="mt-4 w-80 text-2xl font-bold text-balance text-shadow-sm">Institutional orders get a 10% discount</h2>
npm run build:08
node scripts/08-visual.mjs
#promo-plain text-wrap wrap line widths 272px / 153px
#promo-balance text-wrap balance line widths 212px / 213px
Normal kırmada ilk satır doluyor, ikincide kısa bir kuyruk kalıyor; text-balance satırları eşit uzunluğa getirdi. Tarayıcılar bunu birkaç satırlık metinle sınırladığı için yalnız başlıkta kullan; paragraf için text-pretty daha ucuz bir kural uyguluyor ve asıl olarak son satırda tek kelime kalmasını önlemeye çalışıyor. Aynı başlıktaki text-shadow-sm v4.1'de geldi; renkli arka planın üstündeki beyaz metni biraz ayırıyor:
text-shadow-sm
.text-shadow-sm {
text-shadow: 0px 1px 0px var(--tw-text-shadow-color, rgb(0 0 0 / 0.075)), 0px 1px 1px var(--tw-text-shadow-color, rgb(0 0 0 / 0.075)), 0px 2px 2px var(--tw-text-shadow-color, rgb(0 0 0 / 0.075));
}
--tw-text-shadow-color değişkeni, text-shadow-indigo-900 gibi bir renk class'ının aynı gölgeyi yeniden tanımlamadan rengini değiştirmesini sağlıyor. Satır kırma ve metin gölgesinin CSS tarafı CSS Property'leri serisinin Metin Stilleri ve Satır Kırma ve Taşma yazılarında.
Renk, Opacity Modifier'ı ve Gradient'ler
Renk class'ları theme değişkenini okuyor (bg-indigo-600 → var(--color-indigo-600)). v3'teki bg-opacity-* kaldırıldı; şeffaflık rengin yanına / ile yazılıyor:
bg-indigo-600/80
.bg-indigo-600\/80 {
background-color: color-mix(in srgb, oklch(51.1% 0.262 276.966) 80%, transparent);
@supports (color: color-mix(in lab, red, red)) {
background-color: color-mix(in oklab, var(--color-indigo-600) 80%, transparent);
}
}
Opacity modifier'ı color-mix() ile rengi transparent'la karıştırıyor. İlk satır değişkeni değil rengin kendisini kullanan bir yedek; asıl kural @supports içinde. Stokta olmayan kitabın kapağındaki "Out of stock" şeridi bg-slate-900/70:
emma overlay background oklab(0.208 -0.00310889 -0.0418848 / 0.7)
opacity-*'tan farkı burada: opacity-70 element'i, içindeki beyaz metinle birlikte saydamlaştırırdı; modifier yalnız arka planı. Gradient'ler de yeni adlarla geliyor: bg-gradient-to-r yerine bg-linear-to-r, yanına bg-radial ve bg-conic:
bg-linear-to-r
.bg-linear-to-r {
--tw-gradient-position: to right;
@supports (background-image: linear-gradient(in lab, red, red)) {
--tw-gradient-position: to right in oklab;
}
background-image: linear-gradient(var(--tw-gradient-stops));
}
Kampanya bandı bg-linear-to-r from-indigo-600 to-sky-500. Destekleyen tarayıcıda geçiş oklab uzayında hesaplanıyor; sRGB'de iki doygun renk arasında ortada beliren soluk, grimsi ton bu yüzden daha az görülüyor. bg-linear-45 gibi açılar ve /oklch gibi bir interpolasyon modifier'ı da yazılabiliyor. v4.1 ile gelen mask-* utility'leri aynı gradient mantığını maskeye uyguluyor: kitap kartındaki kısa tanıtım metni max-h-16 overflow-hidden mask-b-from-50% ile alt yarısında silikleşerek bitiyor. Gradient'lerin ve maskenin ayrıntısı CSS Property'leri serisinin Background ve Gradient'ler ile clip-path, mask ve shape-outside yazılarında.
Border, Shadow, Ring ve Outline
Bu ailede v3'ten gelen alışkanlıkların en çok yanıldığı yer varsayılanlar. Üç element'i ölçtük:
<p id="border-default" class="border p-2 text-slate-600">Paperback</p>
<p id="ring-default" class="ring p-2 text-indigo-600">Hardcover</p>
<button id="btn-hidden" type="button" class="rounded bg-white px-3 py-1 outline-hidden">outline-hidden</button>
border color oklch(0.446 0.043 257.281) border-color oklch(0.446 0.043 257.281) width 1px
ring box-shadow oklch(0.511 0.262 276.966) 0px 0px 0px 1px
forced-colors none outline-none: none outline-hidden: none
forced-colors active outline-none: none outline-hidden: solid 2px
border renk vermiyor; Preflight kenarlık rengini ayarlamadığı için currentColor kullanılıyor ve kenarlık metinle aynı slate-600 oluyor. v3'te varsayılan gray-200'dü. ring 1px ve yine currentColor; v3'teki 3px mavi halka için artık ring-3 ring-blue-500 yazmak gerekiyor. Ring'in box-shadow ile çizildiğini de unutma: element'te bir shadow-* varsa ikisi aynı property'de katman olarak birleşiyor, birbirini ezmiyor.
Outline satırları önemli. outline-none gerçekten outline-style: none veriyor. outline-hidden normal ekranda aynı görünüyor, ama Windows'un yüksek kontrast modu gibi forced colors modunda 2px'lik bir outline'a dönüşüyor; Playwright'ta forcedColors: "active" ile bunu gördük. Focus halkasını kendi stilinle değiştiriyorsan outline-hidden kullan; yüksek kontrast kullanan biri focus'u yine görür.
Shadow ölçeği v4'te bir kademe kaydı: v3'ün shadow-sm'i artık shadow-xs, v3'ün shadow'u shadow-sm; rounded ve blur için de aynısı geçerli. Bakım yazısında bunu upgrade aracıyla ölçmüştük. inset-shadow-* iç gölge için ayrı bir aile ve dış gölgeyle aynı element'te birlikte kullanılabiliyor. Border, gölge ve focus halkasının CSS tarafı CSS Property'leri serisinin Border, border-radius, outline ve box-shadow yazısında.
Effect ve Transform: Kitap Kartı ve Stokta Yok Durumu
Katalogdaki kart, üzerine gelinince gölgesini büyütüyor ve kapağı hafifçe yakınlaştırıyor. Stokta olmayan kitapta kapak gri ve soluk:
<article id="card-dune" class="group overflow-hidden rounded-lg bg-white shadow-sm transition-shadow duration-300 hover:shadow-lg">
<div class="overflow-hidden">
<div class="aspect-2/3 bg-amber-200 transition-transform duration-300 group-hover:scale-105 motion-reduce:transition-none"></div>
</div>
...
</article>
<article id="card-emma" data-stock="out" class="group overflow-hidden rounded-lg bg-white shadow-sm">
<div class="relative overflow-hidden">
<div class="aspect-2/3 bg-sky-200 group-data-[stock=out]:opacity-60 group-data-[stock=out]:grayscale"></div>
<span class="absolute inset-x-0 bottom-0 bg-slate-900/70 py-1 text-center text-sm text-white">Out of stock</span>
</div>
...
</article>
dune before hover shadow rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(0, 0, 0, 0.1) 0px 1px 2px -1px cover scale none
dune after hover shadow rgba(0, 0, 0, 0.1) 0px 10px 15px -3px, rgba(0, 0, 0, 0.1) 0px 4px 6px -4px cover scale 1.05
emma cover filter grayscale(1) opacity 0.6
reduced motion cover transition-property none
Stok durumu template'te bir class olarak değil, data-stock="out" olarak duruyor; variant yazısındaki group-data-[...] ile kapak bu attribute'a göre griye dönüyor. Kapaktaki overflow-hidden sarmalayıcı, büyüyen kapağın kartın dışına taşmasını engelliyor.
Ölçümde scale satırı dikkat çekiyor: değer transform değil scale property'sinde. v4'te scale-*, rotate-* ve translate-* bağımsız transform property'lerine yazıyor:
scale-105
.scale-105 {
--tw-scale-x: 105%;
--tw-scale-y: 105%;
--tw-scale-z: 105%;
scale: var(--tw-scale-x) var(--tw-scale-y);
}
rotate-y-12
.rotate-y-12 {
--tw-rotate-y: rotateY(12deg);
transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
}
Bunun pratik sonucu, transition-transform'un artık transform, translate, scale, rotate listesini kapsaması ve kendi yazdığın bir transform kuralının scale-105'i ezmemesi. 3D utility'leri (rotate-x-*, rotate-y-*, perspective-*, transform-3d) ise transform property'sini kullanıyor; kapağı hafifçe çeviren bir "kitap sırtı" efektinde derinliği ebeveyndeki perspective-midrange gibi bir utility veriyor. Transform'ların ayrıntısı CSS Property'leri serisinin Transform'lar yazısında, filter ve backdrop-filter ise filter, backdrop-filter ve Blend Mode'lar yazısında.
motion-reduce:transition-none, işletim sisteminde animasyonları azalt ayarı açık olan kullanıcıda geçişi kapatıyor; ölçümde transition-property none. Kapak yine büyüyor, yalnız animasyonsuz. Animasyonu yalnız istenen yerde açmak için tersini de yazabilirsin: motion-safe:transition-transform.
Form ve Etkileşim Utility'leri: Checkout
Checkout form'unu önce plugin'siz kurduk:
<input id="email" type="email" placeholder="ada@example.com" class="mt-1 block w-full rounded-md border border-slate-300 px-3 py-2 caret-indigo-600 placeholder:text-slate-400 focus-visible:outline-2 focus-visible:outline-indigo-600">
<textarea id="note" rows="1" class="mt-1 block w-full field-sizing-content rounded-md border border-slate-300 px-3 py-2"></textarea>
<input id="gift" type="checkbox" class="size-4 accent-indigo-600">
<input id="po" type="file" accept="application/pdf" class="mt-1 block text-sm file:me-4 file:rounded file:border-0 file:bg-indigo-50 file:px-3 file:py-1 file:text-indigo-700">
<button id="place-order" type="submit" disabled class="cursor-pointer rounded bg-indigo-600 py-2 text-white select-none disabled:cursor-not-allowed disabled:opacity-50">Place order</button>
node scripts/08-forms.mjs
checkout.out.css
email appearance auto, font-size 16px, placeholder oklch(0.704 0.04 256.788)
select appearance auto, padding-right 12px, background-image none
checkbox appearance auto, 16px, background rgba(0, 0, 0, 0)
checked appearance auto, 16px, background rgba(0, 0, 0, 0), accent-color oklch(0.511 0.262 276.966)
invoice checked, background rgba(0, 0, 0, 0), accent-color oklch(0.511 0.262 276.966)
textarea field-sizing content, height 42px -> 90px
file button background oklch(0.962 0.018 272.314), margin-inline-end 16px
submit disabled, cursor not-allowed, opacity 0.5
Native kontrol için en ucuz yol accent-*: checkbox'ı tarayıcı çiziyor, işaretli hâlini markanın rengiyle boyuyor. caret-* imlecin, placeholder: placeholder'ın rengini veriyor. field-sizing-content teslimat notu alanını içeriğe göre büyütüyor: üç satır yazınca 42px'ten 90px'e çıktı, JavaScript yok. file: variant'ı ::file-selector-button pseudo-element'ini stilliyor; kurumsal müşterinin satın alma siparişi PDF'ini yüklediği butonu ayrı bir component yazmadan markaya uydurduk. Preflight, v4'te butonlara cursor: default veriyor; işaretçi isteniyorsa cursor-pointer açıkça yazılıyor, disabled hâlde cursor-not-allowed.
Etkileşim tarafındaki küçük utility'ler de doğrudan CSS: select-none (user-select: none), pointer-events-none, touch-pan-x (touch-action). Kapak carousel'i scroll snap ile:
<ul id="carousel" class="mt-8 flex w-80 snap-x snap-mandatory gap-4 overflow-x-auto scrollbar-thin">
<li class="h-36 w-24 shrink-0 snap-start rounded bg-amber-200"></li>
...
</ul>
carousel scrolled 70px, scrollLeft after snap 112px, scrollbar-width thin
70px kaydırınca liste ikinci kapağın başına (96px kapak + 16px gap) oturdu. scrollbar-thin v4.3 ile geldi. Bu property'lerin hepsi CSS Property'leri serisinin Form Kontrolleri ve Etkileşim Property'leri ile Overflow ve Scroll Davranışı yazılarında.
@tailwindcss/forms Ne Zaman Gerekir?
Plugin v4'te CSS dosyasından yükleniyor:
@import "tailwindcss" source(none);
@source "./checkout.html";
@plugin "@tailwindcss/forms";
Aynı form'u bu stylesheet'le ölçtük:
checkout-forms.out.css
email appearance none, font-size 16px, placeholder oklch(0.704 0.04 256.788)
select appearance none, padding-right 12px, background-image url("data:image/svg+xml,%3csvg
checkbox appearance none, 16px, background rgb(255, 255, 255)
checked appearance none, 16px, background oklch(0.546 0.245 262.881), accent-color oklch(0.511 0.262 276.966)
invoice checked, background oklch(0.511 0.262 276.966), accent-color oklch(0.511 0.262 276.966)
Textarea, dosya butonu ve submit satırları plugin'siz hâliyle aynı çıktığı için yalnız değişen satırları gösterdik. Tahmin sorusunun cevabı checked satırında: işaretli kutu oklch(0.546 0.245 262.881), yani plugin'in varsayılanı blue-600. Plugin appearance: none verip kutuyu kendisi çiziyor; tarayıcı artık çizmediği için accent-color hesaplanıyor ama hiçbir şeyi boyamıyor. Plugin işaretli kutunun arka planına currentColor veriyor, bu yüzden rengi text-indigo-600 ile değiştiriyorsun. invoice satırındaki kutuda iki class da var (text-indigo-600 accent-indigo-600) ve iki stylesheet'te de indigo; plugin'i kaldırmaya karar verirsen form bozulmaz.
İkinci ayrıntı select satırında. Plugin bir ok görseli ve onun için padding-right: 2.5rem ekliyor, ama ölçülen değer 12px: bizim px-3'ümüz kazandı. Plugin stilleri base layer'ına giriyor ve layer sırası sayesinde her utility onları eziyor. Bu genelde istediğin şey, ama select'te sağ boşluğu pe-10 ile geri vermezsen uzun bir seçenek metni okun altına girebilir.
Ne zaman gerekir? Tasarım, input'ların tarayıcılar arasında piksel düzeyinde aynı görünmesini istiyorsa ve checkbox/radio'nun kendisini çizmek gerekiyorsa plugin bu işi ucuza yapıyor. Markanın rengi ve birkaç kenarlık yetiyorsa accent-*, border-*, rounded-* ve appearance-none ile native kontroller yeterli; Bookstore'un checkout'u için ikinci yol yetti. Plugin'i global stil olmadan kullanmak da mümkün: @plugin "@tailwindcss/forms" { strategy: "class"; } yalnız form-input, form-select, form-checkbox gibi class'ları üretiyor; mevcut form'lara dokunmadan yeni ekranlarda kullanmak için uygun.
@tailwindcss/typography: CMS Gövdesi için prose
Serinin ilk yazısında CMS'ten gelen HTML'in Preflight'tan sonra stilsiz kaldığını görmüştük: gövdedeki element'lere class ekleyemiyorsun. typography plugin'i bunu tek class'la çözüyor:
@import "tailwindcss" source(none);
@source "./index.html";
@source "./cms.html";
@plugin "@tailwindcss/typography";
<article id="body-prose" class="prose prose-slate prose-a:text-indigo-600 dark:prose-invert">
<h2>Why Middlemarch still matters</h2>
<p>George Eliot's novel follows a whole town. Read it slowly, and read the <a href="#notes">notes</a>.</p>
<ul>
<li>Penguin Classics edition</li>
<li>Oxford World's Classics edition</li>
</ul>
<pre><code>isbn: 9780141439549</code></pre>
<div class="not-prose">
<button id="add-to-cart" type="button" class="rounded bg-indigo-600 px-3 py-1 text-white">Add to cart</button>
</div>
</article>
node scripts/08-prose.mjs
#body-plain
article max-width none, font-size 16px, line-height 24px
h2 font-size 16px, weight 400, margin-bottom 0px
ul list-style none, padding-inline-start 0px
a color rgb(0, 0, 0), text-decoration none
pre background rgba(0, 0, 0, 0), padding 0px
#body-prose
article max-width 655.078px, font-size 16px, line-height 28px
h2 font-size 24px, weight 700, margin-bottom 24px
ul list-style disc, padding-inline-start 26px
a color oklch(0.511 0.262 276.966), text-decoration underline
pre background oklch(0.279 0.041 260.031), padding 12px 16px
not-prose button font-size 16px, margin-top 0px
dark scheme prose p color oklch(0.869 0.022 252.894), plain p color rgb(0, 0, 0)
Aynı HTML prose ile okunabilir bir makaleye döndü: başlık 24px ve kalın, liste madde işaretli, link altı çizili ve indigo, kod bloğu koyu zeminde, gövde 65ch genişlikte. prose-slate gri tonunu projenin paletine uyduruyor, prose-a: gibi element modifier'ları tek bir element türünü değiştiriyor (v4'te durum variant'ı sona yazılıyor: prose-a:hover:text-indigo-500). dark:prose-invert koyu temada metni açık renge çevirdi. Gövdenin içine bir component koyman gerekiyorsa not-prose onu plugin'in kurallarından çıkarıyor; sepete ekle butonu düz kaldı. Genişlik sınırı istemiyorsan max-w-none ekle.
Bedeli CSS boyutu. Aynı cms.html için minify edilmiş CSS plugin'siz 4.5 kB, plugin'le 19.8 kB (gzip ile 1.6 kB'tan 3.6 kB'a).
Bu sitenin blog gövdesi de CMS'ten geliyor; site plugin yerine elle yazılmış tek bir gövde class'ı kullanıyor, çünkü yazı tipi, başlık boşlukları ve kod blokları sitenin kendi tasarımına göre ayarlanmış. İki yol aynı fikre dayanıyor: gövdeyi tek class'ın altında element selector'larıyla stillemek. Hazır bir tipografi yetiyorsa plugin daha az kod; tasarım her ayrıntıyı belirliyorsa plugin'in varsayılanlarını tek tek ezmek yerine kendi class'ını yazmak daha kısa sürebilir.
Üretimde Dikkat
Görünüm utility'leri variant'larla en çok çoğalan aile: hover:, focus-visible:, dark: ve group-* aynı rengi dört kurala çevirir. CSS boyutunu izliyorsan artışı önce buralarda ara.
Opacity modifier'ı ve gradient'ler için Tailwind @supports yedeği üretiyor, ölçtüğümüz CSS'te bunu gördük. text-wrap: balance, field-sizing ve scrollbar-* gibi daha yeni property'ler için böyle bir yedek yok; compatibility sayfasının dediği gibi hedef tarayıcılardaki desteği ayrıca kontrol et. Bookstore'da bunlar zarar vermeden bozuluyor: başlık normal kırılır, teslimat notu alanı büyümez ama kullanılabilir kalır. İşlevin kaybolduğu bir yerde bunlara yaslanma.
Forced colors modunu ve animasyonları azalt ayarını test et. 08-visual.mjs'deki gibi Playwright'ta emulateMedia({ forcedColors: "active" }) ve reducedMotion: "reduce" ile iki satırlık bir kontrol, outline-none ve unutulmuş motion-reduce: class'larını yakalıyor.
Sık Düşülen Tuzaklar
İlki tahmindeki tuzak: @tailwindcss/forms ile accent-* kullanmak. Plugin kontrolü kendisi çizdiği için renk text-* ile veriliyor.
İkincisi v3 ezberi. shadow-sm yazıp v3'ün ince gölgesini, rounded yazıp v3'ün değerini, ring yazıp 3px mavi halkayı, border yazıp açık gri kenarlığı beklemek. v4'te dördü de farklı; bakım yazısındaki yeniden adlandırma tablosu ve bu yazıdaki ölçümler yan yana okununca fark net.
Üçüncüsü focus halkasını outline-none ile gizlemek. Normal ekranda outline-hidden ile aynı görünüyor, ama forced colors modunda focus tamamen kayboluyor.
Dördüncüsü opacity-* ile / modifier'ını karıştırmak. "Out of stock" şeridine opacity-70 verseydik beyaz metin de soluklaşırdı.
Beşincisi plugin ile utility'nin çakışmasını unutmak: forms plugin'inin select'e verdiği sağ boşluk, px-* yazdığın anda gidiyor.
Küçük Bir Deneme
★☆☆ 08/index.html'deki kampanya başlığını üç satıra çıkacak kadar uzat, npm run build:08 ve node scripts/08-visual.mjs çalıştır ve text-balance'ın satır genişliklerini nasıl dağıttığına bak.
★★☆ Checkout'taki select'e plugin'li hâlde pe-10 ekle ve 08-forms.mjs'i padding-right'ın 40px olduğunu gösterecek şekilde çalıştır. Sonra @plugin "@tailwindcss/forms" { strategy: "class"; } ile yeniden derle ve hangi kontrollerin görünümünün değiştiğini ölç.
★★★ cms.html'deki gövdeyi kendi @utility'n ya da @layer components içindeki bir class'la, plugin'siz stille (h2, ul, a ve pre yeterli). 08-prose.mjs'i bu class için genişlet ve CSS boyutunu plugin'li hâlle karşılaştır.
Seri burada bitiyor. Utility-first'ün neyi çözüp neye mal olduğundan başladık; kurulum, @theme ile token'lar, variant'lar, Angular ve ASP.NET Core entegrasyonu, bakım ve sürümler, son iki yazıda da her gün yazılan utility aileleri. Hepsinin ortak noktası, her class'ın arkasında okunabilir bir CSS satırı olması. Bir class'tan emin olmadığında 04-selectors.mjs gibi küçük bir script'le ürettiği CSS'e bak ve sonucu tarayıcıda ölç; Tailwind'i doğru kullanmanın en güvenilir yolu bu.