ข้ามไปเนื้อหาหลัก

Category: reference

HTML Semantic Elements — เขียน HTML ให้มีความหมาย

รวม HTML5 semantic elements ที่ควรรู้ทั้งหมด ว่าควรใช้ element ไหนในสถานการณ์ใด ทำไมถึงสำคัญต่อ accessibility และ SEO และความสัมพันธ์กับ ARIA

· อ่านประมาณ 2 นาที

สารบัญ

ทำไม Semantic HTML สำคัญ

<!-- ❌ div soup — ไม่มีความหมาย -->
<div class="header">
  <div class="nav">
    <div class="nav-item">Home</div>
  </div>
</div>

<!-- ✅ semantic — screen reader, bot, dev อ่านเข้าใจ -->
<header>
  <nav aria-label="Main navigation">
    <a href="/">Home</a>
  </nav>
</header>

Semantic HTML ช่วย:

  • Screen reader นำทางได้ถูกต้องโดยไม่ต้อง ARIA เพิ่ม
  • Search engine เข้าใจโครงสร้างหน้าได้ดีขึ้น
  • Developer อ่านโค้ดเข้าใจเร็วขึ้น
  • Browser render default style ที่เหมาะสม

Document Structure

<!DOCTYPE html>
<html lang="th">
  <head>
    <meta charset="UTF-8">
    <title>ชื่อหน้า</title>
  </head>
  <body>
    <header>...</header>      <!-- header ของ site หรือ section -->
    <nav>...</nav>            <!-- navigation links -->
    <main>                    <!-- เนื้อหาหลัก — มีแค่ 1 ต่อหน้า -->
      <article>...</article>  <!-- เนื้อหาที่เป็น self-contained -->
      <aside>...</aside>      <!-- เนื้อหาที่เกี่ยวข้องแต่ไม่ใช่ main content -->
    </main>
    <footer>...</footer>      <!-- footer ของ site หรือ section -->
  </body>
</html>

Content Elements

<!-- ระดับ heading — ห้ามข้าม (h1 → h3 โดยไม่มี h2) -->
<h1>ชื่อหน้า</h1>     <!-- มีแค่ 1 ต่อหน้า -->
<h2>หัวข้อหลัก</h2>
<h3>หัวข้อรอง</h3>

<!-- paragraph -->
<p>ข้อความ paragraph</p>

<!-- figure — รูปภาพ, diagram, code ที่มี caption -->
<figure>
  <img src="chart.png" alt="กราฟแสดงการเติบโต" />
  <figcaption>รูปที่ 1: อัตราการเติบโต Q1 2026</figcaption>
</figure>

<!-- blockquote -->
<blockquote cite="https://source.com">
  <p>ข้อความที่อ้างถึง</p>
</blockquote>

<!-- code -->
<pre><code class="language-js">const x = 1;</code></pre>
<p>ใช้ <code>npm install</code> เพื่อติดตั้ง</p>

Interactive Elements

<!-- button vs anchor -->
<!-- ใช้ <a> เมื่อ navigate ไปยัง URL -->
<a href="/about">About</a>

<!-- ใช้ <button> เมื่อทำ action ที่ไม่ navigate -->
<button type="button" onclick="toggleMenu()">Menu</button>
<button type="submit">Send</button>

<!-- details + summary — accordion โดยไม่ต้องการ JavaScript -->
<details>
  <summary>คลิกเพื่อดูเพิ่มเติม</summary>
  <p>เนื้อหาที่ซ่อนอยู่</p>
</details>

<!-- dialog — modal โดยไม่ต้องการ JS library -->
<dialog id="modal">
  <form method="dialog">
    <p>ยืนยันการลบ?</p>
    <button type="submit">ยืนยัน</button>
  </form>
</dialog>
<button onclick="document.getElementById('modal').showModal()">ลบ</button>

Lists

<!-- ordered list — ลำดับมีความหมาย -->
<ol>
  <li>เปิด terminal</li>
  <li>รัน npm install</li>
  <li>รัน npm run dev</li>
</ol>

<!-- unordered list — ลำดับไม่มีความหมาย -->
<ul>
  <li>Astro</li>
  <li>TypeScript</li>
</ul>

<!-- description list — คำศัพท์และนิยาม, key-value -->
<dl>
  <dt>Astro</dt>
  <dd>Web framework สำหรับ content-driven websites</dd>

  <dt>TypeScript</dt>
  <dd>JavaScript ที่มี static type system</dd>
</dl>

Time และ Date

<!-- ใช้ <time> เสมอสำหรับวันเวลา -->
<time datetime="2026-06-14">14 มิถุนายน 2026</time>
<time datetime="2026-06-14T09:00">9 โมงเช้า วันที่ 14 มิ.ย. 2026</time>
<time datetime="PT2H30M">2 ชั่วโมง 30 นาที</time>

ใช้กับ Astro

---
// Layout.astro
const { title } = Astro.props;
---
<html lang="th">
  <head>
    <title>{title}</title>
  </head>
  <body>
    <header>
      <nav>...</nav>
    </header>
    <main>
      <slot />
    </main>
    <footer>...</footer>
  </body>
</html>
---
// [slug].astro — blog post
const { Content } = await render(entry);
---
<article>
  <header>
    <h1>{entry.data.title}</h1>
    <time datetime={entry.data.date.toISOString()}>
      {entry.data.date.toLocaleDateString('th-TH')}
    </time>
  </header>
  <Content />
</article>

เมื่อไรต้องเพิ่ม ARIA

Semantic HTML ที่ถูกต้องแทบไม่ต้องการ ARIA แต่มีบางกรณีที่ต้องเพิ่ม:

<!-- เมื่อ semantic element ไม่เพียงพอ -->
<nav aria-label="Main navigation">...</nav>
<nav aria-label="Breadcrumb">...</nav>

<!-- เมื่อ state เปลี่ยน dynamically -->
<button aria-pressed="false" id="theme-toggle">Dark Mode</button>
<button aria-expanded="false" aria-controls="menu">Menu</button>

<!-- เมื่อ error message อยู่แยกจาก input -->
<input id="email" aria-describedby="email-error" />
<p id="email-error" role="alert">กรุณากรอกอีเมลที่ถูกต้อง</p>

กฎง่ายๆ: ถ้า HTML semantic element ทำให้ browser/screen reader เข้าใจได้แล้ว → ไม่ต้องเพิ่ม ARIA