HTML En İyi Uygulamaları
Sağlam HTML, her harika web sitesinin temelidir. Bu ipuçları, tarayıcıların ve ekran okuyucuların sevdiği semantik, sağlam ve geleceğe dönük biçimlendirme yazmanıza yardımcı olur.
<img> öğelerinde açık width ve height nitelikleri belirtmek, tarayıcının görsel yüklenmeden önce doğru alanı ayırmasını sağlayarak Google'ın Temel Web Verileri'nden biri olan Kümülatif Düzen Kaymasını (CLS) ortadan kaldırır.
<!-- ❌ Kötü: tarayıcı görsel yüklenene kadar boyutu bilmez --> <img src="hero.jpg" alt="Kahraman görseli"> <!-- ✅ İyi: alan hemen ayrılır --> <img src="hero.jpg" alt="Kahraman görseli" width="1200" height="630" loading="lazy">
aspect-ratio: auto ile birleştirin; tarayıcı, CSS görseli yeniden boyutlandırsa bile doğru oranı otomatik olarak hesaplayacaktır.Düzgün iç içe geçmiş başlıklarla oluşturulmuş bir belge taslağı, hem arama motorlarının içerik hiyerarşinizi anlamasına hem de ekran okuyucu kullanıcılarının sayfada verimli bir şekilde gezinmesine yardımcı olur.
<h1>Sayfa Başlığı (sayfa başına bir tane)</h1> <h2>Ana Bölüm</h2> <h3>Alt bölüm</h3> <h3>Başka bir alt bölüm</h3> <h2>Başka Bir Ana Bölüm</h2>
target="_blank" ile bağlantıları yeni sekmede açarken, açılan sayfa window.opener aracılığıyla sayfanıza erişebilir. rel="noopener noreferrer" eklemek bu güvenlik açığını önler ve yönlendiren bilgisinin gönderilmesini de durdurur.
<!-- ❌ Savunmasız --> <a href="https://example.com" target="_blank">Ziyaret Et</a> <!-- ✅ Güvenli --> <a href="https://example.com" target="_blank" rel="noopener noreferrer">Ziyaret Et</a>
autocomplete niteliği, tarayıcılara ve parola yöneticilerine form alanlarını nasıl önceden dolduracaklarını söyler. Bu, mobil form tamamlama oranlarını önemli ölçüde artırır.
<input type="text" autocomplete="given-name"> <input type="email" autocomplete="email"> <input type="tel" autocomplete="tel"> <input type="password" autocomplete="current-password"> <input type="text" autocomplete="postal-code">
Open Graph meta etiketleri, sayfanız Facebook, LinkedIn ve Twitter/X gibi sosyal medya platformlarında paylaşıldığında nasıl görüneceğini kontrol eder. Bunlar olmadan, platformlar içeriği rastgele seçer.
<meta property="og:title" content="Sayfa Başlığı"> <meta property="og:description" content="Kısa açıklama"> <meta property="og:image" content="https://alanadiniz.com/og.jpg"> <meta property="og:url" content="https://alanadiniz.com/sayfa"> <meta property="og:type" content="website"> <!-- Twitter/X --> <meta name="twitter:card" content="summary_large_image">
CSS İpuçları ve Püf Noktaları
Modern CSS inanılmaz derecede güçlüdür. Bu ipuçları, size zaman kazandıracak ve stil sayfalarınızı temiz tutacak düzen, özel özellikler ve desenleri kapsar.
Konumlandırma hack'leriyle uğraşmayı bırakın. CSS Grid'in place-items kısayolu, içeriği iki satırda hem yatay hem de dikey olarak ortalar — calc yok, transform yok.
.her-seyi-ortala { display: grid; place-items: center; } /* Tam sayfa ortalama için de çalışır */ body { display: grid; place-items: center; min-height: 100vh; }
CSS özel özellikleri (değişkenler), tasarım belirteçlerinizi bir kez tanımlamanıza ve her yerde yeniden kullanmanıza olanak tanır. Ayrıca gerçek zamanlı olarak güncellenirler, bu da karanlık mod ve tema oluşturmayı önemsiz hale getirir.
:root { --color-primary: #6366f1; --color-bg: #ffffff; --radius-md: 12px; --spacing-md: 16px; } @media (prefers-color-scheme: dark) { :root { --color-bg: #0d1117; } } .btn { background: var(--color-primary); border-radius: var(--radius-md); padding: var(--spacing-md); }
clamp(min, tercih, maks), yazı tipi boyutlarının görünüm alanı genişliğiyle sorunsuz bir şekilde ölçeklenmesini sağlar — medya sorgusuna gerek yoktur. Orta değer genellikle bir vw birimidir.
/* clamp(minimum, tercih, maksimum) */ h1 { font-size: clamp(1.8rem, 5vw, 3.5rem); } p { font-size: clamp(0.9rem, 2vw, 1.1rem); line-height: 1.7; max-width: 65ch; /* optimum okuma genişliği */ }
Genel olarak yumuşak kaydırmayı etkinleştirin ve kaydırılan içeriğin üzerine sabit başlıkların binmemesini sağlamak için çapa hedeflerinde scroll-margin-top kullanın.
@media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } } /* Sabit başlık için ofset (örn. 70px yükseklik) */ [id] { scroll-margin-top: 90px; }
scroll-behavior: smooth özelliğini her zaman bir prefers-reduced-motion: no-preference medya sorgusu içine sarın — bazı kullanıcılar hareketli kaydırmadan hareket hastalığı yaşar.auto-fill + minmax() deseni, mevcut alana göre sütun sayısını otomatik olarak ayarlayan bir ızgara oluşturur — medya sorgusuna gerek yoktur.
.kart-izgarasi { display: grid; grid-template-columns: repeat( auto-fill, minmax(280px, 1fr) ); gap: 24px; } /* Mobilde 1 sütun → 2 → 3 → 4 otomatik olarak */
Genel olarak asla outline: none yapmayın — bu klavye gezintisini bozar. Odak halkalarını yalnızca klavye kullanıcıları için göstermek ve fare kullanıcıları için tasarımı temiz tutmak için :focus-visible kullanın.
/* ❌ Bunu asla yapmayın */ * { outline: none; } /* ✅ Fare için gizle, klavye için göster */ :focus:not(:focus-visible) { outline: none; } :focus-visible { outline: 2px solid #6366f1; outline-offset: 3px; border-radius: 4px; }
JavaScript İpuçları
Bu modern desenler ve tarayıcı API'leri ile daha temiz, daha performanslı JavaScript yazın.
Saniyede yüzlerce kez tetiklenen scroll olayını dinlemek yerine, yalnızca öğeler görünüm alanına girdiğinde veya çıktığında tepki vermek için IntersectionObserver API'sini kullanın.
const observer = new IntersectionObserver( (entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('visible'); observer.unobserve(entry.target); // izlemeyi durdur } }); }, { rootMargin: '0px 0px -50px 0px' } ); document.querySelectorAll('.animate-on-scroll') .forEach(el => observer.observe(el));
resize ve input gibi olaylar çok hızlı tetiklenir. Debouncing, kullanıcı etkileşimi durdurana kadar yürütmeyi geciktirerek gereksiz iş yapılmasını önler.
function debounce(fn, delay = 300) { let timer; return (...args) => { clearTimeout(timer); timer = setTimeout(() => fn(...args), delay); }; } // Kullanım window.addEventListener('resize', debounce(() => { recalculateLayout(); }, 200) );
Modern navigator.clipboard API'si promise tabanlıdır ve eski document.execCommand('copy') hack'inden çok daha temizdir.
async function copyToClipboard(text) { try { await navigator.clipboard.writeText(text); showToast('Kopyalandı!'); } catch (err) { console.error('Kopyalama başarısız:', err); } } // Kullanım document.querySelector('.copy-btn') .addEventListener('click', () => copyToClipboard('Kopyalanacak metin') );
localStorage, özel tarama modunda veya depolama dolduğunda hata verebilir. Her zaman bir try/catch yardımcısına sarın.
const storage = { get(key, fallback = null) { try { const item = localStorage.getItem(key); return item ? JSON.parse(item) : fallback; } catch { return fallback; } }, set(key, value) { try { localStorage.setItem(key, JSON.stringify(value)); return true; } catch { return false; } } }; storage.set('theme', 'dark'); const theme = storage.get('theme', 'light');
JavaScript ile yönlendirilen animasyonlar (örn. canvas, GSAP) için kullanıcının prefers-reduced-motion ayarını kontrol edin ve animasyonları buna göre basitleştirin veya devre dışı bırakın.
const prefersReduced = window .matchMedia('(prefers-reduced-motion: reduce)') .matches; if (!prefersReduced) { startAnimations(); } else { showStaticFallback(); }
Performans İpuçları
Hızlı web siteleri daha üst sıralarda yer alır, daha iyi dönüşüm sağlar ve kullanıcıları mutlu eder. Bu ipuçları, web performansı için en büyük kazanımları kapsar.
font-display: swap olmadan, tarayıcılar özel yazı tipi yüklenene kadar metni gizler (FOIT). Bununla birlikte, sistem yazı tipi hemen gösterilir, ardından değiştirilir — bu, En Büyük İçerikli Boyamayı (LCP) büyük ölçüde iyileştirir.
<!-- Adım 1: preconnect --> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <!-- Adım 2: URL'ye &display=swap ekleyin --> <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap" rel="stylesheet">
WebP ve AVIF görüntüleri, eşit kalitede JPEG ve PNG'lerden önemli ölçüde daha küçüktür. Eski tarayıcılar için JPEG yedeği ile modern formatları sunmak için <picture> öğesini kullanın.
<picture> <source srcset="hero.avif" type="image/avif"> <source srcset="hero.webp" type="image/webp"> <img src="hero.jpg" alt="Kahraman görseli" width="1200" height="630" loading="lazy"> </picture>
Normal <script> etiketleri HTML ayrıştırmasını engeller. defer, ayrıştırma tamamlandıktan sonra script'i (sırayla) çalıştırır. async, script'leri indirilir indirilmez (sıra garantisi olmadan) çalıştırır.
<!-- Oluşturmayı engeller ❌ --> <script src="app.js"></script> <!-- DOM'dan sonra sırayla çalışır ✅ (çoğu script için kullanın) --> <script src="app.js" defer></script> <!-- Hazır olduğunda hemen çalışır ✅ (analitik, reklamlar) --> <script src="analytics.js" async></script>
transform ve opacity'yi hareketlendirmeye bağlı kalın — düzen veya boyama tetiklemeden GPU birleştirici iş parçacığında çalışırlar. Yalnızca profil oluşturup gerçek bir fayda görürseniz will-change ekleyin.
/* ❌ Düzeni tetikler (maliyetli) */ .bad { transition: width 0.3s, top 0.3s; } /* ✅ GPU-birleştirilmiş (ucuz) */ .good { transition: transform 0.3s, opacity 0.3s; } /* İdareli kullanın, yalnızca karmaşık animasyonlardan önce */ .modal-enter { will-change: transform; } .modal-entered { will-change: auto; } /* sonra sıfırlayın */
Tarayıcıya kritik kaynakları CSS veya JS'de keşfedilmeden önce erken getirmesini söylemek için <link rel="preload"> kullanın. Kahraman görselleri, kritik yazı tipleri ve önemli script'ler için idealdir.
<!-- Kahraman görselini ön yükle (LCP öğesi) --> <link rel="preload" as="image" href="hero.webp" fetchpriority="high"> <!-- Kritik yazı tipini ön yükle --> <link rel="preload" as="font" href="font.woff2" type="font/woff2" crossorigin>
Erişilebilirlik İpuçları
Erişilebilirlik bir kontrol listesi değil, iyi tasarımdır. Bu ipuçları, sitelerinizi ekran okuyucu kullanıcıları ve klavye gezginleri dahil herkes için kullanılabilir hale getirmeye yardımcı olur.
Yalnızca simge içeren düğmeler, ekran okuyucuların duyuracağı görünür bir metne sahip değildir. Açıklayıcı bir etiket sağlamak için bir aria-label ekleyin.
<!-- ❌ Ekran okuyucu "düğme" der --> <button><i class="fa-solid fa-times"></i></button> <!-- ✅ Ekran okuyucu "İletişim kutusunu kapat" der --> <button aria-label="İletişim kutusunu kapat"> <i class="fa-solid fa-times" aria-hidden="true"></i> </button>
lang niteliği, ekran okuyuculara hangi dili kullanacaklarını söyler, CSS'te doğru tirelemeyi sağlar ve çeviri araçlarının içerik dilini tanımlamasına yardımcı olur. RTL dilleri için ayrıca dir="rtl" ekleyin.
<!-- İngilizce --> <html lang="en"> <!-- Arapça (RTL) --> <html lang="ar" dir="rtl"> <!-- Fransızca --> <html lang="fr">
WCAG 2.1 AA, normal metin için en az 4.5:1 ve büyük metin (18px+ kalın veya 24px+ normal) için 3:1 kontrast oranı gerektirir. Yayınlamadan önce bir kontrast denetleyicisi kullanın.
/* ❌ #6b7280 on #fff = 4.48:1 (küçük metin için AA'da başarısız) */ .muted { color: #6b7280; background: #fff; } /* ✅ #4b5563 on #fff = 7.0:1 (AA ve AAA'yı geçer) */ .muted { color: #4b5563; background: #fff; }
Bazen yalnızca ekran okuyucuların duyabileceği metne ihtiyaç duyarsınız — içeriğe atla bağlantısı veya görsel bir öğe için etiket gibi. .sr-only yardımcı sınıfı, metni erişilebilir tutarken görsel olarak gizler.
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; } <!-- Atla bağlantısı örneği --> <a href="#main" class="sr-only">İçeriğe atla</a>
Bir modal açıkken, klavye odağı bunun içinde sınırlandırılmalıdır. Aksi takdirde Tab, kaplamanın arkasındaki öğelere odaklanır — bu, klavye kullanıcıları için modalı kullanılamaz hale getirir.
function trapFocus(modal) { const focusable = modal.querySelectorAll( 'a, button, input, select, textarea, [tabindex]:not([tabindex="-1"])' ); const first = focusable[0]; const last = focusable[focusable.length - 1]; modal.addEventListener('keydown', e => { if (e.key !== 'Tab') return; if (e.shiftKey ? document.activeElement === first : document.activeElement === last) { e.preventDefault(); (e.shiftKey ? last : first).focus(); } }); first.focus(); }
Duyarlı ve Mobil İpuçları
Mobil trafik baskındır. Bu ipuçları, tasarımlarınızın 320px'lik bir telefondan 4K monitöre kadar her ekran boyutunda güzelce çalışmasını sağlar.
Viewport meta etiketi olmadan, mobil tarayıcılar ~980px masaüstü genişliğinde oluşturur ve ardından uzaklaştırır. Kullanıcı ölçeklendirmesine izin verin — bunu devre dışı bırakmak büyük bir erişilebilirlik engelidir ve tarayıcı yakınlaştırmasını bozar.
<!-- ❌ Kullanıcı yakınlaştırmasını devre dışı bırakır (erişilebilirlik ihlali) --> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"> <!-- ✅ Doğru: 5×'e kadar ölçeklendirmeye izin verir --> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=5">
Apple'ın İnsan Arayüzü Yönergeleri ve WCAG 2.5.5, minimum 44×44 CSS piksel dokunma hedefi önerir. Küçük hedefler kullanıcıları hayal kırıklığına uğratır ve yanlış dokunmalara yol açar. Görsel boyutu değiştirmeden tıklanabilir alanı padding veya sözde öğeler kullanarak genişletebilirsiniz.
/* Görsel değişiklik olmadan dokunma alanını genişlet */ .icon-btn { position: relative; width: 24px; height: 24px; } .icon-btn::before { content: ''; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); min-width: 44px; min-height: 44px; }
margin-inline-start gibi mantıksal CSS özellikleri, margin-left yerine belgenin yazma moduna göre yönü otomatik olarak çevirir — RTL desteğini neredeyse zahmetsiz hale getirir.
/* Fiziksel (RTL için çevrilmez) */ .icon { margin-right: 8px; } /* Mantıksal (RTL'de otomatik olarak çevrilir) */ .icon { margin-inline-end: 8px; } /* Daha fazla mantıksal özellik örneği */ .card { padding-inline: 16px; /* sol + sağ */ padding-block: 12px; /* üst + alt */ border-start-start-radius: 12px; /* LTR'de sol-üst */ }
Mobil tarayıcılarda 100vh, tarayıcı kromunu (adres çubuğu) içerir ve çubuk göründüğünde taşmaya neden olur. Yeni dvh (dinamik görünüm alanı yüksekliği) birimi, tarayıcı kromu gösterildiğinde veya gizlendiğinde ayarlanır.
/* ❌ Tarayıcı kromu göründüğünde mobilde taşar */ .hero { height: 100vh; } /* ✅ Eski tarayıcılar için yedek ile */ .hero { height: 100vh; /* yedek */ height: 100dvh; /* dinamik görünüm alanı yüksekliği */ }
svh (küçük görünüm alanı, her zaman kromu hariç tutar) ve lvh (büyük görünüm alanı, her zaman krom alanını içerir).ResponsiveCheckTool'dan Daha Fazlası
Bu İpuçlarını Uygulamaya Koyun
Duyarlı değişikliklerinizin mobil, tablet ve masaüstünde nasıl göründüğünü anında, ücretsiz olarak, kayıt olmadan test edin.
Web Sitenizi Şimdi Test Edin