SVG Symbol

ทางเลือกสำหรับ font-based icons — การใช้ SVG symbol sprites เพื่อฝัง scalable icons ที่มีหลายสีโดยตรงใน HTML

SVG Symbol Sprites คืออะไร?

SVG symbol sprites รวมไอคอน SVG หลายชิ้นเข้าเป็นไฟล์เดียว แต่ละไอคอนถูกกำหนดภายใน element <symbol> พร้อม id ที่ไม่ซ้ำ ในการใช้ไอคอน คุณอ้างถึงมันด้วย <use href="#icon-id"> sprite ถูกโหลดครั้งเดียว — ไม่ว่าจะ inline หรือเป็นไฟล์ภายนอก — และไอคอนแต่ละตัวถูก render ทุกที่ในหน้า

นี่เป็นแนวทางที่แตกต่างจาก icon fonts โดยพื้นฐาน แทนที่จะแมป Unicode code points กับ font glyphs คุณกำลังใช้ SVG elements ดั้งเดิม แต่ละไอคอนยังคงความสามารถ SVG เต็มรูปแบบ: หลายสี gradients, filters และ accessibility attributes ที่ละเอียด การแลกเปลี่ยนคือ markup และ styling conventions ที่ซับซ้อนกว่าเล็กน้อยเมื่อเทียบกับแนวทาง CSS pure ของ font icons

วิธีการทำงาน

ไฟล์ sprite คือ SVG document ปกติที่มี element <symbol> หนึ่งหรือมากกว่า แต่ละ symbol กำหนดไอคอนที่ self-contained ด้วย viewBox ของตัวเอง:

icons.svg (ไฟล์ sprite)
<svg xmlns="http://www.w3.org/2000/svg" style="display:none">
  <symbol id="icon-home" viewBox="0 0 24 24">
    <path d="M3 12l9-9 9 9M5 10v10a1 1 0 001 1h3a1 1 0 001-1v-4..."/>
  </symbol>
  <symbol id="icon-search" viewBox="0 0 24 24">
    <path d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/>
  </symbol>
</svg>

<svg> ภายนอกถูกซ่อนด้วย style="display:none" เพื่อไม่ให้ใช้พื้นที่ในหน้า symbols ภายในมองไม่เห็นจนกว่าจะถูกอ้างถึง ในการ render ไอคอน ใช้ element <use>:

การใช้ symbols ใน HTML
<svg class="icon"><use href="#icon-home"></use></svg>
<svg class="icon"><use href="#icon-search"></use></svg>

จัดรูปแบบไอคอนด้วย CSS โดยใช้ fill และ stroke แทน property color สำหรับ font:

CSS สำหรับ SVG icons
.icon {
  width: 24px;
  height: 24px;
  fill: currentColor;
  stroke: none;
}

การใช้ fill: currentColor ให้ไอคอนสืบทอดสีข้อความขององค์ประกอบแม่ คล้ายกับวิธีที่ font icons ทำงานกับ property color

Symbol เทียบกับ Font Icons

    ข้อดีของ Symbols
  • รองรับหลายสี — แต่ละ path มีสีเติมและ stroke ของตัวเอง
  • แต่ละไอคอนเป็น SVG element จริงที่มี accessibility ดีกว่า
  • ไม่ต้องการการแมป Unicode — อ้างถึงไอคอนด้วยชื่อที่อ่านได้
  • การ render คมชัดกว่า — ไม่มีปัญหา font hinting หรือ subpixel artifacts
  • ส่วนไอคอนแต่ละชิ้นสามารถสร้างแอนิเมชันได้แยกกัน
  • ใช้งานกับคุณสมบัติ SVG ทุกอย่าง: gradients, filters, clip-paths, masks
    ข้อเสียของ Symbols
  • Markup ละเอียดมากกว่า (<svg><use> เทียบกับ <i class="icon">)
  • จัดรูปแบบด้วย CSS color ได้ยาก — ต้องใช้ fill/stroke
  • External sprites มีผลกระทบด้าน CORS สำหรับการโหลดข้าม origin
  • ขนาดไฟล์รวมใหญ่กว่ารูปแบบฟอนต์ที่บีบอัด
  • น้ำหนัก HTML มากขึ้นต่อการใช้ไอคอนแต่ละครั้ง
  • ไม่รองรับ pseudo-element ::before/::after

กลยุทธ์การโหลด

มีสามวิธีหลักในการโหลด SVG symbol sprite เข้าสู่หน้า แต่ละวิธีมีการแลกเปลี่ยนที่แตกต่างกัน:

Inline sprite

วาง SVG sprite ทั้งหมดโดยตรงใน <body> HTML นี่เป็นแนวทางที่ง่ายที่สุด — ไม่มีปัญหา CORS ไม่มีคำขอ HTTP เพิ่มเติม symbols พร้อมใช้งานทันทีสำหรับการอ้างอิง <use> ใดก็ได้ในหน้า เหมาะที่สุดสำหรับ single-page applications หรือเมื่อมีชุดไอคอนขนาดเล็ก (ต่ำกว่า ~50 ไอคอน)

External sprite

โหลด sprite เป็นไฟล์ภายนอกผ่าน <use href="icons.svg#home"> สิ่งนี้ทำให้ HTML สะอาดและให้เบราว์เซอร์ cache sprite แยกจากหน้า อย่างไรก็ตามมีผลกระทบด้าน CORS: sprite ต้องให้บริการจาก origin เดียวกัน หรือเซิร์ฟเวอร์ต้องตั้งค่า header Access-Control-Allow-Origin ที่เหมาะสม โปรดทราบว่า Internet Explorer ไม่รองรับการอ้างอิง <use> ภายนอก — ใช้ polyfill svg4everybody ถ้าต้องการรองรับ IE

JS injection

โหลดไฟล์ sprite ผ่าน fetch() และ inject เข้า DOM ที่ runtime สิ่งนี้รวม cacheable ของ external sprites กับความน่าเชื่อถือของ inline sprites — SVG ที่ inject กลายเป็นส่วนหนึ่งของ document ดังนั้นการอ้างอิง <use> ทำงานโดยไม่มีข้อจำกัด CORS Bobcorn สร้างแนวทางนี้: ไฟล์ JS ที่ fetch และลงทะเบียน symbols ทั้งหมดเมื่อโหลด

แนวทาง JS injection (output ของ Bobcorn)
<!-- Load the generated JS sprite -->
<script src="icons-symbol.js"></script>

<!-- Then use normally: -->
<svg class="icon"><use href="#icon-home"></use></svg>
<svg class="icon"><use href="#icon-search"></use></svg>

ไฟล์ JS สร้าง element <svg> ที่ซ่อนซึ่งมีการกำหนด <symbol> ทั้งหมดและ append เข้ากับ document body เมื่อโหลดแล้ว ไอคอนถูกอ้างถึงเหมือนกับแนวทาง inline

เมื่อไรควรใช้ SVG Symbols

SVG symbol sprites เป็นตัวเลือกที่ถูกต้องเมื่อโปรเจกต์ของคุณต้องการความสามารถที่ font icons ไม่สามารถให้ได้:

  • ไอคอนหลายสี — เมื่อไอคอนใช้มากกว่าหนึ่งสี gradients หรือสีเติมที่ซับซ้อนที่ font glyph เดียวไม่สามารถแทนได้
  • Accessibility เป็นความสำคัญสูงสุด — แต่ละไอคอนสามารถรวม element <title> และ attribute aria-label ให้ screen readers มีคำอธิบายที่มีความหมาย
  • ส่วนไอคอนที่สร้างแอนิเมชันได้ — คุณต้องสร้างแอนิเมชัน paths หรือกลุ่มแต่ละชิ้นภายในไอคอน
  • โปรเจกต์ที่ใช้ SVG หนัก — แอปพลิเคชันของคุณใช้ inline SVG อย่างกว้างขวางอยู่แล้ว ดังนั้น symbols เหมาะกับสถาปัตยกรรมที่มีอยู่
  • ความคมชัดของการ render สูงสุด — font hinting อาจทำให้เกิดปัญหาการจัดตำแหน่งในขนาดเล็ก SVG symbols render ได้อย่างสมบูรณ์ในทุกมิติ

เมื่อไรควรยึดกับ Font Icons

Font icons ยังคงเป็นตัวเลือกที่ดีกว่าในหลายสถานการณ์ทั่วไป:

  • ชุดไอคอนขนาดใหญ่ (200+) — ไฟล์ฟอนต์ WOFF2 ที่บีบอัดมีขนาดเล็กกว่า SVG sprite ที่มีจำนวนไอคอนเท่ากันอย่างมีนัยสำคัญ
  • ไอคอนสีเดียวทั้งหมด — ถ้าทุกไอคอนเป็นสีเดียว font icons ให้การรวมที่ง่ายที่สุดโดยไม่มีการแลกเปลี่ยน
  • การรวม CSS เท่านั้น — font icons ต้องการเพียง stylesheet link และ CSS classes โดยไม่มี JavaScript หรือ markup เพิ่มเติม
  • ระบบ legacy — โปรเจกต์ที่ใช้ icon fonts อยู่แล้วไม่ได้รับประโยชน์พอเพียงจากการเปลี่ยนเพื่อพิสูจน์ความพยายามในการ migration
  • รองรับ pseudo-element — คุณต้องการไอคอนใน pseudo-elements ::before หรือ ::after ซึ่งทำงานได้เฉพาะกับ font glyphs
ใน Bobcorn
Bobcorn สามารถส่งออกไอคอนของคุณเป็นไฟล์ JS symbol sprite ควบคู่กับไฟล์ฟอนต์ เปิดใช้งานตัวเลือก JS ในกล่องโต้ตอบการส่งออก ไฟล์ที่สร้างจะสร้าง SVG sprite inline และลงทะเบียน symbols ทั้งหมดเมื่อโหลด คุณสามารถใช้ทั้งสองแนวทางในโปรเจกต์เดียวกัน — fonts สำหรับ UI icons ง่ายๆ, symbols สำหรับ colored illustrations ที่ซับซ้อน
เคล็ดลับ
คุณไม่จำเป็นต้องเลือกอย่างใดอย่างหนึ่ง ระบบออกแบบจำนวนมากใช้ font icons สำหรับไอคอน UI สีเดียวส่วนใหญ่ (ปุ่ม navigation, form elements) และ SVG symbols สำหรับ illustrations สีซับซ้อนหรือไอคอนที่มีแอนิเมชันจำนวนหนึ่ง กล่องโต้ตอบการส่งออกของ Bobcorn ให้คุณสร้างทั้งสองในการส่งออกครั้งเดียว