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 ของตัวเอง:
<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>:
<svg class="icon"><use href="#icon-home"></use></svg>
<svg class="icon"><use href="#icon-search"></use></svg>
จัดรูปแบบไอคอนด้วย CSS โดยใช้ fill และ stroke แทน property color สำหรับ font:
.icon {
width: 24px;
height: 24px;
fill: currentColor;
stroke: none;
}
การใช้ fill: currentColor ให้ไอคอนสืบทอดสีข้อความขององค์ประกอบแม่ คล้ายกับวิธีที่ font icons ทำงานกับ property color
Symbol เทียบกับ Font Icons
- รองรับหลายสี — แต่ละ path มีสีเติมและ stroke ของตัวเอง
- แต่ละไอคอนเป็น SVG element จริงที่มี accessibility ดีกว่า
- ไม่ต้องการการแมป Unicode — อ้างถึงไอคอนด้วยชื่อที่อ่านได้
- การ render คมชัดกว่า — ไม่มีปัญหา font hinting หรือ subpixel artifacts
- ส่วนไอคอนแต่ละชิ้นสามารถสร้างแอนิเมชันได้แยกกัน
- ใช้งานกับคุณสมบัติ SVG ทุกอย่าง: gradients, filters, clip-paths, masks
- 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 ทั้งหมดเมื่อโหลด
<!-- 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>และ attributearia-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