Mark Ku's Blog

Why Use SVG & SVG Sprite?

  • When a browser scales a raster image, it becomes blurry and pixelated.
  • Loading dozens of tiny icons as separate HTTP requests puts pressure on the server and slows down the page. Combining them reduces the number of requests and speeds up load time.

What Is SVG?

Open an SVG file in a text editor and you'll see that it stores paths and colors as text, structured very much like HTML — a tree of tags and attributes. Because of this, the same graphic can be scaled to any size without losing quality.

Syntax-highlighted SVG code defining paths, filters, and gradients
Syntax-highlighted SVG code defining paths, filters, and gradients

Pros and Cons

Pros

  1. No pixelation — vector-based, scales cleanly at any size
  2. Text within the image is selectable and copyable
  3. Colors can be changed via CSS

Cons

  1. File size is slightly larger than raster equivalents (best suited for simple icons)
  2. Not supported in older browsers (e.g., IE 11)

Ways to Load SVG Sprite in a Website

Method 1 — CSS Sprite: combine icons into one image and use background-position to show each one

.icon-match-event-3 {
  width: 24px;
  height: 24px;
  zoom: 0.8;
  background-position: -28px -4px;
  background-repeat: no-repeat;
  background-thumbnail: url(~@/assets/images/icon/match-event/match-event.svg);
}

Method 2 — Inline SVG Sprite: merge all SVG paths into a single <svg> element rendered in the HTML, and switch icons via :xlink:href=#targetId

SVG code snippet defining multiple icons within a sprite
SVG code snippet defining multiple icons within a sprite
  <svg :class="svgClass" aria-hidden="true">
    <use :xlink:href="`#${svgId}`" />
  </svg>

Special SVG Behaviors to Know

  1. When SVGs are loaded, the CSS display defaults to none — they won't appear on the page unless you explicitly set a display value. MDN SVG display attribute
  2. When the page is zoomed, SVGs can escape the normal document flow. DevTools may not reflect the zoomed dimensions accurately.
  3. SVG files are plain text and can be opened and edited in any text editor — the structure is HTML-like.
  4. Compressing SVG file size: drawing tools often produce SVGs with many unused attributes that bloat file size. A webpack plugin can strip these. Example: vue-svgo-loader

Simplifying SVG Loading in a Vue Project

To use icons as conveniently as icon fonts, we use an SVG loader.

Install

npm install svg-sprite-loader --save-dev
npm install svgo svgo-loader --save-dev

Update vue.config.js

chainWebpack: (config) => {
    config.module
      .rule('svg')
      .exclude.add(resolve('src/assets/images/svg-icon'))
      .end()

    config.module
      .rule('icons')
      .test(/\.svg$/)
      .include.add(resolve('src/assets/images/svg-icon'))
      .end()
      .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      .options({
        symbolId: 'icon-[name]',
        extract: true,
        outputPath: 'static/img/',
        publicPath: 'static/img/',
        spriteFilename: 'main.svg'
      })
      .end()
      .use('svgo-loader') // 最佳化 svg (優化寫法及移除不需要的 attibute , 約可以減少30% 以上的圖檔大小)
      .loader('svgo-loader')
      .end()

    config.plugin('svg-sprite') // extract: true 才需要
      .use(require('svg-sprite-loader/plugin')) 
}

Create the SvgIcon Vue Component

<template>
  <svg :class="svgClass" aria-hidden="true">
    <use :xlink:href="`#icon-${iconName}`" />
  </svg>
</template>

<script>

export default {
  name: 'SvgIcon',
  props: {
    iconName: {
      type: String,
      default: '',
      required: false
    }
  },
  data: function() {
    return {

    }
  },
  computed: {
    svgClass() {
      if (this.iconClass) {
        return 'svg-icon ' + 'icon-' + this.iconClass
      } else {
        return 'svg-icon'
      }
    }
  }

}
</script>

<style>
.svg-icon {
  display: inline-block;
  overflow: hidden;
  width: 32px;
  height: 32px;
  fill: currentColor;
}
</style>

Load main.svg in the Root App Component


<template>
  <div>
    <Layout id="app" />
    <span v-if="htmlSvgString.length" v-once id="mainSvg" v-html="htmlSvgString" />
  </div>
</template>

<script>
import Layout from '@/views/layout'
export default {
  components: { Layout },
  data: function() {
    return {
      htmlSvgString: ''
    }
  },
  created() {
    const that = this
    fetch('./static/images/main.svg')
      .then(r => r.text())
      .then(text => {
        that.htmlSvgString = text
      })
  }
}
</script>


<style lang="scss">
#mainSvg {
  position: absolute;
  width: 0;
  height: 0;

  svg {
    position: absolute;
    width: 0;
    height: 0;
  }
}

// 如果要改色,要指定id,原本的顏色會掉,會吃父層的顏色
 #icon-dropdown_b {
   path {
     fill: currentColor;
   }
 }
</style>

Register Globally in main.js

import SvgIcon from '@/components/SvgIcon'
Vue.component('Icon', SvgIcon)

// 引入至 web pack 
const requireAll = requireContext => requireContext.keys().map(requireContext)
const req = require.context('@/assets/images/svg-icon', true, /\.svg$/)
requireAll(req)

Place Your SVG Files in the svg-icon Folder

Usage in Templates

// icon-name 填入 icon 的檔案名稱
<SvgIcon :icon-name="getIconFileName(tab)" class="tab-icon" />

Additional Notes

  1. If you can't change an SVG's color, check whether the inner <path> elements have a hardcoded fill color — change it to currentColor:
 #icon-dropdown_b {
   path {
     fill: currentColor;
   }
 }
  1. To bundle icons into multiple sprites organized by subfolder, see Generating Multiple Sprites.
  2. Icon fonts only support single colors. You can upload SVG files to IcoMoon to generate an icon font.
  3. Windows Explorer cannot preview SVG files by default. Install svg-explorer-extension to enable previews.

Author

Mark Ku

擁有 10+ 年經驗的資深軟體工程師,現為 AI 應用 Builder,專注於大型平台架構與簡化複雜系統設計,從電商系統到訂閱與收費平台,結合 AI Agent、AI 整合與自動化開發,打造高效率且可持續演進的產品技術基礎。Read More

Found this useful?

The author's free tools, daily podcasts and newsletter are all here.

Mark Ku · This article is licensed under CC BY 4.0. Credit the author and link back to the original when reusing it.

Comments

Subscribe to Newsletter

Subscribe to get new posts delivered instantly — never miss a tech share.

By submitting, you agree to receive emails. You can anytime.

Popular Posts

View all
Mark Ku
··602

Oracle Cloud Always Free Tier: Linux Host and Static IP for a $0 Cloud Solution

Oracle Cloud Always Free Tier: Linux Host and Static IP for a $0 Cloud Solution
Mark Ku
··490

Say Goodbye to Postman's Fee Trap! A Hands-on Guide to Bruno, the Open-Source Git-Native API Testing Powerhouse.

Say Goodbye to Postman's Fee Trap! A Hands-on Guide to Bruno, the Open-Source Git-Native API Testing Powerhouse.
Mark Ku
··333

A Free, Open-Source, Notion-like Knowledge Base — A Complete Guide to Deploying and Backing Up Outline Wiki

A Free, Open-Source, Notion-like Knowledge Base — A Complete Guide to Deploying and Backing Up Outline Wiki
Mark Ku
··264

Training Your Own AI Voice: Hardware Requirements, Open-Source Model Comparison, and LoRA Fine-Tuning

Training Your Own AI Voice: Hardware Requirements, Open-Source Model Comparison, and LoRA Fine-Tuning
Mark Ku
··221

Building an Efficient API Management Platform: Deploying Kong Gateway from Scratch - Part 1

Building an Efficient API Management Platform: Deploying Kong Gateway from Scratch - Part 1
Mark Ku
··215

Setting Up Samba on Ubuntu to Share Folders with Windows 11

Setting Up Samba on Ubuntu to Share Folders with Windows 11