HTML tablolarda colspan bir hücreyi yatayda birden fazla sütuna, rowspan dikeyde birden fazla satıra yayar; scope bir <th> başlığının satıra mı, sütuna mı yoksa bir gruba mı ait olduğunu söyler; headers ise karmaşık tablolarda bir hücreyi başlıklarına id üzerinden açıkça bağlar. <caption> tablonun adını verir, <colgroup> ve <col> de sütunları gruplar.

Bu yazı, table, tr, td ve th ile tablo oluşturma yazısındaki temel yapının üzerine kurulur ve tabloları hem görsel olarak doğru hem de ekran okuyucular için anlaşılır yapmaya odaklanır. Tüm kurallar MDN'nin ilgili öğe sayfalarından alındı; örneklerin etiket yapısı bir HTML ayrıştırıcıyla denetlendi. Serinin diğer konuları için HTML öğrenme rehberine bakabilirsiniz.

colspan ve rowspan: hücre birleştirme

colspan ve rowspan hem <td> hem <th> üzerinde kullanılabilir ve değerleri negatif olmayan bir tam sayıdır. İkisinin de varsayılan değeri 1'dir. MDN iki üst sınır belirtir: colspan değeri 1000'den büyükse 1000'e, rowspan değeri 65534'ten büyükse 65534'e kırpılır. rowspan için özel bir değer daha vardır: 0 yazarsanız hücre, ait olduğu tablo bölümünün (<thead>, <tbody> veya <tfoot>, örtük olsa bile) sonuna kadar uzanır.

Birleştirme yapılmayan hücreler, tablo ızgarasında boş kalan 1x1 yuvalara sırayla yerleşir. Yani bir üst satırdan aşağı uzanan bir hücre varsa, alt satırdaki hücreler o yuvayı atlayıp bir sonraki boş yuvaya oturur. MDN'nin açık bir uyarısı var: bu öznitelikler hücreleri üst üste bindirmek için kullanılmamalıdır. MDN'nin üyelik tablosunu Türkçeleştirerek iki satırlı bir başlık kuralım:

html
<table>
  <thead>
    <tr>
      <th scope="col" rowspan="2">Ad</th>
      <th scope="col" rowspan="2">Üye no</th>
      <th scope="col" colspan="2">Üyelik tarihleri</th>
      <th scope="col" rowspan="2">Bakiye</th>
    </tr>
    <tr>
      <th scope="col">Katılım</th>
      <th scope="col">İptal</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">Ayşe Demir</th>
      <td>427311</td>
      <td><time datetime="2010-06-03">3 Haziran 2010</time></td>
      <td>yok</td>
      <td>0,00</td>
    </tr>
    <tr>
      <th scope="row">Mehmet Kaya</th>
      <td>533175</td>
      <td><time datetime="2011-01-13">13 Ocak 2011</time></td>
      <td><time datetime="2017-04-08">8 Nisan 2017</time></td>
      <td>37,00</td>
    </tr>
  </tbody>
</table>

Hücre sayma yöntemi

Birleştirmeli tablolarda en sık hata, bir satıra fazla ya da eksik hücre yazmaktır. Bunu önlemenin yolu tabloyu bir ızgara gibi saymaktır. Yukarıdaki örnekte ilk başlık satırını sayalım: "Ad" 1 sütun, "Üye no" 1 sütun, "Üyelik tarihleri" colspan="2" olduğu için 2 sütun, "Bakiye" 1 sütun; toplam 5 sütun. "Ad", "Üye no" ve "Bakiye" aynı zamanda rowspan="2" taşıdığı için ikinci satırda 1., 2. ve 5. sütunlar zaten doludur. Geriye yalnızca 3. ve 4. sütun kalır; bu yüzden ikinci satıra sadece iki hücre ("Katılım" ve "İptal") yazılır ve bunlar tam olarak "Üyelik tarihleri" başlığının altına oturur. Gövde satırlarında birleştirme olmadığı için her satır beş hücre içerir.

Kural basit: her satırda, o satıra yazdığınız hücrelerin colspan toplamı ile üst satırlardan aşağı sarkan hücrelerin kapladığı sütun sayısı toplandığında tablonun sütun sayısı çıkmalıdır. Toplam tutmuyorsa tablo hata vermez ama sütunlar kayar; eksik yuvalar MDN'ye göre anonim bir hücre varmış gibi çizilir.

Aynı mantık gövdede de geçerlidir. MDN'nin <td> sayfasındaki örnekte "ABC" hücresi rowspan="3" ile ilk üç satıra uzanır; bu yüzden ikinci ve üçüncü satırlarda dördüncü hücre yazılmaz. Dördüncü ve beşinci satırlarda ise son hücre colspan="2" ile iki sütunu kaplar ve tablonun dört sütunlu ızgarası korunur.

caption: tablonun adı

<caption> tablonun başlığını belirtir ve tabloya erişilebilir bir ad ya da erişilebilir bir açıklama kazandırır. Kullanacaksanız mutlaka <table> öğesinin ilk çocuğu olmalıdır. MDN'ye göre tablonun amacını açık ve kısa biçimde anlatan bir başlık, okuyucunun tablonun geri kalanına bakması gerekip gerekmediğine karar vermesini sağlar; bu, ekran okuyucu kullananlara, az görenlere ve bilişsel güçlük yaşayanlara yardım eder.

Eskiden tabloya özet vermek için kullanılan summary özniteliği kullanımdan kalkmıştır; MDN yerine <caption> önerir. <caption> üzerindeki align özniteliği de kullanımdan kalkmıştır; başlığın tablonun altında ya da yanında görünmesi CSS ile ayarlanır. Bir başka ayrıntı: tabloya verilen arka plan rengi başlığa uygulanmaz; aynı rengi istiyorsanız başlığa da ayrıca vermeniz gerekir.

Tablo bir <figure> öğesinin tek içeriğiyse kural değişir: bu durumda başlık tablonun içindeki <caption> ile değil, figürün <figcaption> öğesiyle verilmelidir.

html
<!-- Tablo tek başına: caption kullanın -->
<table>
  <caption>2026 üçüncü çeyrek satışları</caption>
  <tr>
    <th scope="col">Ay</th>
    <th scope="col">Satış</th>
  </tr>
  <tr>
    <td>Temmuz</td>
    <td>320</td>
  </tr>
</table>

<!-- Tablo bir figure içinde tek içerik: figcaption kullanın -->
<figure>
  <figcaption>2026 dördüncü çeyrek satışları</figcaption>
  <table>
    <tr>
      <th scope="col">Ay</th>
      <th scope="col">Satış</th>
    </tr>
    <tr>
      <td>Ekim</td>
      <td>410</td>
    </tr>
  </table>
</figure>

scope: başlık hangi hücrelere ait?

scope: başlık hangi hücrelere ait? Başlık, bulunduğu satırdaki tüm hücrelere aittir., Başlık, bulunduğu sütundaki tüm hücrelere aittir., rowgroup, colgroup

scope yalnızca <th> üzerinde kullanılır; <td> üzerinde kullanımdan kalkmıştır. Dört değer alır:

DeğerAnlamı
rowBaşlık, bulunduğu satırdaki tüm hücrelere aittir.
colBaşlık, bulunduğu sütundaki tüm hücrelere aittir.
rowgroupBaşlık bir satır grubuna (thead, tbody veya tfoot) aittir ve o grubun tüm hücrelerini kapsar.
colgroupBaşlık bir sütun grubuna (colgroup) aittir ve o grubun tüm hücrelerini kapsar.

scope yazılmazsa ya da bu dört değerden biri değilse tarayıcı başlığın hangi hücrelere uygulanacağını kendisi seçer. MDN'ye göre basit tablolarda bu çıkarım yeterlidir ve scope gereksiz kalır; ancak bazı yardımcı teknolojiler doğru çıkarım yapamayabildiği için scope yazmak kullanıcı deneyimini iyileştirebilir. Karmaşık tablolarda ise başlıkla ilgili hücreleri belirtmek için gereklidir.

rowgroup ve colgroup değerleri en iyi bir arada görülür. Aşağıdaki örnekte <colgroup> öğeleri yılın iki yarısını, gövdedeki ilk satır da şubeyi gruplar:

html
<table>
  <caption>Şube bazında yarıyıl satışları</caption>
  <colgroup span="1"></colgroup>
  <colgroup span="2"></colgroup>
  <colgroup span="2"></colgroup>
  <thead>
    <tr>
      <td rowspan="2"></td>
      <th scope="colgroup" colspan="2">1. yarıyıl</th>
      <th scope="colgroup" colspan="2">2. yarıyıl</th>
    </tr>
    <tr>
      <th scope="col">Ocak</th>
      <th scope="col">Şubat</th>
      <th scope="col">Temmuz</th>
      <th scope="col">Ağustos</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="rowgroup" colspan="5">İstanbul</th>
    </tr>
    <tr>
      <th scope="row">Mağaza</th>
      <td>120</td>
      <td>95</td>
      <td>140</td>
      <td>150</td>
    </tr>
    <tr>
      <th scope="row">Online</th>
      <td>80</td>
      <td>70</td>
      <td>110</td>
      <td>130</td>
    </tr>
  </tbody>
</table>

Sol üst köşedeki hücre bir başlık taşımadığı için boş bir <td> olarak bırakıldı ve rowspan="2" ile iki başlık satırını kaplıyor. "1. yarıyıl" başlığı scope="colgroup" ile altındaki iki sütunun tamamına, "İstanbul" başlığı scope="rowgroup" ile kendi <tbody> grubundaki tüm satırlara ait. Saymayı unutmayın: her satır 5 sütun genişliğinde ve üç <colgroup> öğesinin span toplamı da 5.

headers ve id: karmaşık tablolarda açık bağ

headers ve id: karmaşık tablolarda açık bağ

Başlıkların yalnızca yatay ya da yalnızca dikey olarak eşleştirilemediği tablolarda scope tek başına yetmeyebilir. MDN, bu tür karmaşıklığın genellikle colspan ve rowspan kullanımıyla ortaya çıktığını belirtir. Böyle durumlarda her başlık hücresine benzersiz bir id verilir; veri hücresi de kendisine ait başlıkların id değerlerini boşlukla ayrılmış bir liste olarak headers özniteliğine yazar:

html
<table>
  <tr>
    <th id="harf-a" scope="row">A</th>
    <td>Alfa</td>
    <td>AL fah</td>
    <td headers="harf-a harf-b harf-c" rowspan="3">ABC</td>
  </tr>
  <tr>
    <th id="harf-b" scope="row">B</th>
    <td>Bravo</td>
    <td>BRAH voh</td>
  </tr>
  <tr>
    <th id="harf-c" scope="row">C</th>
    <td>Charlie</td>
    <td>CHAR lee</td>
  </tr>
</table>

Üç satıra yayılan "ABC" hücresi artık üç satır başlığına da programatik olarak bağlıdır ve bir ekran okuyucu bu hücreyi seslendirirken ilgili başlıkları da okuyabilir. Görsel sonuç değişmez. headers yalnızca veri hücrelerinde değil, başlık hücrelerinde de kullanılabilir: <th> sayfasındaki örnekte iki sütuna yayılan "Pronunciation" başlığı ile altındaki "IPA" ve "Respelling" alt başlıkları, birbirlerinin id değerlerini headers ile gösterir. Aynı fikrin Türkçe hâli:

html
<table>
  <tr>
    <th scope="col" rowspan="2">Sembol</th>
    <th scope="col" colspan="2" id="okunus" headers="ipa yazim">Okunuş</th>
  </tr>
  <tr>
    <th scope="col" id="ipa" headers="okunus">IPA</th>
    <th scope="col" id="yazim" headers="okunus">Yazılışla</th>
  </tr>
  <tr>
    <th scope="row">A</th>
    <td>ˈælfa</td>
    <td>AL fah</td>
  </tr>
</table>

MDN'nin karmaşık tablolar için ilk önerisi aslında headers değildir: mümkünse içeriği colspan ve rowspan gerektirmeyen daha küçük, ilişkili tablolara bölmeyi düşünün. Bu hem yardımcı teknoloji kullananlara hem de tablo düzenindeki ilişkileri takip etmekte zorlanan okuyuculara yardım eder. Tablo bölünemiyorsa id ve headers birlikte kullanılır.

abbr: başlığa kısa ad vermek

<th> üzerindeki abbr özniteliği, başlık hücresine kısa bir alternatif etiket verir. Bu etiket hücreye başka bağlamlarda atıf yapılırken kullanılır; ekran okuyucular gibi bazı kullanıcı aracıları bunu içerikten önce sunabilir. Uzun başlıkları olan tablolarda, her veri hücresinde uzun başlığın tekrar tekrar okunmasını kısaltmak için işe yarar. Aynı öznitelik <td> üzerinde ise kullanımdan kalkmıştır.

html
<table>
  <tr>
    <th scope="col">Ürün</th>
    <th scope="col" abbr="KDV">Katma değer vergisi oranı</th>
  </tr>
  <tr>
    <td>Kitap</td>
    <td>%10</td>
  </tr>
</table>

colgroup ve col: sütun grupları

HTML'de satırlar <tr> ile açıkça yazılırken sütunlar hücrelerin sırasından doğar. Sütunlara topluca işaret etmek gerektiğinde <colgroup> ve <col> kullanılır. <colgroup>, varsa <caption>'dan sonra; <thead>, <tbody>, <tfoot> ve <tr> öğelerinden önce yazılır. Kaç sütunu kapsadığını iki yoldan biriyle söylersiniz: ya span özniteliğiyle (sıfırdan büyük bir tam sayı, varsayılan 1) ya da içine <col> öğeleri koyarak. İkisi birlikte olmaz: içinde <col> bulunan bir <colgroup> span taşıyamaz.

<col> boş (void) bir öğedir, kapanış etiketi yazılmaz. Kendi span özniteliğiyle art arda birden fazla sütunu temsil edebilir. MDN'ye göre <col> sütunları yapısal olarak gruplamaz; gruplama <colgroup>'un görevidir. İki öğenin de örtük ARIA rolü yoktur ve üzerlerine rol verilemez.

html
<table>
  <caption>Haftalık etkinlikler</caption>
  <colgroup>
    <col span="5" class="hafta-ici" />
    <col span="2" class="hafta-sonu" />
  </colgroup>
  <thead>
    <tr>
      <th scope="col">Pzt</th>
      <th scope="col">Sal</th>
      <th scope="col">Çar</th>
      <th scope="col">Per</th>
      <th scope="col">Cum</th>
      <th scope="col">Cmt</th>
      <th scope="col">Paz</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Yüzme</td>
      <td>Satranç</td>
      <td>Dans</td>
      <td>Tarih kursu</td>
      <td>Alışveriş</td>
      <td>Gezi</td>
      <td>Serbest</td>
    </tr>
  </tbody>
</table>

Sütun öğeleri neden var, diye sorabilirsiniz: bir sütunun tüm hücrelerine tek yerden stil vermenin yolu budur. Ancak MDN, <col> ve <colgroup> üzerinde yalnızca sınırlı sayıda CSS özelliğinin etkili olduğunu belirtir: arka plan, kenarlık (yalnızca tabloda border-collapse: collapse varsa), visibility: collapse ve en az genişlik gibi davranan width. Sütun arka planı, satır ve hücre arka planlarının altında boyandığı için ancak üstteki katmanlar saydamsa görünür. Ayrıntılar CSS'in konusu; HTML tarafında önemli olan, sütun sayısını doğru vermektir.

<col> ve <colgroup> üzerindeki align, valign, width, char ve charoff gibi öznitelikler kullanımdan kalkmıştır. Toplu listeyi kullanımdan kalkan etiketler yazısında bulabilirsiniz.

ARIA ile tablo: ne zaman gerekir?

Yerel <table> kullandığınızda satır, hücre ve başlık rolleri ile birleştirme bilgileri tarayıcı tarafından kendiliğinden sunulur. aria-colspan, aria-rowspan, aria-rowcount, aria-colcount, aria-rowindex ve aria-colindex gibi öznitelikler, MDN'nin ARIA table rolü sayfasında anlatıldığı gibi, <div> öğeleriyle role="table" kurulan yapılarda ya da satırların bir kısmı belgede her zaman bulunmayan tablolarda gerekir. MDN'nin özeti nettir: <table> ve ilgili öğeleri kullanmak çok daha basittir. Erişilebilir ad konusunu genel olarak aria-label ve aria-labelledby yazısında ele aldık.

Erişilebilir tablo kontrol listesi

Erişilebilir tablo kontrol listesi: Tablonun konusunu söyleyen bir <caption> var mı ve tablonun ilk çocuğu mu?, Başlık hücreleri <th>, veri hücreleri <td> mi?, Satır başlıklarında...
  • Tablonun konusunu söyleyen bir <caption> var mı ve tablonun ilk çocuğu mu?
  • Başlık hücreleri <th>, veri hücreleri <td> mi?
  • Satır başlıklarında scope="row", sütun başlıklarında scope="col" belirtilmiş mi?
  • Grup başlıkları için rowgroup veya colgroup değerleri doğru grupla eşleşiyor mu?
  • Birleştirmeli satırlarda hücre sayısı ızgarayla tutarlı mı, hücreler üst üste binmiyor mu?
  • Karmaşık tablolarda headers değerleri var olan ve benzersiz id'lere mi işaret ediyor?
  • Tablo daha küçük tablolara bölünerek sadeleştirilebilir mi?

Bu maddeler, WCAG'nin "algılanabilir" ilkesinin, özellikle bilgi ve ilişkilerin yapı aracılığıyla aktarılması fikrinin tablolardaki karşılığıdır. Genel çerçeve için WCAG temelleri yazısına bakın.

Sık yapılan hatalar

  • Hücreleri üst üste bindirmek: Bir rowspan aşağı sarkarken alt satıra o yuvayı da dolduracak bir hücre yazmak. MDN bu özniteliklerin hücre bindirmek için kullanılmamasını açıkça belirtir.
  • colspan toplamını tutturamamak: Satırların genişliği farklı çıkar, sütunlar kayar.
  • caption'ı ilk çocuk yapmamak: <caption> yalnızca <table> öğesinin ilk çocuğu olarak geçerlidir.
  • figure içinde çift başlık: Tablo figürün tek içeriğiyse <caption> yerine <figcaption> kullanın.
  • scope'u td üzerinde kullanmak: Bu kullanım kalkmıştır; başlık hücresini <th> yapın.
  • span ile col'u birlikte kullanmak: İçinde <col> olan <colgroup> span taşıyamaz.
  • col için kapanış etiketi yazmak: <col> boş bir öğedir; </col> geçersizdir.
  • summary özniteliğine güvenmek: Kullanımdan kalkmıştır; özeti <caption> içinde verin.

Sık Sorulan Sorular

rowspan="0" ne işe yarar?

Hücreyi, ait olduğu tablo bölümünün (<thead>, <tbody> veya <tfoot>) sonuna kadar uzatır. Bölüm örtük olarak oluşturulmuş olsa bile bu davranış geçerlidir. MDN colspan için böyle bir özel değer tanımlamaz.

Basit bir tabloda scope yazmak gerekir mi?

MDN'ye göre basit tablolarda tarayıcı başlık kapsamını çıkarabildiği için zorunlu değildir; yine de bazı yardımcı teknolojiler yanlış çıkarım yapabildiği için yazmak deneyimi iyileştirebilir.

caption mı, aria-label mı?

Yerel <table> için <caption> kullanın; hem görünür bir başlık olur hem de tabloya erişilebilir ad ya da açıklama kazandırır. aria-label ve aria-labelledby, MDN'nin anlattığı gibi özellikle role="table" ile kurulan yapılarda ad vermek için kullanılır.

headers ile scope birlikte kullanılabilir mi?

Evet. MDN'nin örneklerinde headers verilen başlık hücreleri aynı zamanda scope da taşır. scope basit yönleri, headers ise yönle ifade edilemeyen bağları anlatır.

Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.

İlgili içerikler: HTML öğrenme rehberi · HTML tablo oluşturma · Erişilebilir ad · WCAG temelleri · ARIA nedir · Sık yapılan HTML hataları · Kullanımdan kalkan etiketler