Blok 3 · Ders 19
HTML: sayfanın iskeleti
Etiketler, başlıklar, paragraf, bağlantı, resim, liste, tablo ve form elemanlarıyla anlamlı (semantik) bir sayfa kuruyorsun.
Bu dersin sonunda
- Bir HTML satırında etiketi, öğeyi ve niteliği gösterebilir, etiketleri doğru sırayla iç içe yazabilirsin
- Her sayfanın iskeletini (
<!doctype html>,html lang,head,meta,title,body) ezbere kurabilirsin - Başlık, paragraf, vurgu, bağlantı, resim, liste ve tabloyla bir sayfanın içeriğini yazabilirsin
labelile eşleşmiş metin, sayı, e-posta, onay kutusu, seçenek düğmesi, açılır liste ve yazı alanı kurabilirsin- Sayfayı
header,nav,main,section,article,aside,footerile bölgelere ayırıp erişilebilirliğin temellerini uygulayabilirsin - W3C doğrulayıcısının mesajlarını okuyup HTML hatalarını tek tek düzeltebilirsin
Bu sayfada
- Etiketsiz metin: tarayıcı neyin ne olduğunu bilmez
- Etiket, öğe, nitelik
- Her sayfanın iskeleti
- HTML hata vermez, doğrulayıcı verir
- Başlıklar, paragraf ve vurgu
- Bağlantılar ve resimler
- Listeler ve tablo
- Formlar: kullanıcıdan bilgi almak
- Semantik etiketler: sayfanın haritası
- Erişilebilirlik: herkes kullanabilsin
- Uygulama: şampiyon tanıtım sayfası
- Sık hatalar
- Görevler
- Kendini sına
- Kayıt noktası
Ders 18'de bir web sayfasının üç katmanını gördün: HTML iskelet, CSS görünüm, JavaScript davranış. Bu ders iskeletin dersi. HTML bir programlama dili değil: değişken, if, döngü yok. Bir işaretleme dili: içeriğin her parçasını işaretleyip tarayıcıya "bu bir başlık", "bu bir liste", "bu bir form kutusu" dersin. Dersin sonunda yalnız HTML ile, telefonda da düzgün açılan ve doğrulayıcıdan hatasız geçen tek sayfalık bir şampiyon tanıtım sayfası yazmış olacaksın.
Etiketsiz metin: tarayıcı neyin ne olduğunu bilmez
HTML'in neden gerektiğini görmek için deneme.html'e hiç etiket kullanmadan şunu yaz, kaydet ve tarayıcıda aç:
AhriDokuz Kuyruklu Tilki Rol: BüyücüKoridor: OrtaBeş satır yazdın, tarayıcı tek satır gösterdi. Tarayıcı satır sonlarını ve art arda gelen boşlukları tek bir boşluğa indirir. Hangi satırın başlık, hangisinin ayrı bir paragraf olduğunu bilemez, çünkü bunu ona sen söylemedin. Şimdi aynı içeriği etiketlerle yaz:
<h1>Ahri</h1><p>Dokuz Kuyruklu Tilki</p><p>Rol: Büyücü</p><p>Koridor: Orta</p><h1> "bu sayfanın ana başlığı", <p> "bu bir paragraf" demek. Tarayıcı başlığı büyük ve kalın, paragrafları alt alta ve aralarında boşlukla çizdi. Bu, tarayıcının varsayılan görünümü; rengi, boyutu ve yazı tipini Ders 20'de CSS ile sen belirleyeceksin. HTML'in işi görünüş değil, anlam.
Etiket, öğe, nitelik
<p>Rol: Büyücü</p> satırında üç parça var: <p> açılış etiketi, </p> kapanış etiketi (adın önünde eğik çizgi var), aradaki yazı da içerik. Üçüne birlikte öğe denir. Bazı öğeler açılış etiketinde ek bilgi taşır; buna nitelik denir. En iyi örnek bağlantı öğesi a: nereye gideceğini href niteliği söyler.
Yazım kuralları az ve hep aynı:
- Etiket adlarını küçük harfle yaz.
<P>de çalışır ama herkes küçük harf kullanır. - Nitelik değerini çift tırnağa al. Değerde boşluk varsa tırnak şart:
src=img/ahri resmi.pngyazarsan tarayıcıresmi.png'yi ayrı bir nitelik sanar. - Nitelikleri birbirinden boşlukla ayır:
<img src="ahri.png" alt="Ahri">.
İç içe yazmak
Bir öğenin içine başka öğeler koyabilirsin. strong "bu kısım önemli" demek ve paragrafın içinde bir parçayı işaretler: <p>Ahri <strong>çok</strong> hızlı.</p>. Kural Ders 2'deki parantezlerle aynı: en son açtığını ilk kapat. ( [ ] ) doğru, ( [ ) ] yanlış.
<p><strong>Ahri</p></strong><p><strong>Ahri</strong></p>VS Code burada yardım eder: bir açılış etiketini yazıp > girdiğinde kapanışını kendisi ekler, imleci bir etiketin üstüne koyduğunda eşini de vurgular.
Kapanışı olmayan öğeler
Bazı öğelerin içi olmaz, bu yüzden kapanış etiketleri de yoktur: satır kırma <br>, resim <img>, form kutusu <input>, sayfa bilgisi <meta>. Bunlara boş öğe (void element) denir. Başka kodlarda <br /> biçimini görebilirsin; HTML'de sondaki eğik çizginin hiçbir etkisi yoktur.
Yorum
<!-- Bu satır sayfada görünmez -->JavaScript'teki // gibi: tarayıcı yorumu göstermez. Ama sayfanın kaynağını açan (sağ tık → Sayfa kaynağını görüntüle, İngilizcede View page source, ya da Ctrl+U) herkes okur. Yoruma şifre ya da gizli not yazma.
Her sayfanın iskeleti
Etiketli dosyan çalıştı ama eksik: sekmede sayfanın adı yerine dosyanın adı ya da adresi yazıyor, telefonda küçücük görünecek ve Türkçe harfler bazı durumlarda bozulacak. Ders 18'de her sayfanın aynı iskeletle başladığını gördün ve onu kalıp olarak yazdın. Şimdi her satırın ne iş yaptığını öğrenecek ve iskelete telefonlar için bir satır daha ekleyeceksin. deneme.html'in içini sil ve şunu elle yaz:
<!doctype html><html lang="tr"><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Ahri - Sihirdar Rehberi</title></head><body> <h1>Ahri</h1> <p>Dokuz Kuyruklu Tilki</p></body></html>head ve body, html öğesinin içindedir ama alışkanlık olarak ikisini girintilemeyiz. Onların içindekiler 4 boşluk girintili. Beşinci satır pencereye sığmıyor; kodu yana kaydırınca sonu görünür: content="width=device-width, initial-scale=1">.
| Satır | Ne işe yarar? |
|---|---|
<!doctype html> | "Bu belge güncel HTML." Tarayıcıyı güncel kurallarla çalıştırır. |
<html lang="tr"> | Bütün sayfayı saran kök öğe. lang="tr": sayfanın dili Türkçe. |
<head> … </head> | Sayfada görünmeyen bilgiler: harf kodlaması, ekran ayarı, sekme adı. |
<meta charset="utf-8"> | Harf kodlaması UTF-8; Türkçe harfler doğru görünür. |
<meta name="viewport" …> | Telefonda sayfayı ekranın gerçek genişliğinde çiz. |
<title> … </title> | Sekmede, yer imlerinde ve arama sonuçlarında görünen ad. |
<body> … </body> | Sayfada görünen her şey. |
head içindekiler sayfada görünmez; title sekmeye, body sayfaya düşer.Satırlar neden gerekli?
<!doctype html>: Tarayıcılar 1990'ların sayfalarını bozmamak için "eski kurallar" diye bir mod taşır (quirks mode). Bu ilk satır "güncel kuralları kullan" der; yazmazsan sayfa yine açılır ama eski kurallarla çizilir.
lang="tr": Ekran okuyucu sayfayı Türkçe sesle okur; yoksa "Şampiyon"u İngilizce okumaya çalışabilir. Tarayıcı da gereksiz yere "çevir" önermez.
<meta charset="utf-8">: Karakter kodlamasını Ders 18'de gördün: bilgisayar harfleri sayı olarak saklar ve UTF-8, Türkçe dahil bütün dillerin harflerini içeren tablodur. VS Code dosyanı UTF-8 kaydeder (durum çubuğunun sağında UTF-8 yazar); bu satır aynı bilgiyi tarayıcıya verir.
Vermezsen tarayıcı tahmin eder ve kodlama bildirmeyen bir sunucudan gelen sayfada yanılır: Ders 18'deki bozuk harfler böyle çıkıyordu. Satırı head'in ilk satırı yap: kurala göre bu bilgi sayfanın ilk 1024 baytının içinde olmalı, tarayıcı onu orada arar.
<meta name="viewport" …>: Telefon tarayıcıları, eski masaüstü sitelerini bozmamak için bu satırı görmezlerse sayfayı yaklaşık 980 piksel genişliğinde bir ekrana çizip telefona sığacak kadar küçültür. width=device-width "ekranın gerçek genişliğini kullan", initial-scale=1 "yakınlaştırmadan başla" der.

<title>: Sekmede görünen ad. Sayfayı yer imlerine ekleyince ve arama sonuçlarında da bu yazı çıkar. Her sayfanın kendi title'ı olmalı.
Kısayol: Emmet
İskeleti bir kez daha elle yazdın; artık Ders 18'de adını duyduğun kısayolu kullanabilirsin. VS Code'un içinde gelen Emmet aracı kısa yazıları koda açar. Boş bir .html dosyasında ! yaz; çıkan öneri listesinde Emmet Abbreviation satırı seçiliyken Enter'a bas (arayüz değişmiş olabilir). VS Code şu iskeleti yazar:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body> </body></html>İki yeri değiştir: lang="en"'i lang="tr" yap, Document yerine kendi başlığını yaz. Büyük harfli <!DOCTYPE html> ve UTF-8 seninkiyle aynı anlama gelir; HTML bu yerlerde büyük-küçük harf ayırmaz. 1.0 ile 1 de aynıdır.
HTML hata vermez, doğrulayıcı verir
JavaScript'te tek bir eksik parantez programı durdururdu (Ders 1'deki SyntaxError). HTML'de tarayıcı asla durmaz: hatalı kodu da çizer, eksikleri tahmin ederek tamamlar. Ama tahmin her zaman senin istediğin şey olmaz. deneme.html'in body kısmını şöyle değiştir; strong'u kapatmayı unuttuk:
<body> <h1>Orta koridor</h1> <p>Ahri <strong>çok hızlı bir büyücü.</p> <p>Lux ise uzaktan vurur.</p></body>Hiçbir hata mesajı yok, ama Lux'un cümlesi de kalın çıktı. Tarayıcının bu dosyadan ne kurduğunu görmek için sayfada F12'ye bas ve Elements sekmesine bak. Elements bunu açılıp kapanan bir ağaç olarak gösterir; aynı body'nin düz yazı hâli şu (Chromium'dan, boş satırları kısalttık):
<body> <h1>Orta koridor</h1> <p>Ahri <strong>çok hızlı bir büyücü.</strong></p><strong> <p>Lux ise uzaktan vurur.</p></strong></body>Tarayıcı ilk paragrafı kapatırken strong'u da kapattı, sonra "yazar kalın yazmaya devam etmek istiyor herhalde" diye düşünüp ikinci paragrafı yeni bir strong'un içine aldı. Sayfa büyüdükçe böyle sessiz tahminler bulması zor hatalara dönüşür. Onları görmenin yolu doğrulayıcı.
W3C doğrulayıcısını kullanmak
W3C (World Wide Web Consortium), web standartlarını yazan kuruluşlardan biri. Ücretsiz doğrulayıcısı herkese açık:
- Tarayıcıda
https://validator.w3.org/nu/adresini aç. - Check by menüsünden text input seç. (Dosyanı yüklemek istersen file upload.)
- Açılan kutu boş gelmez: ilk seferde hazır bir örnek, sonrakilerde en son denetlediğin kod durur. Kutuya tıkla, Ctrl+A ile hepsini seç ve Delete ile sil; yoksa yapıştırdığın kod onunla karışır ve satır numaraları kayar.
- VS Code'da
deneme.html'in içinde Ctrl+A, Ctrl+C ile hepsini kopyala, boş kutuya yapıştır ve Check düğmesine bas. - Mesajları yukarıdan aşağı oku. Hiç sorun yoksa Document checking completed. No errors or warnings to show. yazar.

deneme.html ile aynı.Ders 1'de Node'un hata mesajını okumayı öğrenmiştin; burada da aynı mantık işler:
- Error (kırmızı) mutlaka düzeltilir. Warning (sarı) büyük ihtimalle düzeltilmeli. Info yalnızca bilgi verir.
From line 10, column 13dosyanın 10. satırı, 13. karakteri demek: Node'dakiders1.js:3gibi.- Kesik çizgili kutu o satırdan bir parça; sarıyla boyalı kısım sorunun yeri, Node'daki
^işareti gibi.↩işareti orada bir satır sonu olduğunu gösterir. - Mesajlar İngilizce.
End tag p seen, but there were open elements"p'nin kapanış etiketi geldi ama içeride hâlâ açık öğeler vardı",Unclosed element strong"strong öğesi kapanmamış" demek.
Başlıklar, paragraf ve vurgu
Bir sayfanın başlıkları onun içindekiler listesidir. HTML'de altı başlık düzeyi var: h1 en önemli, h6 en az önemli. Bundan sonraki örnekleri deneme.html'deki iskeletin body kısmına yaz; iskelet hep aynı kalsın.
<h1>Ahri</h1><p>Orta koridorun en hareketli büyücülerinden biri.</p><h2>Yetenekler</h2><h3>Q: Aldatan Küre</h3><p>Küre gider ve geri döner, <strong>iki yolda da</strong> hasar verir.</p><h3>E: Ayartan Öpücük</h3><p>İsabet eden rakip bir süre <em>sana doğru</em> yürür.</p><h2>Kısa kombo</h2><p>Önce E at.<br>Rakip yürürken Q ile vur.</p>Başlık kuralları:
- Her sayfada bir
h1olur: sayfanın konusu. - Düzey atlanmaz:
h1'den sonrah2gelir,h3değil. Bir bölümü bitirip yeni bir ana bölüme geçerken yenidenh2'ye dönebilirsin; geri dönmek serbest, atlamak yasak. - Başlığı boyutuna göre seçme. "Daha küçük yazı" istiyorsan yine doğru düzeyi seç; boyutu Ders 20'de CSS ayarlayacak.
<p> paragraftır. <strong> "bu kısım önemli" der, tarayıcı kalın çizer. <em> vurgudur: yüksek sesle okurken üstüne basarak söylediğin sözcük; tarayıcı eğik çizer. Başka kodlarda b (kalın) ve i (eğik) de görürsün; aynı görünürler ama "önemli" ya da "vurgulu" anlamı taşımazlar, sen strong ve em kullan.
<br> paragrafın içinde satır kırar: adres, şiir, kombo adımları gibi. Paragraflar arasında boşluk için <br><br> yazma; ayrı <p> aç, boşluğu CSS ayarlar.
Önizlemeye bir daha bak: h1, h2, h3 ve p her biri kendi satırını kapladı ve alt alta dizildi; strong ile em ise cümlenin içinde kaldı, alt satıra inmedi. İlk türe blok öğe (Ders 2'deki süslü parantezli kod bloğuyla ilgisi yok), ikincisine satır içi öğe denir. Birazdan göreceğin bağlantı (a) da satır içidir. Bu davranışı Ders 21'de CSS ile değiştirmeyi öğreneceksin.
Bağlantılar ve resimler
Bağlantı: a
Web'i web yapan şey bağlantılardır. a öğesi tıklanabilir bir bağlantı kurar; nereye gideceğini href niteliği söyler. href üç türlü yazılır:
<p><a href="https://www.leagueoflegends.com/tr-tr/">League of Legends resmî sitesi</a></p><p><a href="lux.html">Lux'un sayfası</a></p><p><a href="#kombo">Komboya atla</a></p><h2 id="kombo">Kısa kombo</h2>href | Ne demek | Ne zaman |
|---|---|---|
https://… | Tam adres: protokol, alan adı, yol | Başka bir siteye |
lux.html | Göreli yol: bu dosyanın yanındaki lux.html | Kendi sitendeki başka bir sayfaya |
#kombo | Aynı sayfada id="kombo" olan öğe | Uzun sayfada bir bölüme atlamak |
Ders 18'deki adreslerin sonundaki # kısmı budur: xdd.baby/ders19#gorevler bu sayfada id="gorevler" olan başlığa iner. Klasöründe henüz lux.html yok; o bağlantıya tıklarsan hata sayfası gelir (bunu aşağıdaki sık hatalarda göreceksin). Denemek istersen yanına boş bir lux.html oluştur.
index.html'den bakınca göreli yollar. Tam adres ise klasörün dışına, internete çıkar.Başka bir siteye giden bağlantıyı yeni sekmede açmak istersen iki nitelik daha eklersin:
<a href="https://www.leagueoflegends.com/tr-tr/" target="_blank" rel="noopener noreferrer">Resmî site (yeni sekmede açılır)</a>target="_blank" bağlantıyı yeni sekmede açar. Eskiden açılan sayfa, onu açan sekmeyi başka bir adrese yönlendirebiliyordu; rel="noopener" bu kapıyı kapatır, noreferrer karşı siteye nereden geldiğini söylemez. Güncel tarayıcılar noopener'ı kendiliğinden uyguluyor, ama rel eski tarayıcılarda da korur ve yerleşik bir alışkanlıktır. Yeni sekmede açılacağını bağlantı yazısında söyle; kendi sitendeki sayfalar için target kullanma.
Resim: img
<img src="img/ahri.png" alt="Ahri'nin portresi" width="128" height="128">| Nitelik | Görevi |
|---|---|
src | Resim dosyasının yolu. href gibi tam adres ya da göreli yol olabilir. |
alt | Resim görünmezse yerine geçen yazı. Ekran okuyucu resmi bu yazıyla anlatır. |
width, height | Piksel olarak boyut, birim yazılmaz. Tarayıcı resim inmeden yerini ayırır, sayfa yüklenirken zıplamaz. Resmin gerçek boyutunu yaz; küçük göstereceksen ikisini aynı oranda küçült (128×128'lik resim için 64 ve 64), yoksa resim basık ya da uzun görünür. |
img boş öğedir, kapanış etiketi yok. Resim için sampiyon-sayfasi içinde img adında bir klasör aç ve kendi çizdiğin ya da çektiğin bir resmi koy. Kendi resminin boyutunu Dosya Gezgini'nde resme sağ tıklayıp Özellikler → Ayrıntılar (Properties → Details) sekmesinde görürsün.
Kendi denemende Riot'un Data Dragon'daki resmini de kullanabilirsin: https://ddragon.leagueoflegends.com/cdn/16.20.1/img/champion/Ahri.png adresini aç, resme sağ tıkla, Resmi farklı kaydet (İngilizcede Save image as) de ve img klasörüne ahri.png adıyla kaydet. Bu resim 128×128 piksel; koddaki width ve height bu yüzden 128. Adresteki 16.20.1 veri sürümü; Ders 15'teki versions.json en yenisini verir.
Bu sitede Riot'un resimlerini telif nedeniyle göstermiyoruz; önizlemelerde Ahri'nin resminin yerinde kendi çizdiğimiz bir yer tutucu var.

alt varsa tarayıcı yazıyı gösterir, yoksa boş bir çerçeve kalır (gerçek ekran görüntüsü, Chromium).alt yazarken:
- Resimde ne görünüyorsa onu kısaca yaz: "Ahri'nin portresi". "resim", "fotoğraf" deme; ekran okuyucu zaten "resim" der.
- Yalnızca süs olan bir resimde (bir ayraç çizgisi gibi)
alt=""yaz: boşalt, ekran okuyucuya "bunu atla" der.alt'ı hiç yazmamak ise hatadır.
Listeler ve tablo
Listeler
<h2>Güçlü yanları</h2><ul> <li>Çok hareketli: R ile üç kez atılır.</li> <li>E ile rakibi yakalar.</li></ul><h2>Geliştirme sırası</h2><ol> <li>Q: Aldatan Küre</li> <li>W: Tilki Ateşi</li> <li>E: Ayartan Öpücük</li></ol>ul (unordered list) sırasız listedir, maddelerin önüne nokta konur. ol (ordered list) sıralı listedir; numaraları tarayıcı yazar, araya bir madde eklersen numaralar kendiliğinden kayar. Her madde bir li (list item). li yalnız ul ya da ol'un içinde durabilir; listenin içine de li'den başka bir şey konmaz.
Tablo
Satırı ve sütunu olan veri için tablo kullanılır: istatistikler, fiyat listeleri, skorlar.
<table> <caption>Ahri'nin değerleri</caption> <thead> <tr> <th>Değer</th> <th>1. seviye</th> <th>Her seviyede</th> </tr> </thead> <tbody> <tr> <td>Can</td> <td>590</td> <td>+104</td> </tr> <tr> <td>Mana</td> <td>418</td> <td>+25</td> </tr> </tbody></table>| Etiket | Anlamı |
|---|---|
table | Tablonun tamamı |
caption | Tablonun başlığı: bu ne tablosu? |
thead | Başlık satırlarının bölümü |
tbody | Veri satırlarının bölümü |
tr | Bir satır (table row) |
th | Başlık hücresi; kalın ve ortalı çizilir |
td | Veri hücresi (table data) |
Tablo satır satır yazılır: bir tr açarsın, içine o satırın hücrelerini soldan sağa dizersin. Her satırda hücre sayısı aynı olmalı; bir hücre eksik kalırsa doğrulayıcı A table row was 2 columns wide, which is less than the column count established by the first row (3). diye uyarır.
th yalnız görünüş için değil: ekran okuyucu bir hücreyi okurken sütunun başlığını da söyler. Çizgiler görünüş işi, Ders 20'de CSS ile gelecek. Tabloyu sayfa düzeni (yan yana sütunlar) kurmak için kullanma; o iş Ders 21'deki CSS yerleşiminin.
Formlar: kullanıcıdan bilgi almak
Arama kutusu, giriş ekranı, yorum alanı… Kullanıcının bir şey yazdığı ya da seçtiği her yer bir formdur. Bu derste formun iskeletini kuruyorsun; yazılanları JavaScript ile okumayı Ders 23'te, bir sunucuya göndermeyi Blok 4'te öğreneceksin.
input ve label
<form> <label for="sihirdar">Sihirdar adın</label> <input type="text" id="sihirdar" name="sihirdar"> <button type="submit">Gönder</button></form>form: bütün form öğelerini saran kap.input: kullanıcının bilgi girdiği kutu. Boş öğedir, kapanışı yok. Ne tür bilgi alacağınıtypesöyler.label: kutunun adı.forniteliği, ait olduğu kutununid'siyle harfi harfine aynı olmalı. Bu bağ hem tıklamayı kolaylaştırır hem de ekran okuyucuya kutunun adını söyler.name: form gönderilirken bu bilginin hangi adla gideceği.name'i olmayan kutu hiç gönderilmez.button: formu gönderen düğme. Türlerini birazdan göreceksin.
label'ın for'u ile input'un id'si aynı ad olunca ikisi bağlanır.Diğer input türleri
<form> <p> <label for="eposta">E-posta</label> <input type="email" id="eposta" name="eposta"> </p> <p> <label for="saat">Haftada kaç saat oynuyorsun?</label> <input type="number" id="saat" name="saat" min="0" max="168"> </p> <p> <input type="checkbox" id="haber" name="haber"> <label for="haber">Yeni rehberlerden haberdar et</label> </p> <fieldset> <legend>Hangi koridorda oynuyorsun?</legend> <input type="radio" id="ust" name="koridor" value="ust"> <label for="ust">Üst</label> <input type="radio" id="orta" name="koridor" value="orta"> <label for="orta">Orta</label> <input type="radio" id="alt" name="koridor" value="alt"> <label for="alt">Alt</label> </fieldset> <button type="submit">Gönder</button></form>type | Ne alır? | Not |
|---|---|---|
text | Tek satır yazı | type yazmazsan bu sayılır. |
email | E-posta adresi | Gönderirken @ var mı diye bakar; telefonda klavyeye @ tuşu gelir. |
number | Sayı | Fareyle üstüne gelince artır-azalt okları çıkar; min ve max sınır koyar. |
checkbox | Evet ya da hayır işareti | Her kutu bağımsızdır, hepsi birden işaretlenebilir. |
radio | Bir gruptan tek seçim | Aynı name'i taşıyan düğmeler bir gruptur. |
Seçenek düğmelerini fieldset içine al ve grubun sorusunu legend ile yaz; ekran okuyucu her düğmeyi okurken soruyu da söyler. Her düğmenin value'su, o düğme seçilince gönderilecek değerdir.
Formu kendi dosyanda dene: e-posta kutusuna deniz@ornek.com, saate 12 yaz, onay kutusunu işaretle, Orta'yı seç ve Gönder'e bas. Sayfa yenilenir, kutular boşalır ve adres çubuğunun sonu şöyle olur:
deneme.html?eposta=deniz%40ornek.com&saat=12&haber=on&koridor=ortaDers 18'deki adres parçalarından ? sonrası işte bu: her kutunun name'i ve değeri, aralarında &; @ adreste %40 diye yazılır. Onay kutusuna value yazmadığın için işaretliyken on gitti.
Hiçbir şeyi doldurmadan gönderirsen adres deneme.html?eposta=&saat= olur: işaretlenmemiş onay kutusu ve seçilmemiş grup hiç gönderilmez. E-postaya @ içermeyen bir şey yazarsan tarayıcı formu göndermez ve bir uyarı gösterir; bu denetimleri Ders 23'te göreceksin.
select, textarea ve button
<form> <p> <label for="yetenek">En sevdiğin yetenek</label> <select id="yetenek" name="yetenek"> <option value="q">Q: Aldatan Küre</option> <option value="w">W: Tilki Ateşi</option> <option value="e" selected>E: Ayartan Öpücük</option> </select> </p> <p> <label for="ipucu">Senin ipucun</label> <textarea id="ipucu" name="ipucu" rows="3"></textarea> </p> <button type="submit">Gönder</button> <button type="reset">Temizle</button> <button type="button">Bir şey yapmaz</button></form>selectaçılır listedir, her seçenek biroption. Ekrandaoption'ın yazısı görünür, gönderilen isevalue'su.selectedniteliği açılışta hangi seçeneğin seçili geleceğini söyler; değeri yoktur, yazılması yeter.textareaçok satırlı yazı alanıdır.input'tan farklı olarak kapanış etiketi vardır; iki etiketin arasına yazdığın şey kutuya hazır yazı olarak girer.rowskaç satır yüksekliğinde görüneceğini söyler.buttondüğmedir vetypeüç değer alır:submitformu gönderir,resetformu ilk hâline döndürür,buttonkendi başına hiçbir şey yapmaz (Ders 22'de ona JavaScript ile iş yaptıracaksın).
Bir de placeholder niteliği var: <input placeholder="örnek: Deniz"> kutunun içinde soluk bir örnek gösterir. label'ın yerini tutmaz, çünkü yazmaya başlayınca kaybolur ve kullanıcı neyin sorulduğunu unutur.
Semantik etiketler: sayfanın haritası
Şimdiye kadar içeriğin parçalarını işaretledin; sayfanın bölgeleri için de etiketler var. Eskiden her bölge div denen anlamsız bir kutuyla yapılırdı ve tarayıcı hangisinin menü, hangisinin ana içerik olduğunu bilemezdi. Bugün her bölgenin kendi etiketi var:
| Etiket | İçine ne konur? |
|---|---|
header | Sayfanın (ya da bir bölümün) başı: site adı, logo, menü. |
nav | Ana gezinme bağlantıları. |
main | Sayfanın asıl içeriği. Sayfada bir tane olur. |
section | Konuya göre bir bölüm; kendi başlığıyla birlikte. |
article | Tek başına anlamlı içerik: bir haber, bir şampiyon tanıtımı, bir yorum. |
aside | Ana konuyla ilgili yan bilgi: ipucu kutusu, ilgili bağlantılar. |
footer | Sayfanın (ya da bir bölümün) sonu: hazırlayan, kaynaklar, iletişim. |
Bu etiketler görünüşü değiştirmez; değişen, tarayıcının ve yardımcı araçların sayfayı anlamasıdır. Chrome'un erişilebilirlik ağacında bu bölgeler birer yer işareti (landmark) olur: header → banner, nav → navigation, main → main, aside → complementary, footer → contentinfo. Ekran okuyucu kullanan biri tek tuşla bu yer işaretleri arasında atlar ve menüyü baştan sona dinlemeden ana içeriğe geçer. Hiçbir etiket uymuyorsa blok için div, satır içi parça için span kullanılır; ikisi de anlamsızdır, genelde CSS ile süslemek için vardır.
Erişilebilirlik: herkes kullanabilsin
Sayfanı yalnızca gözüyle ve faresiyle kullananlar ziyaret etmeyecek. Görme engelli biri ekran okuyucu ile sayfayı dinler, eli titreyen biri yalnız klavyeyle gezer, internet yavaşken resimler hiç inmez. Erişilebilirlik, sayfanın bu kişilerin hepsi için çalışması demek; doğru HTML yazınca işin büyük kısmı zaten biter.
Ekran okuyucu sayfayı tarayıcının kurduğu erişilebilirlik ağacından okur. Aynı şeyin iki yazılışı Chromium'un ağacına şöyle geçiyor (gerçek çıktı: önce rol, tırnak içinde ekran okuyucunun söyleyeceği ad):
| Yazdığın HTML | Erişilebilirlik ağacında |
|---|---|
<img src="ahri.png"> | image (adı yok, ne olduğu bilinmez) |
<img src="ahri.png" alt="Ahri'nin portresi"> | image "Ahri'nin portresi" |
<img src="cizgi.png" alt=""> | hiç yok: süs resmi atlanır |
<p>Sihirdar adın</p> ve <input type="text"> | textbox (adı yok) |
<label for="sihirdar">Sihirdar adın</label> ve <input type="text" id="sihirdar"> | textbox "Sihirdar adın" |
<a href="lux.html">buraya tıkla</a> | link "buraya tıkla" |
<a href="lux.html">Lux'un yetenekleri</a> | link "Lux'un yetenekleri" |
Ekran okuyucu kullananlar sayfadaki bağlantıları çoğu zaman bir liste olarak dinler; o listede beş tane "buraya tıkla" duyan biri hangisinin nereye gittiğini bilemez. Bu dersin erişilebilirlik temelleri:
<html lang="tr">: sayfa doğru dilde okunur.- Her anlamlı resimde
alt, süs resmindealt="". - Her form kutusunun bir
label'ı; seçenek gruplarındafieldsetvelegend. - Başlıklar sırayla: bir
h1, düzey atlamadan. - Gideceği yeri söyleyen bağlantı yazısı; tıklanan şeyler için süslenmiş bir
divdeğil, gerçekavebutton.
Kendin dene: fareye dokunmadan Tab'a bas. Odak bağlantılardan ve form kutularından sırayla geçmeli, Shift+Tab geri gider. Bir seçenek grubu tek durak sayılır, düğmeler arasında ok tuşlarıyla gezilir. Bir öğenin rolünü ve ekran okuyucuya hangi adla gittiğini F12 → Elements → sağ paneldeki Accessibility sekmesinin Role ve Name satırları gösterir (arayüz değişmiş olabilir).
Uygulama: şampiyon tanıtım sayfası
Şimdi hepsini birleştir. sampiyon-sayfasi klasöründe index.html adında yeni bir dosya oluştur; Ders 18'den hatırla, sunucu klasörün adresine gelen isteğe bu dosyayı verir. Resim için img/ahri.png dosyasını hazırla. Sayfanın planı:
header: site adı ve sayfa içi menü (nav)mainiçinde birarticle: başlık, resim, giriş paragrafı; ardından Oynanış, Yetenekler, Temel değerler ve Anket bölümleriaside: kısa bir ipucufooter: kaynak ve dış bağlantı
Dosyayı üç parçada yaz; satır numaraları kaldığın yerden devam ediyor. Önce iskelet, başlık bölgesi ve tanıtım:
<!doctype html><html lang="tr"><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Ahri - Sihirdar Rehberi</title></head><body> <header> <p><strong>Sihirdar Rehberi</strong></p> <nav> <ul> <li><a href="#oynanis">Oynanış</a></li> <li><a href="#yetenekler">Yetenekler</a></li> <li><a href="#degerler">Değerler</a></li> <li><a href="#anket">Anket</a></li> </ul> </nav> </header> <main> <article> <h1>Ahri</h1> <img src="img/ahri.png" alt="Ahri'nin portresi" width="128" height="128"> <p><em>Dokuz Kuyruklu Tilki.</em> Orta koridorun <strong>en hareketli</strong> büyücülerinden biri.</p>Menü bir bağlantı listesi: bağlantılar ul içinde, her biri bir li. Her bağlantı birazdan yazacağın bir bölümün id'sine gidiyor. İkinci parça, içerik bölümleri:
<section id="oynanis"> <h2>Oynanış</h2> <p>Ahri rakibini uzaktan yetenekleriyle yıpratır. Fırsat bulunca E ile yakalar, R ile üç kez atılarak ya kovalar ya kaçar.</p> </section> <section id="yetenekler"> <h2>Yetenekler</h2> <ul> <li><strong>Q, Aldatan Küre:</strong> Küre gider ve geri döner, iki yolda da hasar verir.</li> <li><strong>W, Tilki Ateşi:</strong> Üç alev yakındaki rakiplere kendiliğinden saldırır.</li> <li><strong>E, Ayartan Öpücük:</strong> İsabet eden rakip bir süre sana doğru yürür.</li> <li><strong>R, Ruh Saldırısı:</strong> Kısa sürede üç kez atılırsın.</li> </ul> <h3>Geliştirme sırası</h3> <ol> <li>Q: Aldatan Küre</li> <li>W: Tilki Ateşi</li> <li>E: Ayartan Öpücük</li> </ol> </section> <section id="degerler"> <h2>Temel değerler</h2> <table> <caption>Ahri'nin değerleri (yamayla değişebilir)</caption> <thead> <tr> <th>Değer</th> <th>1. seviye</th> <th>Her seviyede</th> </tr> </thead> <tbody> <tr> <td>Can</td> <td>590</td> <td>+104</td> </tr> <tr> <td>Mana</td> <td>418</td> <td>+25</td> </tr> <tr> <td>Zırh</td> <td>21</td> <td>+4,2</td> </tr> </tbody> </table> </section>Değerler Data Dragon'daki Ahri verisinden; yamalarla değişebildiği için tablonun başlığında bunu söylüyoruz. Son parça anket, yan bilgi ve sayfa sonu:
<section id="anket"> <h2>Anket</h2> <form> <p> <label for="sihirdar">Sihirdar adın</label> <input type="text" id="sihirdar" name="sihirdar"> </p> <p> <label for="saat">Haftada kaç saat Ahri oynuyorsun?</label> <input type="number" id="saat" name="saat" min="0" max="168"> </p> <fieldset> <legend>Ahri'yi hangi koridorda oynuyorsun?</legend> <input type="radio" id="orta" name="koridor" value="orta"> <label for="orta">Orta</label> <input type="radio" id="ust" name="koridor" value="ust"> <label for="ust">Üst</label> </fieldset> <p> <label for="yetenek">En sevdiğin yetenek</label> <select id="yetenek" name="yetenek"> <option value="q">Q: Aldatan Küre</option> <option value="w">W: Tilki Ateşi</option> <option value="e">E: Ayartan Öpücük</option> <option value="r">R: Ruh Saldırısı</option> </select> </p> <p> <label for="ipucu">Senin ipucun</label> <textarea id="ipucu" name="ipucu" rows="3"></textarea> </p> <p> <input type="checkbox" id="haber" name="haber"> <label for="haber">Yeni rehberlerden haberdar et</label> </p> <button type="submit">Gönder</button> </form> </section> </article> </main> <aside> <h2>Kısa ipucu</h2> <p>E isabet ederse hemen ardından Q'yu at: rakip sana doğru yürürken kaçamaz.</p> </aside> <footer> <p>Değerler Riot Games'in Data Dragon verisinden alındı.<br>Hazırlayan: Deniz</p> <p><a href="https://developer.riotgames.com/docs/lol" target="_blank" rel="noopener noreferrer">Riot geliştirici belgeleri (yeni sekmede açılır)</a></p> </footer></body></html>Kaydet ve index.html'i tarayıcıda aç. CSS olmadığı için her şey alt alta, tarayıcının varsayılan görünüşüyle dizilir:
Bitirmeden önce üç denetim yap:
- Doğrulayıcı:
index.html'in tamamını doğrulayıcıya yapıştır. Hedef: Document checking completed. No errors or warnings to show. Bu dosyayı biz denetledik, aynen yazdıysan bu mesajı göreceksin. - Klavye: Tab ile baştan sona gez. Menüdeki Anket bağlantısında Enter'a bas: sayfa ankete inmeli.
- Telefon: F12'ye bas, geliştirici araçlarında cihaz düğmesine (Toggle device toolbar, Ctrl+Shift+M) tıkla. Viewport satırı sayesinde yazılar okunaklı kalmalı.
Sık hatalar
HTML'de hata mesajını tarayıcı değil doğrulayıcı verir; aşağıdaki doğrulayıcı mesajlarının hepsi W3C doğrulayıcısının gerçek çıktısı. Son iki kart, doğrulayıcının hiç yakalamadığı hatalar: onları ancak tıklayarak bulursun. Bütün derslerin hataları hata rehberinde.
Error: Unclosed element strong.Ne zaman çıkar? Bir öğeyi açıp kapatmayı unutunca. Tarayıcı sessizce tahmin eder; burada sonraki paragrafı da kalın yaptı.
<h1>Orta koridor</h1> <p>Ahri <strong>çok hızlı bir büyücü.</p> <p>Lux ise uzaktan vurur.</p>Error: End tag p seen, but there were open elements.From line 10, column 42; to line 10, column 45ir büyücü.</p>↩ < Error: Unclosed element strong.From line 10, column 13; to line 10, column 20 <p>Ahri <strong>çok hıNasıl düzelir? Mesajdaki satıra git ve öğeyi, içindekileri bitirdiğin yerde kapat: çok hızlı bir büyücü.</strong></p>. Tek bir eksik etiket dört mesaj birden üretebilir; ilkini düzeltip yeniden denetle.
Error: An img element must have an alt attribute, except under certain conditions.Ne zaman çıkar? img öğesine alt yazmayınca.
<h1>Ahri</h1> <img src="img/ahri.png" width="128" height="128">Error: An img element must have an alt attribute, except under certain conditions. For details, consult guidance on providing text alternatives for images.From line 10, column 5; to line 10, column 53</h1>↩ <img src="img/ahri.png" width="128" height="128">↩</bodNasıl düzelir? Resmi anlatan bir alt ekle: alt="Ahri'nin portresi". Resim yalnız süsse alt="" yaz.
Error: The value of the for attribute of the label element must be the ID of a non-hidden form control.Ne zaman çıkar? label'ın for'u hiçbir kutunun id'sine uymayınca. Sayfa açılır ama yazıya tıklamak kutuyu seçmez, ekran okuyucu da kutunun adını bilmez.
<form> <label for="sihirdar">Sihirdar adın</label> <input type="text" id="sihirdarAdi" name="sihirdar"> </form>Error: The value of the for attribute of the label element must be the ID of a non-hidden form control.From line 10, column 9; to line 10, column 30>↩ <label for="sihirdar">SihirdNasıl düzelir? for ile id'yi harfi harfine aynı yap. Büyük-küçük harf de fark eder: sihirdar ile Sihirdar iki ayrı ad.
Error: Duplicate ID ad.Ne zaman çıkar? İki öğeye aynı id'yi verince. Genellikle bir form satırını kopyalayıp id'yi değiştirmeyi unutunca olur.
<form> <label for="ad">Sihirdar adın</label> <input type="text" id="ad" name="sihirdar"> <label for="ad">Takım adın</label> <input type="text" id="ad" name="takim"> </form>Error: Duplicate ID ad.From line 13, column 9; to line 13, column 48>↩ <input type="text" id="ad" name="takim">↩ < Warning: The first occurrence of ID ad was here.From line 11, column 9; to line 11, column 51>↩ <input type="text" id="ad" name="sihirdar">↩ Nasıl düzelir? Her öğeye kendi id'sini ver (sihirdar, takim) ve label'ların for'larını da ona göre güncelle. Aynı id iki kez geçince ikinci label'a tıklamak da birinci kutuyu seçer.
Error: The heading h3 (with computed level 3) follows the heading h1 (with computed level 1), skipping 1 heading level.Ne zaman çıkar? Başlık düzeyini atlayınca, çoğu zaman h2 "çok büyük göründüğü" için h3 seçince.
<h1>Ahri</h1> <h3>Yetenekler</h3>Error: The heading h3 (with computed level 3) follows the heading h1 (with computed level 1), skipping 1 heading level.From line 10, column 5; to line 10, column 8</h1>↩ <h3>YeteneNasıl düzelir? h3'ü h2 yap. Boyutu beğenmiyorsan bunu Ders 20'de CSS ile değiştireceksin; düzeyi görünüşe göre seçme.
Error: Element li not allowed as child of element body in this context.Ne zaman çıkar? li maddelerini bir ul ya da ol içine koymayı unutunca.
<h1>Geliştirme sırası</h1> <li>Q: Aldatan Küre</li> <li>W: Tilki Ateşi</li>Error: Element li not allowed as child of element body in this context. (Suppressing further errors from this subtree.)From line 10, column 5; to line 10, column 8</h1>↩ <li>Q: Ald Error: Element li not allowed as child of element body in this context. (Suppressing further errors from this subtree.)From line 11, column 5; to line 11, column 8</li>↩ <li>W: TilListenin dışında kalan her li için ayrı bir mesaj gelir.
Nasıl düzelir? Maddeleri sıra önemliyse <ol>…</ol>, önemsizse <ul>…</ul> içine al. Tersi de hatadır: ul'un içine li dışında yazı koyarsan Text not allowed in element ul in this context. mesajını alırsın.
Error: Element head is missing a required instance of child element title.Ne zaman çıkar? head içine title yazmayınca. Sekmede sayfanın adı yerine dosyanın adı ya da adresi görünür.
<!doctype html><html lang="tr"><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"></head><body> <h1>Ahri</h1></body></html>Error: Element head is missing a required instance of child element title.From line 6, column 1; to line 6, column 7scale=1">↩</head>↩<bodyNasıl düzelir? head içine <title>Ahri - Sihirdar Rehberi</title> gibi bir satır ekle. İlk satırdaki <!doctype html>'i unutursan da doğrulayıcı hata verir: Start tag seen without seeing a doctype first. Expected <!DOCTYPE html>.
Error: The character encoding was not declared. Proceeding using windows-1252.Ne zaman çıkar? <meta charset="utf-8"> satırı olmayan bir dosyayı doğrulayıcıya file upload ile yükleyince. Doğrulayıcı kodlamayı bilmediği için eski bir Batı Avrupa tablosu (windows-1252) kullandığını söylüyor; o tabloda Türkçe harfler bozulur.
Nasıl düzelir? head'in ilk satırı olarak <meta charset="utf-8"> yaz. Text input ile yapıştırınca bu hatayı görmezsin, çünkü yapıştırılan yazının kodlaması zaten bilinir; satırı yine de her sayfaya koy.
ERR_FILE_NOT_FOUND)Ne zaman çıkar? Başka bir sitenin adresini https:// olmadan yazınca. Doğrulayıcı bunu hata saymaz, çünkü www.leagueoflegends.com geçerli bir göreli yoldur: "bu klasördeki www.leagueoflegends.com adlı dosya".
<a href="www.leagueoflegends.com">Resmî site</a>Dosyaya çift tıklayıp açtıysan tarayıcı file:///C:/kod/sampiyon-sayfasi/www.leagueoflegends.com adresine gider ve bir hata sayfası gösterir; sayfanın altında ERR_FILE_NOT_FOUND kodu yazar. Live Server'da adres 127.0.0.1:5500/www.leagueoflegends.com olur ve Ders 18'de gördüğün Cannot GET sayfası gelir.
Nasıl düzelir? Başka siteye giden her bağlantıyı tam adresle yaz: href="https://www.leagueoflegends.com/tr-tr/". Adresi tarayıcının adres çubuğundan kopyalarsan https:// kısmı da gelir.
Ne zaman çıkar? Aynı gruba ait seçenek düğmelerine farklı name verince. Doğrulayıcı bunu hata saymaz, ama tarayıcı her name'i ayrı bir grup sanır ve "Orta" ile "Alt" aynı anda seçili kalır.
<input type="radio" id="orta" name="orta" value="orta"><label for="orta">Orta</label><input type="radio" id="alt" name="alt" value="alt"><label for="alt">Alt</label>Nasıl düzelir? Bir gruptaki bütün düğmelere aynı name'i ver (name="koridor"), farkı id ve value ile yap.
Görevler
Her görevi sampiyon-sayfasi klasöründe ayrı bir dosyada (gorev1.html, gorev2.html…), tam iskeletle yap. Bitirince doğrulayıcıdan geçir; hedef her seferinde No errors or warnings to show. Önce kendin dene, takılırsan ipuçlarını sırayla aç, çözüme en son bak.
Maç günlüğü
İskeleti bakmadan yaz. Sekmede Maç günlüğüm yazan bir sayfa yap. Sayfada aynı yazıyla bir ana başlık ve iki paragraf olsun: ilkinde kaç maç oynadığını yaz ve sayıyı strong ile önemli say; ikincisinde em ile vurgulanmış bir "kendime not" ve br ile kırılmış ikinci bir satır olsun. Sayfan şuna benzesin:
İpucu 1
İskelet sırası: doctype, html (dili Türkçe), head (iki meta ve title), body. head'in içindekiler sayfada görünmez.
İpucu 2
br boş öğedir, kapanışı yok. Paragrafın içinde, satırın kırılacağı yere yazılır.
Çözümü göster
<!doctype html><html lang="tr"><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Maç günlüğüm</title></head><body> <h1>Maç günlüğüm</h1> <p>Bugün Lux ile <strong>üç maç</strong> oynadım, ikisini kazandım.</p> <p><em>Kendime not:</em> Q'yu boşa atma.<br>Önce rakibin Flash'ını bekle.</p></body></html>Sınır denemesi: title satırını sil ve doğrulayıcıdan geçir, Element head is missing a required instance of child element title. hatasını gör. Sonra geri koy ve bu kez lang="tr"'yi sil: Consider adding a lang attribute… uyarısı çıkar. İkisini de geri koyunca mesaj kalmamalı.
Hata avı
Aşağıdaki sayfayı gorev2.html olarak yaz ve doğrulayıcıdan geçir. Gözle aramadan, yalnızca mesajları okuyarak düzelt: en üstteki mesajı düzelt, yeniden denetle, sıradakine geç. Bitince mesaj kalmamalı ve sayfa yine aynı içeriği göstermeli.
<!doctype html><html lang="tr"><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Jinx - Sihirdar Rehberi</title></head><body> <h1>Jinx</h1> <img src="img/jinx.png" width="128" height="128"> <p>Uzaktan vuran, <em>kaotik bir nişancı.</p> <h3>Silahları</h3> <li>Minigun</li> <li>Roket atar</li> <label for="favori">En sevdiğin silah</label> <input type="text" id="silah" name="silah"></body></html>İlk denetimde 9 mesaj gelir. İlk üçü:
Error: An img element must have an alt attribute, except under certain conditions. For details, consult guidance on providing text alternatives for images.From line 10, column 5; to line 10, column 53</h1>↩ <img src="img/jinx.png" width="128" height="128">↩ < Error: End tag p seen, but there were open elements.From line 11, column 46; to line 11, column 49r nişancı.</p>↩ < Error: Unclosed element em.From line 11, column 23; to line 11, column 26an vuran, <em>kaotikİpucu 1
Mesajların çoğu tek bir hatadan çıkıyor: kapanmayan em. 9 mesajın dördü doğrudan ondan geliyor; em'i kapatıp yeniden denetleyince 5 mesaj kalır. li mesajları da değişir, artık em değil body diyorlar.
İpucu 2
Kalanlar: resmin alt'ı yok; h1'den sonra h3 gelmiş; li'ler bir listenin içinde değil; label'ın for'u hiçbir kutunun id'si değil.
Çözümü göster
<!doctype html><html lang="tr"><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Jinx - Sihirdar Rehberi</title></head><body> <h1>Jinx</h1> <img src="img/jinx.png" alt="Jinx'in portresi" width="128" height="128"> <p>Uzaktan vuran, <em>kaotik bir nişancı.</em></p> <h2>Silahları</h2> <ul> <li>Minigun</li> <li>Roket atar</li> </ul> <label for="silah">En sevdiğin silah</label> <input type="text" id="silah" name="silah"></body></html>label hatasını iki yoldan düzeltebilirdin: for'u silah yapmak ya da kutunun id'sini favori yapmak. İkisi de doğru; önemli olan ikisinin aynı olması. Denetim: Document checking completed. No errors or warnings to show.
TFT faiz tablosu
TFT'de tur sonunda, elindeki her 10 altın için 1 altın faiz alırsın, ama en fazla 5. gorev3.html'de bunu gösteren bir tablo yaz: başlığı (caption) olsun, ilk satırı başlık hücreleriyle Elindeki altın ve Faiz olsun. Altın sütununda sırasıyla şu değerler bulunsun: 0, 9, 10, 19, 20, 49, 50, 75. Faiz sütununu kendin hesapla; hesap HTML'in değil senin işin.
İpucu 1
Tablo satır satır yazılır: başlık satırı thead içinde th'lerle, her veri satırı tbody içinde iki td'li bir tr.
İpucu 2
Sınırlara dikkat: 9 altın henüz 10 değil, faizi 0. 49 altında dört tane 10 var. 50 ve üstünde faiz hep 5.
Çözümü göster
<!doctype html><html lang="tr"><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>TFT faiz tablosu</title></head><body> <h1>TFT faiz tablosu</h1> <p>Her 10 altın için tur sonunda 1 altın faiz gelir, ama en fazla 5.</p> <table> <caption>Elindeki altına göre tur sonu faizi</caption> <thead> <tr> <th>Elindeki altın</th> <th>Faiz</th> </tr> </thead> <tbody> <tr> <td>0</td> <td>0</td> </tr> <tr> <td>9</td> <td>0</td> </tr> <tr> <td>10</td> <td>1</td> </tr> <tr> <td>19</td> <td>1</td> </tr> <tr> <td>20</td> <td>2</td> </tr> <tr> <td>49</td> <td>4</td> </tr> <tr> <td>50</td> <td>5</td> </tr> <tr> <td>75</td> <td>5</td> </tr> </tbody> </table></body></html>Bu tablodaki çiftler (9 ve 10, 49 ve 50) Ders 2'deki sınır değerleri: kural tam o noktada değişiyor. 75'teki 5 ise "en fazla" kuralının denemesi. Sınır denemesi: herhangi bir satırdan bir td sil ve doğrulayıcıdan geçir; A table row was 1 columns wide, which is less than the column count established by the first row (2). uyarısı çıkar.
Yama notlarım
gorev4.html'de kendi uydurduğun bir yama için not sayfası yaz. İstenenler:
- Ana başlık Yama notlarım, altında iki bölüm başlığı: Şampiyonlar ve Eşyalar. Şampiyonlar bölümünde en az iki şampiyonun adı alt başlık olsun. Düzey atlanmasın.
- Başlığın hemen altında
naviçinde bir "İçindekiler" listesi: iki bölüm başlığına giden sayfa içi bağlantılar. - Her şampiyonun ve eşyaların altında değişiklikleri sayan bir liste.
- En az bir şampiyon için bir resim:
alt,widthveheightile. Kendi resmin ya da Data Dragon'daki şampiyon resmi olabilir. - En altta resmî yama notlarına yeni sekmede açılan bir bağlantı:
https://www.leagueoflegends.com/tr-tr/news/tags/patch-notes/
İpucu 1
Sayfa içi bağlantı iki parçadır: hedef başlıkta id="esyalar", bağlantıda href="#esyalar". İki ad harfi harfine aynı olmalı.
İpucu 2
Başlık düzeni: h1 Yama notlarım → h2 Şampiyonlar → h3 Lux, h3 Garen → h2 Eşyalar. Her şampiyon başlığının ve Eşyalar başlığının altına birer ul.
Çözümü göster
<!doctype html><html lang="tr"><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Yama notlarım</title></head><body> <h1>Yama notlarım</h1> <nav> <p>İçindekiler:</p> <ul> <li><a href="#sampiyonlar">Şampiyonlar</a></li> <li><a href="#esyalar">Eşyalar</a></li> </ul> </nav> <h2 id="sampiyonlar">Şampiyonlar</h2> <h3>Lux</h3> <img src="img/lux.png" alt="Lux'un simgesi" width="64" height="64"> <ul> <li>Q yeteneğinin bekleme süresi kısaldı.</li> <li>R yeteneğinin hasarı arttı.</li> </ul> <h3>Garen</h3> <ul> <li>E yeteneğinde dönüş hızı arttı.</li> </ul> <h2 id="esyalar">Eşyalar</h2> <ul> <li>Zhonya'nın Kumsaati 100 altın pahalandı.</li> </ul> <p><a href="https://www.leagueoflegends.com/tr-tr/news/tags/patch-notes/" target="_blank" rel="noopener noreferrer">Resmî yama notları (yeni sekmede açılır)</a></p></body></html>Sınır denemesi: Eşyalar bağlantısına tıkla; adres çubuğunun sonu #esyalar olmalı. Bu sayfa kısa olduğu için ekrana sığıyorsa sayfa kaymaz, gidilecek başlık zaten görünüyordur.
Bozuk bağlantıyı görmek için uzun sayfanı kullan: index.html'de id="anket"'i id="anketler" yap, sayfanın en üstüne dön ve menüdeki Anket'e tıkla. Adres #anket ile biter ama sayfa yerinden kıpırdamaz; doğrulayıcı da hiçbir şey demez. Sayfa içi bağlantıları her zaman tıklayarak dene, sonra id'yi geri düzelt.
Turnuva kayıt sayfası
Bir hayran turnuvası için gorev5.html'de tam bir sayfa kur. İstenenler:
headeriçinde turnuvanın adı ve üç bölüme giden birnav.mainiçinde tekh1ve üçsection: Kurallar (sıralı liste, en az üç kural; biri "her takımda 5 asıl oyuncu, en fazla 2 yedek" olsun), Ödüller (caption'lı, iki sütunlu bir tablo: sıra ve ödül), Kayıt (form).- Formda: takım adı (yazı), kaptanın e-postası, yedeklerle oyuncu sayısı (5 ile 7 arası sayı), hangi gün oynayabilecekleri (üç seçenekli bir grup,
fieldsetvelegendile), sunucu (en az üç seçenekli açılır liste), takım tanıtımı (çok satırlı alan), "Kuralları okudum" onay kutusu, bir gönderme ve bir temizleme düğmesi. Her kutunun birlabel'ı olsun. main'in dışında biraside(sorular için iletişim) ve birfooter.- Doğrulayıcı: hiç hata ve uyarı yok.
İpucu 1
Önce body'nin iskeletini kur: header, main, aside, footer. İçlerini sonra doldur. Bölümlerin id'leri menüdeki href'lerle aynı olmalı.
İpucu 2
Oyuncu sayısı için <input type="number" … min="5" max="7">. Günler için üç radio, üçünde de aynı name. Düğmeler: type="submit" ve type="reset".
İpucu 3
Her label'ın for'u bir id'yle eşleşmeli ve her id sayfada bir kez geçmeli. Bitince her label'a tek tek tıklayarak dene.
Çözümü göster
<!doctype html><html lang="tr"><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Vadi Kupası - Kayıt</title></head><body> <header> <p><strong>Vadi Kupası</strong></p> <nav> <ul> <li><a href="#kurallar">Kurallar</a></li> <li><a href="#oduller">Ödüller</a></li> <li><a href="#kayit">Kayıt</a></li> </ul> </nav> </header> <main> <h1>Vadi Kupası kayıtları açık</h1> <p>Takımını kur, kaydını <strong>cuma akşamına kadar</strong> yap.</p> <section id="kurallar"> <h2>Kurallar</h2> <ol> <li>Her takımda 5 asıl oyuncu olur, en fazla 2 yedek eklenebilir.</li> <li>Maçlar Sihirdar Vadisi'nde turnuva seçimi (draft) ile oynanır.</li> <li>Maça 10 dakikadan fazla geç kalan takım hükmen kaybeder.</li> </ol> </section> <section id="oduller"> <h2>Ödüller</h2> <table> <caption>Sıralamaya göre ödüller</caption> <thead> <tr> <th>Sıra</th> <th>Ödül</th> </tr> </thead> <tbody> <tr> <td>1.</td> <td>Kupa ve sitede şampiyonlar köşesi</td> </tr> <tr> <td>2.</td> <td>Gümüş rozet</td> </tr> <tr> <td>3.</td> <td>Bronz rozet</td> </tr> </tbody> </table> </section> <section id="kayit"> <h2>Kayıt</h2> <form> <p> <label for="takim">Takım adı</label> <input type="text" id="takim" name="takim"> </p> <p> <label for="eposta">Kaptanın e-postası</label> <input type="email" id="eposta" name="eposta"> </p> <p> <label for="oyuncu">Oyuncu sayısı (yedeklerle)</label> <input type="number" id="oyuncu" name="oyuncu" min="5" max="7"> </p> <fieldset> <legend>Hangi gün oynayabilirsiniz?</legend> <input type="radio" id="cumartesi" name="gun" value="cumartesi"> <label for="cumartesi">Cumartesi</label> <input type="radio" id="pazar" name="gun" value="pazar"> <label for="pazar">Pazar</label> <input type="radio" id="ikisi" name="gun" value="ikisi"> <label for="ikisi">İkisi de olur</label> </fieldset> <p> <label for="sunucu">Sunucu</label> <select id="sunucu" name="sunucu"> <option value="tr">TR</option> <option value="euw">EUW</option> <option value="eune">EUNE</option> </select> </p> <p> <label for="tanitim">Takımınızı tanıtın</label> <textarea id="tanitim" name="tanitim" rows="4"></textarea> </p> <p> <input type="checkbox" id="onay" name="onay"> <label for="onay">Kuralları okudum</label> </p> <button type="submit">Takımı kaydet</button> <button type="reset">Formu temizle</button> </form> </section> </main> <aside> <h2>Sorun mu var?</h2> <p>Turnuva sorumlusuna Discord'dan yaz: <strong>vadikupasi</strong></p> </aside> <footer> <p>Vadi Kupası bir hayran turnuvasıdır, Riot Games ile bağı yoktur.</p> </footer></body></html>Sınır denemesi: takım adına Mor Tilkiler yaz, oyuncu sayısına sırayla 4, 5, 7 ve 8 yazıp her seferinde Takımı kaydet'e bas. 5 ve 7'de form gönderilir; 5'te adresin sonu gorev5.html?takim=Mor+Tilkiler&eposta=&oyuncu=5&sunucu=tr&tanitim= olur. Adda boşluk + olarak yazıldı; seçilmemiş gün ve işaretlenmemiş onay kutusu hiç gönderilmedi. 4 ve 8'de tarayıcı göndermez, kutunun yanında bir uyarı gösterir ve adres değişmez.
Günlerde birini seçip ötekine tıkla: önceki seçim kalkmalı. Formu temizle her kutuyu ilk hâline döndürmeli: yazılar silinir, seçimler kalkar, sunucu listesi yeniden TR'yi gösterir. Tab ile gezince seçenek grubu tek durak olmalı.
Kendini sına
Soru 1
Bu satırda hangi parçalar etiket, hangileri nitelik? Kapanış etiketi nerede?
<img src="lux.png" alt="Lux'un portresi" width="128" height="128">Cevabı göster
Satırın tamamı tek bir açılış etiketi ve aynı zamanda öğenin kendisi. img boş öğe olduğu için içeriği ve kapanış etiketi yok. Etiketin içindeki src, alt, width ve height niteliklerin adları, tırnak içindekiler değerleri.
Soru 2
Tarayıcı bunu nasıl gösterir?
<p>Ahri Lux Garen</p>Cevabı göster
Tek satırda Ahri Lux Garen. Tarayıcı art arda gelen boşlukları ve satır sonlarını tek bir boşluğa indirir. Satırı gerçekten kırmak istersen <br> ya da ayrı paragraflar kullanırsın.
Soru 3
Bu başlık düzeninin sorunu ne, nasıl düzelir?
<h1>Ahri</h1><h3>Yetenekler</h3><h2>Oynanış</h2>Cevabı göster
h1'den sonra h2 atlanıp doğrudan h3 gelmiş; doğrulayıcı bunu hata sayar ve başlıklarla gezen biri arada bir bölüm kaçırdığını sanır. Yetenekler de bir ana bölüm olduğu için h2 olmalı. h3'ten h2'ye geri dönmek ise serbest.
Soru 4
Takım adı yazısına tıklayınca kutu seçilmiyor. Neden?
<label for="takim">Takım adı</label><input type="text" id="takimAdi" name="takim">Cevabı göster
label'ın for'u (takim) kutunun id'siyle (takimAdi) aynı değil, bu yüzden ikisi bağlanmıyor. name'in takim olması işe yaramaz; label name'e değil id'ye bakar. İkisini aynı yap: for="takim" ve id="takim".
Soru 5
Bu düğmeye basınca sayfa yenileniyor ve yazdıkların siliniyor. Neden?
<form> <label for="ad">Sihirdar adın</label> <input type="text" id="ad" name="ad"> <button>Rastgele ad öner</button></form>Cevabı göster
Form içindeki type'sız bir button submit sayılır: tıklanınca form gönderilir ve sayfa yenilenir. Göndermemesi gereken düğmeye type="button" yazılır.
Soru 6
alt="" (boş) yazmakla alt'ı hiç yazmamak arasındaki fark ne?
Cevabı göster
Boş alt geçerlidir ve "bu resim süs, atla" demektir; ekran okuyucu resmi hiç anmaz. alt'ın hiç olmaması ise hatadır: doğrulayıcı Error verir, ekran okuyucu adı olmayan bir resimle karşılaşır. Ne olduğunu bilemez; ya yalnız "resim" der ya da dosya adını (ahri.png) okur.
Soru 7
<a href="www.leagueoflegends.com">Resmî site</a> neden siteye gitmiyor?
Cevabı göster
https:// olmadığı için tarayıcı bu adresi göreli yol sanıyor ve kendi klasöründe www.leagueoflegends.com adlı bir dosya arıyor (çift tıklayıp açtıysan ERR_FILE_NOT_FOUND). Başka siteye giden bağlantı tam adresle yazılır: https://www.leagueoflegends.com/tr-tr/.
Kayıt noktası
Bu derste yeni bir klasörde çalıştın, o yüzden Git'i bu klasörde baştan başlatıyorsun. VS Code terminalinde, C:\kod\sampiyon-sayfasi klasöründeyken:
Bir sonraki derste CSS'e geçiyorsun: renk, yazı tipi ve boşluk verecek, kutu modeliyle her öğenin etrafındaki boşlukları yönetecek ve sıfırdan bir şampiyon kartı boyayacaksın.