Skip to content

Bölüm 2 / 20

HTML temelleri

Etiket, öznitelik, belge iskeleti, metin etiketleri.

15 dakikalık okuma

HTML bir programlama dili değildir; işaretleme dilidir. Yaptığı iş, metnin hangi parçasının başlık, hangisinin paragraf, hangisinin bağlantı olduğunu söylemektir. Kolay görünür ve gerçekten de yarım saatte "yazmaya" başlarsın; buna karşılık HTML'i doğru yazmak, tarayıcının hataları nasıl kurtardığını, hangi önceliklerle çalıştığını ve tek bir eksik özniteliğin sayfayı nasıl bozduğunu bilmeyi gerektirir. Bu ders sıfırdan başlar ama sözdiziminin ötesine geçer: uyumluluk modu, karakter kodlaması sırası, boş etiketler, kaçış kuralları ve tarayıcının kaynak koddan farklı bir DOM üretmesi.

01Ne öğreneceksin

  • HTML'in ne olduğu, ne olmadığı; belge iskeletinin her satırının işi
  • <!doctype html> eksikse ne olur — uyumluluk modu (quirks mode)
  • Karakter kodlamasının ilk 1024 bayt kuralı ve Türkçe karakter bozulmaları
  • Etiket, öznitelik, içerik modeli; boş (void) etiketler ve boole öznitelikler
  • Metin etiketleri ve anlam farkı: strong/b, em/i, pre, blockquote
  • Bağlantılar: göreli/mutlak yol, target="_blank" ve rel="noopener" tuzağı
  • Görseller: alt yazma kuralları, srcset, loading="lazy", boyut verip yerleşim kaymasını önlemek
  • Karakter kaçışı, &amp; ve innerHTML'in neden tehlikeli olduğu
  • Tarayıcının hata kurtarması: kaynak kod ≠ DOM ağacı
  • Doğrulama araçları ve HTML'i gerçekten okumayı öğrenmek

02HTML nedir

HTML (HyperText Markup Language) bir belgenin yapısını ve anlamını tanımlar. Görünüşü CSS, davranışı JavaScript belirler. Bu ayrım bir slogan değil, pratik bir karardır: aynı HTML'i farklı temalarla göstermek, ekran okuyucuya doğru bilgiyi vermek ve arama motorunun içeriği anlaması bu ayrıma dayanır.

En küçük geçerli belge şudur:

<!doctype html>
<html lang="tr">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Başvuru Listesi</title>
</head>
<body>
  <h1>Başvuru Listesi</h1>
  <p>Açık başvurular aşağıdadır.</p>
</body>
</html>

Bu yedi satırın her biri işe yarar:

SatırİşiYazılmazsa
<!doctype html>Tarayıcıyı standart moda alırUyumluluk moduna düşer — kutu modeli ve tablo hizalaması 1990'ların kurallarıyla çalışır
<html lang="tr">Belgenin diliEkran okuyucu yanlış aksanla okur, tarayıcı çeviri/heceleme kararlarını yanlış verir; erişilebilirlik denetimlerinde ilk düşen madde
<meta charset="utf-8">Bayt → karakter dönüşümüTürkçe karakterler bozulur (ÅŸ, ı)
<meta name="viewport">Mobilde gerçek genişliği kullanTelefon sayfayı 980 px varsayıp küçültür; duyarlı tasarımın hiçbiri çalışmaz
<title>Sekme adı, yer imi adı, arama sonucu başlığıErişilebilirlikte sayfa kimliği kaybolur

Uyumluluk modu hâlâ bilinmesi gereken bir konudur, çünkü eski kurumsal sayfaları devraldığında karşına çıkar. Standart modda width içeriğin genişliğidir; uyumluluk modunda dolgu ve kenarlık de dâhil edilir, yani bugün box-sizing: border-box diye açıkça istediğimiz davranış zorla dayatılır ve düzen beklenmedik biçimde kayar. Hangi modda olduğunu konsolda görebilirsin: document.compatMode standart modda "CSS1Compat", uyumluluk modunda "BackCompat" döner.

Kodlamanın ilk 1024 bayt kuralı: <meta charset> belgenin ilk 1024 baytı içinde bulunmak zorundadır; ayrıştırıcı orayı geçtikten sonra kodlamayı öğrenirse belgeyi baştan ayrıştırmak zorunda kalır. Bu yüzden <head>'in ilk satırı olur. Sıralama önemlidir: HTTP başlığındaki Content-Type: text/html; charset=..., belgedeki meta'dan önce gelir ve onu ezer. Türkçe karakter bozulmasında bakılacak sıra: (1) dosya gerçekten UTF-8 kaydedilmiş mi, (2) HTTP başlığı ne diyor, (3) meta etiketi var mı.

03Etiket, öznitelik, içerik modeli

Bir HTML ögesi üç parçadan oluşur:

<a href="/basvuru" class="dugme" data-izleme="ust-menu">Başvur</a>
└┬┘ └───────────────── öznitelikler ──────────────────┘└─┬──┘└┬┘
açılış etiketi                                        içerik  kapanış

Bilinmesi gereken üç kural vardır:

  • Boş (void) etiketler kapanmaz. <img>, <br>, <hr>, <input>, <meta>, <link>, <source>. <img /> yazmak HTML'de hata değildir ama gereksizdir; XHTML alışkanlığıdır (JSX'te ise zorunludur — 11. hatta göreceksin).
  • Boole öznitelikler değer almaz. disabled, checked, required, readonly, hidden. Öznitelik varsa doğrudur. disabled="false" yazmak alanı etkin yapmaz — hâlâ devre dışıdır. Kapatmanın tek yolu özniteliği silmektir.
  • İçerik modeli hangi ögenin içine hangisinin girebileceğini belirler. Örneğin <p> içine <div> giremez, <ul> doğrudan yalnız <li> alır, <a> içine başka bir <a> ya da <button> konmaz.

Öznitelik değerlerini her zaman tırnakla. Tırnaksız yazım bazı durumlarda geçerlidir ama değerde boşluk olduğu anda sessizce bozulur:

<div class=kirmizi kalin>   <!-- class="kirmizi", ayrıca "kalin" adında boş bir öznitelik -->
<div class="kirmizi kalin">  <!-- doğrusu -->

id belgede benzersiz olmalıdır; class tekrarlanabilir. id tekrarlanırsa getElementById ilkini döndürür, etiket–alan eşleşmeleri (3. ders) yanlış ögeye gider ve #hedef bağlantıları şaşar. Kendi verilerini işaretlemeye iliştirmek istiyorsan uydurma öznitelik icat etme; data-* kullan — geçerlidir ve JavaScript'ten element.dataset.izleme olarak okunur. Bu sitenin ders sayfalarındaki data-ders ve data-kok öznitelikleri tam olarak bu mekanizmadır.

Beyaz boşluk ve yorumlar

HTML'de art arda gelen boşluk, sekme ve satır sonu tek boşluğa indirgenir. Yani kaynak kodunu istediğin gibi girintileyebilirsin. Bunun iki istisnası vardır: <pre> içi (boşluklar korunur) ve white-space CSS özelliğiyle değiştirilen durumlar. Buna karşılık boşluk tamamen yok da sayılmaz — satır içi ögeler arasındaki satır sonu görünür bir boşluk üretir ve iki resim ya da iki inline-block kutu arasında açıklanamayan 4 px'lik aralık olarak karşına çıkar. Bu, flexbox'ın (9. ders) çözdüğü klasik sorunlardan biridir.

Yorum <!-- ... --> ile yazılır ve kaynak koda gönderilir; tarayıcıda görünmez ama herkes okuyabilir. Yorum içine parola, iç sunucu adı ya da "geçici olarak kapatıldı" diye bir yönetim adresi bırakmak, sızma testlerinde bulunan ilk şeylerdendir.

04Metin etiketleri ve anlam farkları

Görsel olarak aynı sonucu veren ama anlamı farklı etiketler HTML'in en çok yanlış kullanılan kısmıdır:

EtiketAnlamıNe zaman
<strong>Güçlü önem"Son başvuru tarihi 15 Eylül" — ekran okuyucu vurgular
<b>Anlamsal önem taşımayan kalınlıkAnahtar kelime, ürün adı; stil amaçlı
<em>Vurgu — cümlenin anlamını değiştirir"Formu bugün gönder"
<i>Farklı ses/terim; italikYabancı terim, teknik ad
<mark>İlgi nedeniyle işaretlenmişArama sonucunda eşleşen kelime
<small>Yan not, telif, yasal uyarı"Ücretler KDV hariçtir"
<del> / <ins>Silinmiş / eklenmiş içerikDeğişiklik gösterimi, eski fiyat
<code>Kod parçasıTek satırlık kod; <pre> ile birlikte blok
<abbr title>Kısaltmanın açılımıİlk geçtiği yerde
<time datetime>Makine okunur tarih<time datetime="2026-09-15">15 Eylül</time>

Pratik ölçüt: sesli okuyan biri bu kelimeyi vurgulamalı mı? Evetse strong/em, hayırsa b/i ya da doğrudan CSS. Görsel kalınlık istiyorsan zaten font-weight yazabilirsin; etiket seçimi anlamla ilgilidir.

Başlıklar: h1–h6

Başlıklar sayfanın içindekiler tablosudur. Ekran okuyucu kullanıcıları sayfayı çoğu zaman başlıktan başlığa atlayarak gezer; arama motorları da yapıyı buradan çıkarır. Üç kural:

  • Sayfada bir tane h1 bulunur ve sayfanın konusudur.
  • Seviye atlanmaz — h2'den sonra h4 gelmez.
  • Seviye büyüklük için seçilmez. Küçük görünmesini istiyorsan CSS ile küçült.

Bir dönem HTML5'in "belge ana hat algoritması" sayesinde her <section> içinde yeniden h1 kullanılabileceği söylendi. Bu algoritma hiçbir tarayıcıda uygulanmadı ve spesifikasyondan kaldırıldı. Bugün geçerli olan tek şey h1–h6 numaralarıdır — 5. derste bu konuya tekrar döneceğiz.

Blok ve satır içi

Etiketler kabaca ikiye ayrılır: blok ögeler kendi satırını kaplar (p, div, h1, ul, section); satır içi ögeler metnin akışında durur (a, span, strong, img, code). Bu ayrım aslında CSS'in display özelliğinin varsayılan değeridir ve değiştirilebilir; ama HTML'in içerik modeli buna göre yazılmıştır — blok bir ögeyi satır içi bir ögenin içine koymak çoğu durumda geçersizdir. Tek istisna: HTML5'te <a> blok içerik sarabilir; bir kartın tamamını bağlantı yapmak geçerlidir.

<br> yalnızca metnin kendisinin parçası olan satır sonları içindir: şiir, adres, marş sözü. Paragrafları ayırmak ya da boşluk bırakmak için <br><br> yazmak yanlıştır — bunun için ayrı <p>'ler ve CSS margin kullanılır.

05Bağlantılar

Web'i web yapan öge budur:

<a href="/basvuru/liste">Başvurular</a>              <!-- köke göre -->
<a href="detay.html">Detay</a>                      <!-- bulunduğun dizine göre -->
<a href="../index.html">Üst dizin</a>
<a href="https://ornek.gov.tr">Dış site</a>
<a href="#sonuclar">Sayfa içi hedef</a>
<a href="mailto:bilgi@ornek.gov.tr">E-posta</a>
<a href="tel:+902121234567">Telefon</a>
<a href="rapor.pdf" download>İndir</a>

Göreli yol bulunduğun belgenin konumuna göre çözülür; / ile başlayan yol her zaman sitenin kökünden başlar. Bu sitenin ders sayfalarındaki ../../styles.css yazımı, dersin iki dizin altta olmasındandır — bu yüzden dosyalar taşınırsa bağlantılar kırılır. Sabitlemek istersen <head> içinde <base href> kullanılabilir; ancak base sayfa içi #hedef bağlantılarını da etkilediği için sürprizlidir, tercih edilmez.

Yeni sekmede açma tuzağı. target="_blank" ile açılan sayfa, eski tarayıcılarda window.opener üzerinden seni yönlendirebilir — buna sekme ele geçirme (tabnabbing) denir. Modern tarayıcılar rel="noopener" davranışını varsayılan yaptı, ancak kurumsal ortamlarda eski tarayıcı ihtimali olduğu için hâlâ açıkça yazılır:

<a href="https://dis-site.com" target="_blank" rel="noopener noreferrer">
  Dış site <span aria-hidden="true">↗</span><span class="gizli"> (yeni sekmede açılır)</span>
</a>

noreferrer ayrıca Referer başlığını da gönderme der; iç adresini dışarı sızdırmamak için işe yarar. Erişilebilirlik tarafında ek bir kural vardır: bağlantının yeni sekmede açılacağı kullanıcıya söylenmelidir, çünkü geri düğmesinin çalışmaması ekran okuyucu kullanıcılarını şaşırtır.

Bağlantı metni kuralı: "tıklayınız", "buraya", "devamı" yazma. Ekran okuyucu kullanıcıları sayfadaki bağlantıları liste hâlinde gezebilir; bağlamdan koparıldığında metnin tek başına anlamlı olması gerekir. "Başvuru kılavuzunu indir (PDF, 1,2 MB)" iyi bir bağlantı metnidir — hedefi, biçimi ve boyutu söyler.

Son olarak düğme mi bağlantı mı ayrımı: bir yere götürüyorsa <a>, bir eylem yapıyorsa <button>. Bu, keyfi bir tercih değildir — bağlantılar Enter ile, düğmeler hem Enter hem Boşluk ile çalışır; bağlantılar yeni sekmede açılabilir, kopyalanabilir, arama motoru tarafından taranır. Eylemi <a href="#"> ile yapmak, kullanıcıyı sayfanın başına atan ve adres çubuğunu kirleten yaygın bir hatadır.

06Görseller

<img src="/gorsel/kampus.jpg"
     alt="Kampüsün havadan görünümü"
     width="1200" height="800"
     loading="lazy" decoding="async">
ÖznitelikNeden
altGörsel yüklenmezse ve ekran okuyucu için metin karşılığı. Zorunludur
width / heightTarayıcı en–boy oranını önceden bilir ve yerini ayırır — CLS'i düşürür. CSS ile width:100%; height:auto versen bile bu öznitelikleri yaz
loading="lazy"Ekran dışındaki görseller görünene yakın indirilir. İlk ekrandaki görsele koyma — LCP'yi geciktirir
decoding="async"Kod çözme işini ana iş parçacığından çıkarır
fetchpriority="high"Hero görselini erken çekmek için; ölçmeden kullanma

alt yazma kuralları — bu, mülakatta erişilebilirlik bilgisini ölçen klasik sorudur:

  • Görsel bilgi taşıyorsa: bilgiyi yaz. "Grafik" değil, "2025'te başvuru sayısı %18 arttı".
  • Görsel süsse: alt="" yaz (boş ama var). Ekran okuyucu onu tamamen atlar. Özniteliği hiç yazmazsan okuyucu çaresiz kalıp dosya adını okur.
  • Görsel bir bağlantının içindeyse: alt, bağlantının nereye gittiğini anlatır — "logo" değil, "Ana sayfa".
  • "…resmi", "…görseli" yazma; ekran okuyucu zaten "resim" der.

Duyarlı görsel için iki mekanizma vardır ve karıştırılırlar:

<!-- Aynı görselin farklı çözünürlükleri: tarayıcı seçer -->
<img src="foto-800.jpg"
     srcset="foto-400.jpg 400w, foto-800.jpg 800w, foto-1600.jpg 1600w"
     sizes="(max-width: 600px) 100vw, 50vw"
     alt="...">

<!-- Farklı biçim ya da farklı kırpma: sen seçersin -->
<picture>
  <source srcset="foto.avif" type="image/avif">
  <source srcset="foto.webp" type="image/webp">
  <img src="foto.jpg" alt="...">
</picture>

Kural: çözünürlük değişiyorsa srcset, içerik ya da biçim değişiyorsa <picture>. sizes yazmayı unutmak sık yapılan hatadır; tarayıcı o zaman görselin tam genişlikte olduğunu varsayar ve gereksiz büyük dosya indirir.

07Karakter kaçışı ve güvenlik

HTML'de üç karakter özeldir: <, > ve &. Metin olarak göstermek istiyorsan varlık (entity) yazımını kullanırsın:

KarakterVarlıkNot
<&lt;Zorunlu — yoksa etiket sanılır
>&gt;Çoğu yerde şart değil ama alışkanlık iyi
&&amp;URL'lerde de gerekir: ?a=1&amp;b=2
tırnak&quot;Öznitelik değeri içinde
bölünmez boşluk&nbsp;Satır sonu engeller — "15&nbsp;Eylül" ayrı satıra düşmez

Bu ders sayfasının kaynak kodunda gördüğün &lt;'lerin sebebi tam olarak budur: kod örneklerindeki HTML'i göstermek için kaçırmak zorundayız.

Ve asıl mesele: aynı kaçış kuralı, kullanıcıdan gelen veriyi sayfaya yazarken güvenlik sınırıdır. Kullanıcı adına "<script>…</script>" yazan biri, veri kaçırılmadan sayfaya konursa kodu senin sayfanda çalıştırır — buna XSS denir. JavaScript tarafında ayrım tek satırdır:

const ad = kullanicidanGelen;

el.innerHTML = ad;     // TEHLİKELİ — içindeki işaretleme YORUMLANIR
el.textContent = ad;   // GÜVENLİ  — içindeki her şey düz metin olarak yazılır

Kural basittir: işaretleme üretmek zorunda değilsen textContent kullan. Üretmek zorundaysan sunucu tarafında kaçır (5. hattaki Razor ve 11. hattaki JSX bunu varsayılan olarak yapar) ya da temizleyici bir kütüphane kullan. XSS'in türleri, İçerik Güvenlik Politikası (CSP) ve savunma katmanları 13. hattın konusu; burada bilmen gereken, bu iki satırın farkının bir güvenlik açığı büyüklüğünde olduğudur.

08Tarayıcı hatalarını kurtarır: kaynak ≠ DOM

HTML, XML gibi katı değildir. Ayrıştırıcı hata verip durmaz; tanımlı bir kurtarma algoritması uygular. Sonuç: DevTools'un Elements panelinde gördüğün ağaç, yazdığın kaynak koddan farklı olabilir. En sık karşılaşılan üç durum:

<!-- Yazdığın -->
<p>Bir paragraf <div>kutu</div> devamı</p>

<!-- Tarayıcının ürettiği -->
<p>Bir paragraf </p><div>kutu</div> devamı<p></p>

<p> blok içerik alamadığı için ayrıştırıcı paragrafı erkenden kapatır. Bunu bilmeyen biri "CSS'im neden bu kutuya uygulanmıyor" diye saatlerce arar; çünkü CSS seçicisi p .kutu yazmıştır ama DOM'da kutu artık paragrafın içinde değildir.

<!-- Tablo dışına yazılmış içerik yukarı taşınır -->
<table><p>metin</p><tr><td>a</td></tr></table>
<!-- DOM: <p> tablonun ÖNÜNE çıkar, ayrıca <tbody> kendiliğinden eklenir -->

Üçüncüsü de <tbody>'nin kendiliğinden eklenmesidir: yazmasan bile DOM'da vardır, bu yüzden table > tr seçicisi hiçbir şey seçmez. 4. derste tablolara geldiğimizde bu tuzağı tekrar göreceğiz.

Pratik sonuç: Elements panelindeki ağaca güven, kaynak koda değil. "View source" sunucudan gelen ham metni gösterir; Elements paneli tarayıcının kurduğu (ve JavaScript'in değiştirdiği) canlı DOM'u gösterir. İkisinin farklı olması normaldir ve hata ayıklarken bakılacak yer ikincisidir.

Doğrulama için W3C Nu HTML Checker kullanılır. "Tarayıcıda düzgün görünüyor" bir doğruluk ölçütü değildir; kurtarma algoritması sayesinde bozuk HTML de düzgün görünebilir, ta ki başka bir tarayıcıda ya da ekran okuyucuda görünmeyene kadar.

09Mini alıştırma — Bozuk sayfayı düzelt

Yaklaşık 20 dakika · tek bir .html dosyası, sunucu gerekmez

  1. İskeleti kur: boş bir deneme.html aç ve yukarıdaki yedi satırlık iskeleti yaz. Tarayıcıda aç, sekme başlığını gör.
  2. Uyumluluk modu: <!doctype html> satırını sil, konsolda document.compatMode yaz. Ne döndü? Sonra geri koy.
  3. Kodlama: <meta charset> satırını sil ve içinde "şğüıöç" geçen bir paragraf yaz. Bozuldu mu? Bozulmadıysa sebebi nedir — dosya ne olarak kaydedilmiş, sunucu ne başlık gönderiyor?
  4. Viewport: viewport meta'sını silip DevTools'ta cihaz emülasyonunu aç. Metin okunabilir mi?
  5. Boole öznitelik: bir <button disabled="false"> koy ve tıklamayı dene. Beklediğin oldu mu?
  6. Kurtarma algoritması: <p>metin<div>kutu</div></p> yaz; Elements panelinde ağacı incele. Kaç <p> var?
  7. Anlam farkı: aynı cümleyi <b> ve <strong> ile yaz. Görünüş aynı mı? Şimdi Elements panelinde erişilebilirlik sekmesinden ikisinin rolüne bak.
  8. Başlık hiyerarşisi: h1 → h3 → h2 sırasıyla üç başlık yaz; DevTools → Lighthouse → Accessibility denetimini çalıştır ve uyarıyı oku.
  9. Görsel ve CLS: büyük bir görseli önce width/height olmadan, sonra vererek koy. Performance panelinde Layout Shift kayıtlarını karşılaştır.
  10. alt: aynı görseli üç kez koy — biri anlamlı alt, biri alt="", biri alt özniteliği hiç olmadan. Ekran okuyucu (Windows'ta NVDA, macOS'ta VoiceOver) ya da tarayıcının erişilebilirlik ağacında farkı gör.
  11. Kaçış: bir paragrafa 5 < 10 && 10 > 5 yazmayı dene. Doğru görünmesi için hangi karakterleri kaçırdın?
  12. innerHTML vs textContent: konsolda document.body.append(...) ile bir div oluştur; içine <img src=x onerror="alert(1)"> metnini bir kez innerHTML, bir kez textContent ile yaz. Hangisi çalıştı?
  13. Doğrulama: dosyayı W3C Nu HTML Checker'a yükle ve çıkan tüm uyarıları sıfıra indir.

10Kendini sına

<!doctype html> ne işe yarar, olmazsa ne olur?

Belge türü bildirimi tarayıcıya belgeyi standart modda işlemesini söyler. Yazılmazsa tarayıcı uyumluluk moduna (quirks mode) düşer ve 1990'ların tarayıcı davranışlarını taklit eder. En görünür farkı kutu modelidir: standart modda width yalnız içeriği kapsar, uyumluluk modunda dolgu ve kenarlık da dâhil edilir — yani düzenler beklenmedik biçimde kayar. Ayrıca satır yüksekliği, tablo hücre hizalaması ve bazı CSS özelliklerinin yorumlanması değişir. Hangi modda olduğun konsolda document.compatMode ile görülür: "CSS1Compat" standart, "BackCompat" uyumluluk modudur. HTML5'te doctype'ın tek işlevi budur; HTML4 dönemindeki uzun DTD bildirimleri artık gereksizdir. Not: modern bir tarayıcı doctype olmayan eski bir kurumsal sayfayı da "çalıştırır", bu yüzden sorun görünmez kalır — CSS düzeltmeleri tutmadığında ilk bakılacak yerlerden biridir.

<strong> ile <b>, <em> ile <i> arasındaki fark nedir?

Görsel sonuç aynıdır (kalın ve italik), anlam farklıdır. <strong> "güçlü önem" bildirir; <em> "vurgu" bildirir ve cümlenin anlamını değiştirir ("bugün gönder" ile "bugün gönder" farklı şeyler söyler). <b> ve <i> ise anlamsal önem taşımayan, yalnızca tipografik ayrım isteyen durumlar içindir: ürün adı, anahtar kelime, yabancı terim, teknik ad. Fark erişilebilirlikte ortaya çıkar — ekran okuyucular strong/em'i tonlamayla belirtebilir, b/i için bir şey yapmaz — ve makine okunurluğunda önemlidir. Pratik ölçüt: "sesli okuyan biri burada sesini yükseltmeli mi?" Cevap hayırsa zaten CSS ile font-weight: 600 yazman daha doğrudur. HTML5, bu iki etiketi kaldırmadı; anlamlarını yeniden tanımlayarak korudu.

Görselde alt özniteliğini boş bırakmakla hiç yazmamak arasında fark var mıdır?

Evet, ve fark büyüktür. alt="" ekran okuyucuya "bu görsel süstür, atla" der; okuyucu görseli hiç duyurmaz — ayraç çizgileri, dekoratif simgeler ve arka plan görselleri için doğru olan budur. alt özniteliğini hiç yazmamak ise "metin karşılığı bilinmiyor" anlamına gelir; ekran okuyucu çaresiz kalır ve genellikle dosya adını okur (IMG_20260115_final_v3.jpg). Yani boş alt bilinçli bir karardır, eksik alt bir hatadır. Üçüncü durum: görsel bilgi taşıyorsa alt o bilgiyi anlatmalıdır — "grafik" değil, grafiğin söylediği şey. Görsel bir bağlantının tek içeriğiyse alt, bağlantının hedefini anlatır ("Ana sayfa"), görselin kendisini değil ("logo"). Son olarak alt ile title karıştırılmamalıdır: title yalnız fare üzerine gelince çıkar, klavye ve dokunmatik kullanıcıları için erişilemez, bu yüzden erişilebilirlik çözümü olarak kullanılmaz.

Tarayıcıda gördüğün DOM ile yazdığın HTML neden farklı olabilir?

Üç sebepten. (1) Hata kurtarma: HTML ayrıştırıcısı geçersiz iç içeliği durup hata vererek değil, tanımlı bir algoritmayla düzelterek karşılar. <p> içine <div> yazarsan paragraf erkenden kapatılır; tablo içine yazılmış serbest metin tablonun dışına taşınır; kapatılmamış etiketler kapatılır. (2) Zorunlu ögeler: yazmasan bile <html>, <head>, <body> ve tablolarda <tbody> DOM'a eklenir — bu yüzden table > tr seçicisi hiçbir şey seçmez. (3) JavaScript: sayfa yüklendikten sonra DOM değiştirilmiş olabilir; tek sayfalık uygulamalarda kaynak kod neredeyse boş, DOM ise doludur. Pratik sonucu: hata ayıklarken "View source" değil Elements paneli okunur; CSS seçicilerin neden tutmadığını anlamanın en hızlı yolu da odur. Bozuk HTML'in tarayıcıda düzgün görünmesi doğruluk kanıtı değildir — doğrulayıcı çalıştırmak gerekir, çünkü aynı kurtarma her tarayıcıda ve her ekran okuyucuda aynı sonucu vermeyebilir.

11Sınav köşesi

Yazılıda nasıl sorulur

(1) HTML nedir, programlama dili midir? (2) <!doctype html> ne işe yarar? (3) <head> ile <body> farkı; head içinde neler bulunur. (4) Blok ve satır içi ögeler; örnek veriniz. (5) <strong>/<b> ve <em>/<i> farkı. (6) id ile class farkı. (7) Void element nedir, örnekleyiniz. (8) <img> etiketinin öznitelikleri; alt neden zorunludur. (9) Göreli ve mutlak yol. (10) HTML varlıkları (entity) ne için kullanılır. (11) data-* öznitelikleri. (12) Meta viewport ne işe yarar.

Sözlüde nasıl anlatılır — 2 dakikalık taslak

Düzen: (1) Tanım — "HTML bir işaretleme dilidir; belgenin yapısını ve anlamını tanımlar, görünüşü CSS'e, davranışı JavaScript'e bırakır." (2) İskelet — "doctype standart modu açar, lang dili bildirir, charset ilk 1024 baytta olmalıdır, viewport meta'sı olmadan duyarlı tasarım mobilde çalışmaz." (3) Kıdem vuruşu — "etiket seçimini görünüşe göre değil anlama göre yaparım; strong ile b aynı görünür ama ekran okuyucuya farklı şey söyler, başlık seviyesini boyut için seçmem." (4) Tuzak bilgisi — "HTML ayrıştırıcısı hataları kurtarır; bu yüzden Elements panelindeki DOM kaynak koddan farklı olabilir — <p> içine <div> koyarsan paragraf erken kapanır, <tbody> yazmasam da eklenir." (5) Güvenlik ve performans — "kullanıcı verisini yazarken textContent kullanırım, innerHTML XSS açar; görsellere width/height yazarım, yoksa yerleşim kayması olur."