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

Category: guide

SVG Sprites & Icon System — icon ที่ maintain ง่ายและ accessible

วิธีสร้าง icon system ด้วย SVG sprite (symbol + use) และแนวทางทำ accessible icons ที่ถูกต้อง

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

สารบัญ

ปัญหาของ inline SVG ทุก icon

การ copy SVG ทุก icon เข้า HTML ตรงๆ ทำให้:

  • HTML ยาวมาก อ่านยาก
  • แก้ icon ต้องหาหลายที่
  • browser โหลด SVG ซ้ำทุก instance (ถ้า embed ตรงๆ)

SVG Sprite Pattern (ใช้งานได้กับ Astro)

<!-- sprite.svg — โหลดครั้งเดียว ซ่อนไว้ -->
<svg xmlns="http://www.w3.org/2000/svg" style="display: none">
  <symbol id="icon-arrow" viewBox="0 0 24 24">
    <path d="M5 12h14M12 5l7 7-7 7" stroke="currentColor" stroke-width="2"
      stroke-linecap="round" stroke-linejoin="round" fill="none"/>
  </symbol>

  <symbol id="icon-check" viewBox="0 0 24 24">
    <path d="M20 6L9 17l-5-5" stroke="currentColor" stroke-width="2"
      stroke-linecap="round" stroke-linejoin="round" fill="none"/>
  </symbol>
</svg>

<!-- ใช้ซ้ำได้ทุกที่ -->
<svg width="20" height="20" aria-hidden="true" focusable="false">
  <use href="#icon-arrow" />
</svg>

Astro Component สำหรับ Icon

---
// src/components/Icon.astro
interface Props {
  name: string;
  size?: number;
  label?: string;   // ถ้ามี label = accessible icon; ถ้าไม่มี = decorative
}
const { name, size = 20, label } = Astro.props;
---

<svg
  width={size}
  height={size}
  aria-label={label}
  aria-hidden={label ? undefined : 'true'}
  focusable="false"
  role={label ? 'img' : undefined}
>
  <use href={`/icons/sprite.svg#icon-${name}`} />
</svg>
<!-- Decorative icon (ข้างข้อความ) -->
<Icon name="arrow" size={16} />

<!-- Standalone icon (ปุ่มที่มีแค่ icon) -->
<button aria-label="ดูเพิ่มเติม">
  <Icon name="arrow" label="ดูเพิ่มเติม" />
</button>

Accessibility Rules

กรณีวิธี
Icon ข้างข้อความaria-hidden="true" — text อธิบายอยู่แล้ว
Icon คนเดียวใน buttonaria-label บน button หรือ <title> ใน SVG
Icon เป็นส่วนหนึ่งของ headingaria-hidden="true" — heading text อธิบายอยู่แล้ว

currentColor — ให้ icon ตาม text color

/* SVG ที่ใช้ currentColor จะเปลี่ยนสีตาม CSS color อัตโนมัติ */
.icon-btn { color: #2563eb; }
.icon-btn:hover { color: #1d4ed8; }

/* svg ใน .icon-btn จะเปลี่ยนสีตามโดยไม่ต้อง override */

สำคัญ: ใน SVG source ใช้ stroke="currentColor" และ fill="currentColor" ไม่ใช่ hardcode สี