SVG profile

SVG, short for Scalable Vector Graphics, is an XML markup language for describing two-dimensional Vector Graphics. SVG graphics do not depend on resolution, so the graphics do not show significant jagged edges when zoomed in.

icon sprite

When we need to use multiple ICONS, in order to save requests and facilitate management, we usually combine the ICONS into one file, and then take out the required graphics from the icon set file and display them through certain methods. The most commonly used CSS Sprite and Icon Font are familiar.

CSS Sprite

The principle of CSS Sprite is to arrange multiple ICONS into an image file according to certain rules, and use background-image and background-position to display specific parts of the image. CSS Sprite technology has been widely used for a long time, and there are many tools available to automate Sprite images and CSS files, such as gulp.spritesmith [github.com/twolfson/gu…] .

.icon1 {
    background-image: url(/res/icon1.png)
}
.icon1-increase {
    background-position: -10px -10px;
}Copy the code
<i class="icon1 icon1-increase"/>Copy the code

CSS Sprite is mature and compatible, but its disadvantages are obvious. In actual demand, corresponding ICONS with the same shape but different colors need to be saved for each icon with different colors; Sometimes when we need to enlarge the display of an existing icon, we find that the serrations are serious, so we need to save another enlarged version of the icon. As a result, Sprite files get bigger and bigger over time, while the content gets messier and harder to manage.

Icon Font

The basic principle of Icon Font is to define an Icon as a picture Font. In the CSS, @font-face is used to introduce a custom Icon Font, and the Font family and character code are used to display the specified Icon.

@font-face {
    font-family: 'iconfont';
    src: url(/res/icon2.ttf) format('truetype');
}
.icon2 {
    font-family: 'iconfont';
}Copy the code
<i class="icon2">& # 33</i>Copy the code

Since the font is used, the style of the icon can be set through color, font size. Icon Fonts have a smaller file size than CSS Sprite images and are easier to maintain than images, but Icon Fonts are usually limited to a single color and Font file generation is more complex than CSS Sprite.

SVG Sprite

Usually when using SVG, we write directly to the SVG tag:

    <svg xmlns="http://www.w3.org/2000/svg" width="150" height="100" viewBox="0 0 3 2">
        <rect width="1" height="2" x="0" fill="#008d46" />
        <rect width="1" height="2" x="1" fill="#ffffff" />
        <rect width="1" height="2" x="2" fill="#d2232c" />
    </svg>Copy the code

At this point, the SVG graphics will be displayed directly on the page. SVG attributes can use (symbol)[developer.mozilla.org/zh-CN/docs/… and (use)[developer.mozilla.org/zh-CN/docs/… to achieve SVG Sprite functionality.

SVG Sprite

<svg style="height:0; width:0; display:none;" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <symbol id="icon-italy" width="150" height="100" viewBox="0 0 3 2">
        <rect width="1" height="2" x="0" fill="#008d46" />
        <rect width="1" height="2" x="1" fill="#ffffff" />
        <rect width="1" height="2" x="2" fill="#d2232c" />
    </symbol>

    <symbol id="icon-france" width="150" height="100" viewBox="0 0 3 2">
        <rect width="1" height="2" x="0" fill="# 002496" />
        <rect width="1" height="2" x="1" fill="#ffffff" />
        <rect width="1" height="2" x="2" fill="#ee2839" />
    </symbol>
</svg>

<svg><use xlink:href="#icon-italy"/></svg>
<svg><use xlink:href="#icon-france"/></svg>Copy the code

This gives you an SVG Sprite.

The principle of

As you can see from Devtool, the use tag is implemented using shadow DOM.

use.shadowdom

It refers to the specified SVG Symbol via the Xlink :href XML attribute, and the contents of the specified symbol tag are rendered on the page at render time. This means that shadow DOM in the Use tag cannot be accessed and modified directly. Selectors like use#rect, for example, are not valid, so you can’t control different parts of the use image through normal CSS selectors.

CSS styles

More often than not, we just need to change the size and color of the icon, which in SVG Sprite is not complicated to implement.

  1. The size of the

Icon size can be easily controlled by changing the size of the SVG container.

.icon{
    width: 120px;
    height: 80px;
}
.icon.icon-small{
    width: 60px;
    height: 40px;
}Copy the code
<svg class="icon"><use xlink:href="#icon-italy"/></svg>
<svg class="icon icon-small"><use xlink:href="#icon-italy"/></svg>Copy the code

svg.icon.size

  1. color
  • monochromatic

Since you cannot directly select the graphic label in use’s Shadow root, you need to use the fill: Inherit property to define the color for the icon.

svg path{
    fill: inherit;
}
.icon2-green{
    fill: #008d46;
}
.icon2-red{
    fill: #dc352f;
}Copy the code
<svg class="icon2 icon2-green">
    <use xlink:href="#icon-increase"/>
</svg>
<svg class="icon2 icon2-red">
    <use xlink:href="#icon-increase"/>
</svg>Copy the code

svg.icon.color

Inherit, you can also define stroke-width, stroke, and other attributes.

  • multicolor

In addition to defining the overall color of the icon, you can also define the color of different parts of the graph as required. CSS Custom Properties are used here.

Here we need to modify icon.svg by setting the color of each part of the image to fill: var(–*[, default]).

<symbol id="icon-flag" width="150" height="100" viewBox="0 0 3 2">
    <rect width="1" height="2" x="0" style="fill: var(--color0, #008d46)" />
    <rect width="1" height="2" x="1" style="fill: var(--color1, #fff)"/>
    <rect width="1" height="2" x="2" style="fill: var(--color2, #d2232c)"/>
</symbol>Copy the code

Defining CSS styles

.flag-belgium {
    --color0: #201b18;
    --color1: #f1ee3d;
    --color2: #dc352f;
}Copy the code
<svg class="icon">
    <use xlink:href="#icon-flag"/>
</svg>
<svg class="icon flag-belgium">
    <use xlink:href="#icon-flag"/>
</svg>Copy the code

svg.icon.color.parts

In addition, there are some other Styling definitions available. Read Styling SVG Content with CSS for more details.

The actual use

Referencing external SVG

The previous article described using inline SVG, but you can use external SVG as well.

<svg class="icon">
    <use xlink:href="/res/svg/icon.svg#icon-flag"/>
</svg>Copy the code

This approach is not compatible with IE9~10, but if you must use external SVG, you can introduce pollyFillSvg4Everybody. When running without external SVG support, this Pollyfill will load the SVG board file and inject it into the page via an asynchronous request. Convert the reference method to inline SVG.

Used in FTL

You can define a series of macros in svg.ftl to load.svg files.

<#macro svgicon path>
    <#include "${path} ">
</#macro>

<#macro svgicon3 >
    <@svgicon "./icon3.svg"/ >
</#macro>Copy the code

Reference demo.ftl in the page:

<@svgicon1/>
<svg>
    <use xlink:href="#icon-italy"/>
</svg>Copy the code

Used in regular

Xlink :href is a namespaced XML feature that, if written on an.html page, is properly parsed by the browser and rendered in SVG. If the SVG variable is created using the DOM API, it needs to be processed in a special way (SVG with USE Tag not rendering).

The createElementNS and setAttributeNS methods are used to declare the namespace along with the creation.

var use = document.createElementNS('http://www.w3.org/2000/svg'.'use');
use.setAttributeNS('http://www.w3.org/1999/xlink'.'xlink:href'.'#icon-increase');
document.querySelector('#svgid').appendChild(use);Copy the code

This method is used to instantiate elements in an SVG Sprite whenever a use element needs to be created dynamically. However, in current Regular(0.4.3), namespaces are not handled, which means that < SVG >

will not render properly if written directly to the template of a Regular component. To do this, you can add a directive r-xlink:href to manually set the namespace.

Regular.directive('r-xlink:href'.function (elem, val) {
    if (val&& val.type === 'expression') {
        this.$watch(val, function (newVal) {
            elem.setAttributeNS('http://www.w3.org/1999/xlink'.'href', newVal);
        });
    } else {
        elem.setAttributeNS('http://www.w3.org/1999/xlink'.'href', val); }});Copy the code

You can then use SVG Sprite in the component template just as you would in normal.html. Of course, first make sure that the SVG Sprite is written to the page.

<svg>
    <use r-xlink:href="#icon-italy"/>
</svg>Copy the code

I would like to express my gratitude to Zheng Haibo for his advice in Regular’s SVG practice. Otherwise, I would have to go a long way to solve the problem.

summary

SVG has obvious advantages over the CSS Sprite and Icon Font mentioned above:

  • Zoom in and out without distortion
  • Size, color and other attributes are flexible to customize
  • Small volume, convenient management

While SVG Sprite has a high degree of flexibility, at the same time, SVG compatibility is tricky, rendering performance is not as good as images and fonts, and may not be appropriate in some cases. However, in general scenarios, SVG Sprite can be very handy for development.

reference

  1. SVG Element Reference
  2. SVG with USE tag not rendering
  3. Future will be hot: SVG Sprite technology introduction
  4. Styling SVG Content with CSS
  5. Icon System with SVG Sprites