The author | week sauce

This article was written in January 2020. First in zhouzhoujiang personal blog, reproduced please indicate the source.

Managing ICONS is a common problem in web project development. With the development of Web technology, icon schemes have gone through several stages. The following icon schemes can also cover the process of using Web ICONS.

image sprite

At first, ICONS were referenced by img tags or background-image, and each icon was referenced separately. Later, in order to reduce HTTP requests and improve website performance, Sprite was proposed to combine small PNG images into a single image. Then display different images according to background-position.

Advantage:

  1. Good compatibility
  2. Reduction degree is high,

Disadvantage:

  1. Different colors of the same icon require multiple images
  2. New ICONS need to be recomposed from Sprite
  3. Since bitmaps are compatible with different resolutions, multiple sizes are required

iconfont

The IconFont scheme was developed to make it easier to control the color and size of ICONS and to work with various device screens. Iconfont is an iconfont. You can use it just like a normal font. You can easily control the size and color of an icon by using font size and color, as long as the CSS properties that are appropriate for the font are appropriate for the font icon. With the emergence of various font icon library websites, icomon. IO abroad, or domestic Ali iconfont.cn, brought a full set of solutions, make iconfont popular.

Advantage:

  1. Easy to change icon color, size
  2. Vector graphics are not distorted
  3. Compatible with all popular browsers, it can be used on BOTH H5 and APP
  4. Replacing and adding ICONS is also easy, and there is no need to worry about icon merging

Disadvantage:

  1. Only monochrome ICONS are supported
  2. Font rendering, low – magnification screen is easy to appear jagged

Reference way

Iconfont is also easy to use, using @font-face to introduce a font format just like any other custom font.

@spicons-font-path: "./fonts";
@font-face {
	font-family: "spicons";
	src: url('@{spicons-font-path}/spicons.eot? v=1');
	src: url('@{spicons-font-path}/spicons.eot? v=1#iefix') format('eot'),
    	url('@{spicons-font-path}/spicons.ttf? v=1') format('truetype'),
		url('@{spicons-font-path}/spicons.woff? v=1') format('woff'),
		url('@{spicons-font-path}/spicons.svg? v=1#spicons') format('svg');
}
.sp-icon {
	font-family: "spicons";
    display: inline-block;
    font-style: normal;
    font-weight: normal;
    font-variant: normal;
    text-transform: none;
    text-rendering: auto;
    line-height: 1;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}
Copy the code
  • Unicode reference
<div class="sp-icon">&#xE001;</div>
Copy the code
  • Use the matching generated styles
<link rel="stylesheet" href="./iconfont.css">
<span class="sp-icon icon-xxx"></span>
Copy the code

Engineering mode

Relying on web sites to generate font files and having to re-write the icon CSS code in your project after replacing or adding ICONS is not automated enough. You can use tool scripts to generate iconFont from SVG files in your local project to make it easier to manage project ICONS. The following dependency libraries need to be installed in your project.

  • Gulp (Automated Build Tool)
  • Gulp-iconfont (using gulp to create SVG/TTF /eot/woff/woff2 font)
  • Gulp-iconfont CSS (combined with gulp-iconfont to generate matching CSS styles)

gulpfile

var gulp = require('gulp');
var iconfont = require('gulp-iconfont');
var iconfontCss = require('gulp-iconfont-css');

/** Generates the icon font file */
gulp.task('Iconfont'.function() {
    return gulp
        .src(['.. /src/icons/svg/*.svg'])
        .pipe(
            iconfontCss({
                fontName: 'spicons'./ / font name
                path: '.. /src/icons/templates/iconFont.less'.// Template file path
                targetPath: '.. /spicons-icons.less'.// Style file target address relative to dest directory
                cssClass: 'sp-icon' // Style class name
            })
        )
        .pipe(
            iconfont({
                fontName: 'spicons'.// required
                formats: ['ttf'.'eot'.'woff'.'svg']
            })
        )
        .pipe(gulp.dest('.. /src/styles/iconfont/fonts'));
});


gulp.task('default',gulp.series('Iconfont'));
Copy the code

Gulp-iconfont CSS supports the use of custom CSS templates, to organize the generated font style, to create a flexible way to conform to the project specification style name, reference path.

  • Less template
@spicons-font-path: "./fonts";
@font-face {
	font-family: "<%= fontName %>";
	src: url('@{spicons-font-path}/<%= fontName %>.eot? v=1');
	src: url('@{spicons-font-path}/<%= fontName %>.eot? v=1#iefix') format('eot'),
    	url('@{spicons-font-path}/<%= fontName %>.ttf? v=1') format('truetype'),
		url('@{spicons-font-path}/<%= fontName %>.woff? v=1') format('woff'),
		url('@{spicons-font-path}/<%= fontName %>.svg? v=1#<%= fontName %>') format('svg');
}

.<%= cssClass%> {
	font-family: "<%= fontName %>";
    display: inline-block;
    font-style: normal;
    font-weight: normal;
    font-variant: normal;
    text-transform: none;
    text-rendering: auto;
    line-height: 1;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale; } < % _.each(glyphs, function(glyph) { %>@icon-<%= glyph.fileName.replace(/[\d]{1,} ([\] -) /, "") % > :"\<%= glyph.codePoint %>"; The < %}); %> .<%= cssClass%>-char(@icon-variable) {
	content: @@icon-variable;
}

.<%= cssClass%>-base-pseudo(@filenameThe @insert: before) {
	@pseudo-selector: ~":@{insert}";
    @icon-variable: ~"icon-@{filename}";
	&@{pseudo-selector} {
		.<%= cssClass%>-char(@icon-variable);
	}
}

<% _.each(glyphs, function(glyph) { 
    %>.<%= cssClass%>-<%= glyph.fileName.replace(/[\d]{1,} ([\] -)/, "") %> {
	.<%= cssClass%>-base-pseudo(<%= glyph.fileName.replace(/[\d]{1,} ([\] -) /, "") % >); } < %}); % >Copy the code
  • Run the build icon command gulp –gulpfile build/build-icon.js

  • Generate font ICONS and style files

  • The style file

svg sprite

SVG stands for scalable vector graphics. Unlike bitmaps, which are distorted by magnification, SVG looks equally sharp at different resolutions. SVG has been around for a long time, but it wasn’t really used to its full potential due to compatibility issues, but with ie6/7/8 gone and Android 4.x starting, many websites started using SVG as an icon scheme. Github replaced iconfont with SVG in 2016, and Ant Design replaced iconfont with an SVG icon after 3.9.0.

Advantage:

  1. Easy to change icon color, size
  2. Support for color ICONS
  3. Vector graphics are not distorted
  4. Good readability, conducive to SEO and accessibility
  5. Good rendering effect, no jagged

Disadvantage:

  1. It is larger than iconfont

Introducing way

  1. Use img, Object, and Embed tags either to reference SVG directly as a background image, or to incorporate Sprite images in the same way as PNG Sprite images.
  2. Inline SVG, SVG itself is an HTML tag, and you can write SVG directly to HTML.
<body>
  <div>
    <svg>.</svg>
  </div>
</body>
Copy the code
  1. Use the SYMBOL and use elements in SVG to create ICONS

The tag defines an image template that does not output any images of its own. You can instantiate it using the tag. In a real project we would have a lot of ICONS and merge the fragments of SVG, each icon would have a unique symbol and be referenced by symbol. Insert the Symbol definition into the body of the page, and then pass the reference where needed. Set xlink:href to the defined symbol ID.

<svg style="display: none;">
	<symbol viewBox="0 0 16 16" id="icon-bell">
		<path fill="#ffa896" d="M14,12 L15.5,12 C15.7761424,12 16 12.2238576, 12.12.C16,12.7761424 15.7761424,13 15.5,13 L0.5,13 C0.223857625,13 3.38176876E-17,12.7761424,12.2238576 0.223857625,12 0.5,12 L0.5,12 L2,12 L2,6 C2,2.6862915 4.6862915,6.08718376e-16 8,0 C11.3137085,-6.08718376e-16 14,2.6862915 14,6 L14,12 Z M3,12 L13,12 L13,6 C13,3.23857625 10.7614237,1 8,1 C5.23857625,1 3,3.23857625 3,6 L3,12 Z M8,16 C6.8954305,16 6,15.1045695,14 C7,14 9,14 10,14 C10, 15.1045695 9.1045695, 16 August 16th Z"></path>
	</symbol>
  <symbol viewBox="0 0 16 16" id="icon-arrow-up">
		<path fill="#ffa896" d="M413.1, 327.3 l - 1.8-2.1 l - 136-156.5 - c - 4.6-5.3-11.5-8.6-19.2-8.6 - c - 7.7, 0-14.6, 3.4, 19.2, 8.6 L101, 324.9 l - 2.3, 2.6 C97, 330,96,333,96,336.2 c0, 8.7, 7.4, 15.8, 16.6, 15.8 v0h286. 8 v0c9. 2,0,16.6-7.1, 16.6 15.8 C416, 332.9, 414.9, 329.8, 413.1, 327.3 z"></path>
	</symbol>
</svg>
Copy the code
<svg>
	<use xlink:href="#icon-arrow-up"/> 
</svg>
<svg>
	<use xlink:href="#icon-bell"/> 
</svg>
Copy the code

Symbol can be written to the body, and can be referenced with an outer chain, but using the outer chain is not compatible with IE.

<svg>
	<use xlink:href="/assets/svg-symbols.svg#icon-arrow-up"/> 
</svg>
Copy the code

Engineering mode

It is not convenient to import that batch of symbol template manually, what we need is automatic icon management. As Webpack packaging matures, various loaders appear, providing us with mature solutions.

  • svg-sprite-loader

For the SVG file referenced, svG-Sprite-loader will stuff your icon into each symbol and eventually embed the merged symbol in your body.

The example project is set up using vue CLI 3. The configuration of vue.config.js is as follows. We will put the icon file in a specific directory, and use SVG-sprite-loader to exclude the default loader configuration for files in this directory.

chainWebpack:config= > {  
        config.module
          .rule('svg')
          .exclude.add(resolve('src/icons'))
          .end()
        config.module
          .rule('icons')
          .test(/\.svg$/)
          .include.add(resolve('src/icons'))
          .end()
          .use('svg-sprite-loader')
          .loader('svg-sprite-loader')
          .options({
            symbolId: 'icon-[name]'
          })
          .end()
      }
Copy the code
  • Import icon files in batches
const req = require.context('/src/icons'.true./\.svg$/)
const requireAll = requireContext= > requireContext.keys().map(requireContext)
requireAll(req)
Copy the code
  • After running the project, you can see that the SVG Symbol is inserted into the body

  • We can use these ICONS in the page, at the same time can encapsulate the general icon call component, icon name, size, color as parameters, can easily control the use of ICONS.
<template>
<i :style="styles" :class="iconClass">
  <svg class="svg-icon" aria-hidden="true" v-on="$listeners">
    <use :xlink:href="iconName" />
  </svg>
</i>
</template>

<script>
export default {
  name: 'SvgIcon'.props: {
    type: String.size: [Number.String].color: String.className:String
  },
  computed: {
    iconName() {
      return `#icon-The ${this.type}`
    },
    iconClass() {
      if (this.className) {
        return 'icon ' + this.className
      } else {
        return 'icon'}},styles() {
      let style = {}
      if (this.size) {
        style['font-size'] = `The ${this.size}px`
      }
      if (this.color) {
        style.color = this.color
      }
      return style
    },
  },
}
</script>
<style scoped>
.icon{
  display: inline-block;
  line-height: 0;
}
.svg-icon {
  width: 1em;
  height: 1em;
  fill: currentColor;
  overflow: hidden;
  vertical-align: middle;
}
</style>
Copy the code
<svg-icon type="bell" size="60" color="#ffa896"/>
Copy the code

summary

Each solution has its advantages and disadvantages. One solution may not be compatible with all scenarios. It all depends on the actual situation of the project and the support of the browser.