CSS Performance: Render Optimizasyonu

CSS Performance: Render Optimizasyonu
CSS, sayfanın görsel yapısını oluşturan temel bileşendir. Ancak yanlış yazılmış CSS, render engelleyici kaynaklara, gereksiz reflow/repaint döngülerine ve yavaş sayfa yüklemelerine yol açabilir. Bu rehberde Critical CSS, contain property, will-change, selector performansı ve kullanılmayan CSS temizleme gibi konuları ele alacağız.
1. Critical CSS: Render Engelini Kırmak
Tarayıcı, sayfayı render etmeden önce tüm CSS'i indirip parse etmek zorundadır. Büyük CSS dosyaları "render-blocking resource" olarak ilk içerik gösterimini (FCP/LCP) geciktirir.
/* Strateji: Critical CSS inline, geri kalanı async */
/* HTML'de critical CSS inline <head> içinde: */
<style>
/* Sadece above-the-fold (ilk ekran) içeriği için gerekli stiller */
:root { font-family: system-ui, sans-serif; }
body { margin: 0; }
.hero { /* ... */ }
.nav { /* ... */ }
</style>
/* Async CSS yükleme */
<link rel="preload" href="/styles/main.css" as="style"
>
<noscript><link rel="stylesheet" href="/styles/main.css"></noscript>
/* media attribute ile koşullu yükleme */
<link rel="stylesheet" href="/print.css" media="print">
<link rel="stylesheet" href="/wide.css" media="(min-width: 1024px)">
/* Next.js ile: _document.tsx */
/* Critical CSS otomatik extract edilir (Next.js bunu yerleşik yapar) */
/* Sass/PostCSS ile critical CSS extract */
/* critical npm paketi veya next-plugin-css-modules */
2. contain Property: İzole Render Bölgeleri
contain property, tarayıcıya bir elementin değişikliklerinin sayfa düzeninin geri kalanını etkilemediğini söyler. Bu bilgi ile tarayıcı gereksiz hesaplamalardan kaçınır.
/* contain değerleri */
.widget {
contain: strict; /* layout + style + paint + size */
contain: content; /* layout + style + paint (size hariç) */
contain: layout; /* Sadece layout izolasyonu */
contain: paint; /* Sadece paint izolasyonu */
contain: style; /* Sadece style izolasyonu */
contain: size; /* Boyut izolasyonu */
}
/* Pratik kullanım: Büyük listeler */
.list-item {
contain: content;
/* Bu eleman değişse bile tarayıcı */
/* listenin geri kalanını tekrar hesaplamaz */
}
/* Chat uygulaması — mesaj bileşeni */
.message {
contain: layout style;
/* Mesaj içindeki değişiklikler dışarıyı etkilemez */
}
/* Reklam/widget kutuları */
.ad-unit {
contain: strict;
width: 300px;
height: 250px;
/* Sabit boyut — reklam içeriği layout'u bozmaz */
}
/* content-visibility: auto — gelişmiş sayfa optimizasyonu */
.article-section {
content-visibility: auto;
contain-intrinsic-size: auto 800px; /* Tahmini yükseklik */
/*
Viewport dışındaki bölümleri render etme.
Scroll ettikçe render yap.
100.000 satırlık içerikte dramatik performans artışı sağlar.
*/
}
content-visibility: auto, tarayıcıya viewport dışındaki elementlerin render işlemini erteleme izni verir. Uzun sayfalar (haber siteleri, belgeler) için FCP ve LCP metriklerini önemli ölçüde iyileştirebilir.
3. will-change: GPU Aceleration
will-change property, tarayıcıya hangi CSS özelliğinin değişeceğini önceden bildirir. Tarayıcı bu elementi ayrı bir compositor layer'a taşıyarak animate etmeyi GPU'ya devreder.
/* Temel kullanım */
.animated-element {
will-change: transform; /* En sık kullanılan */
}
.fading-element {
will-change: opacity;
}
/* Yanlış kullanım — PERFORMANSI DÜŞÜRÜR */
* {
will-change: transform; /* ASLA yapmayin! */
}
.static-element {
will-change: all; /* "all" anlamsız ve zararlı */
}
/* DOĞRU: JavaScript ile dinamik uygulama */
const el = document.querySelector('.card');
el.addEventListener('mouseenter', () => {
el.style.willChange = 'transform';
});
el.addEventListener('animationend', () => {
el.style.willChange = 'auto'; /* Animasyon bitince temizle */
});
/* CSS ile: Hover başlamadan önce hazırla */
.card-container:hover .card {
will-change: transform;
}
.card {
transition: transform 0.3s ease;
}
.card-container:hover .card {
transform: translateY(-4px);
}
/* GPU layer oluşturmanın diğer yolları */
.layer {
transform: translateZ(0); /* Eski hack — will-change tercih edilmeli */
backface-visibility: hidden; /* 3D context oluşturur */
}
will-change uygulamak bellek kullanımını artırır ve performansı olumsuz etkiler. Yalnızca gerçekten animasyon yapacak elementlere, animasyon öncesinde uygulayın ve sonrasında kaldırın.
4. Selector Performansı
CSS selector'ları sağdan sola okunur. Karmaşık selector'lar özellikle büyük DOM ağaçlarında performansı etkileyebilir.
/* Performans sıralaması (hızlıdan yavaşa): */
/* 1. ID: #header */
/* 2. Class: .nav */
/* 3. Element: div */
/* 4. Adjacent: h1 + p */
/* 5. Child: ul > li */
/* 6. Descendant: div span */
/* 7. Universal: * */
/* 8. Attribute: [href] */
/* 9. Pseudo-class: :nth-child(2n+1) */
/* KÖTÜ: Aşırı nitelendi (over-qualified) */
body div#main ul.list li.item a.link { /* ... */ }
/* İYİ: Minimal selector */
.nav-link { /* ... */ }
/* KÖTÜ: Universal selector ile zincirleme */
div * { font-size: 1rem; }
/* İYİ: Doğrudan hedefle */
.container { font-size: 1rem; }
/* KÖTÜ: Aşırı derin nesting */
.page > .content > .sidebar > .widget > .widget-title { }
/* İYİ: BEM ile flat yapı */
.widget__title { }
/* Modern CSS: :is() ile tekrarı azalt ama performansi koru */
/* KÖTÜ: Her birini ayrı ayrı yaz */
h1 { margin-bottom: 1rem; }
h2 { margin-bottom: 1rem; }
h3 { margin-bottom: 1rem; }
/* İYİ: :is() kullan */
:is(h1, h2, h3) { margin-bottom: 1rem; }
5. Unused CSS Temizleme
Büyük projelerde zamanla birikmiş kullanılmayan CSS kuralları dosya boyutunu şişirir. Otomatik araçlarla bu kuralları tespit edip kaldırabilirsiniz.
/* PurgeCSS konfigürasyonu — postcss.config.js */
module.exports = {
plugins: [
require('@fullhuman/postcss-purgecss')({
content: [
'./src/**/*.{js,jsx,ts,tsx}',
'./public/**/*.html',
],
defaultExtractor: (content) =>
content.match(/[\w-/:]+(?<!:)/g) || [],
/* Dinamik class'ları koruma listesi */
safelist: [
/^data-/,
/^aria-/,
'active',
'open',
/^is-/,
/^has-/,
],
}),
/* CSS minification */
require('cssnano')({
preset: ['default', {
discardComments: { removeAll: true },
normalizeWhitespace: true,
}],
}),
],
};
/* Vite ile — vite.config.ts */
import { defineConfig } from 'vite';
import { PurgeCSS } from 'vite-plugin-purgecss';
export default defineConfig({
plugins: [
PurgeCSS({
content: ['./src/**/*.{ts,tsx,html}'],
}),
],
build: {
cssCodeSplit: true, /* Her chunk için ayrı CSS */
cssMinify: true,
},
});
6. Animasyon ve Reflow Optimizasyonu
/* Reflow tetikleyen özellikler (kaçının) */
/*
width, height, padding, margin, border,
top, left, right, bottom,
font-size, text-align, display, position
*/
/* Sadece paint (daha hızlı) */
/*
color, background-color, border-color,
box-shadow, outline
*/
/* Compositor'da (en hızlı) */
/*
transform, opacity
*/
/* Animasyon performans örneği */
/* KÖTÜ: Left/top ile konum animasyonu — reflow tetikler */
.bad-animation {
position: absolute;
left: 0;
animation: moveLeft 1s;
}
@keyframes moveLeft {
to { left: 200px; } /* Her frame'de reflow! */
}
/* İYİ: Transform ile — compositor'da çalışır */
.good-animation {
animation: moveRight 1s;
}
@keyframes moveRight {
from { transform: translateX(0); }
to { transform: translateX(200px); } /* GPU'da, reflow yok */
}
/* will-change + transform kombinasyonu */
.slide-in {
transform: translateX(-100%);
transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
will-change: transform;
}
.slide-in.visible {
transform: translateX(0);
}
/* Animation fill-mode ile yeniden hesaplama önleme */
.fade-in {
animation: fadeIn 0.5s ease forwards;
/* forwards: animasyon bitince son frame'de kal */
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
Sonuç
CSS performans optimizasyonu birçok katmanda yapılabilir: kritik CSS'i inline ederek render'ı hızlandırın, contain ve content-visibility ile gereksiz render işlemlerini kısıtlayın, will-change'i akıllıca kullanarak GPU acceleration'dan yararlanın, selector'ları basit tutarak parse süresini azaltın ve PurgeCSS gibi araçlarla kullanılmayan CSS'i temizleyin. Bu adımların her biri Core Web Vitals metriklerini — özellikle LCP ve CLS'i — olumlu yönde etkiler.