SVG notes

Some notes on working with <svg> that you may not know and that will be useful.

Resources

Icons (free):

URL-encoder:

SVG optimization:

Vectorization (Image → SVG):

Is it necessary to use the attribute xmlns="http://www.w3.org/2000/svg"?

In half of the SVG examples I see on the Internet, the code is wrapped in simple tags <svg></svg>. In the other half, the SVG tags have many attributes, for example:

<svg
	xmlns="http://www.w3.org/2000/svg"
	xmlns:xlink="http://www.w3.org/1999/xlink"
	version="1.1"
>

Which of the SVG attributes are really needed?

  • If you are embedding SVG code directly into HTML and the HTML is served with the header text/html, then the xmlns attributes can be omitted.

    However, if when serving HTML, which embeds SVG code, you specify a different type (response header) such as image/svg+xml, application/xhtml+xml or any other that forces the user agent to use an XML parser, then the xmlns attributes are mandatory!

    Note: Embedding SVG into HTML documents became possible in HTML5.

    More details: https://stackoverflow.com/questions/18467982/are-svg-parameters-such-as-xmlns-and-version-needed

  • All browsers ignore the version attribute, so you can always omit it.

How to inherit the color of the parent element in SVG

There are several SVG images that need to be inserted into a CSS-styled HTML page. It is necessary for the SVG elements to inherit color from the color attribute of the parent HTML element. The options: style="fill: inherit" or fill="inherit" do not work.

The problem here is that HTML uses color, while SVG uses fill and stroke.

To take the color from the parent element, you can make fill and stroke use the value of the color property from CSS. For this, there is a special value in CSS called currentColor. fill understands this value:

<svg ... fill="currentColor">

IMPORTANT: this technique will only work if the SVG is embedded in the HTML code itself and not included as a file. Because the file code is encapsulated within the file and knows nothing about external data, thus currentColor has nothing to reference.

Browser Support:

SVG sprites

node.js library for creating sprites: https://github.com/svg-sprite/svg-sprite

Sprites allow you to combine several SVG codes into one. And then refer to individual icons (SVG) without adding the entire SVG code again in HTML.

How to create a sprite?

Suppose we have two SVG icons:

<svg height="24px" width="24px" viewBox="0 0 24 24" fill="currentColor">
	<path d="M19 13H5v-2h14v2z"/>
</svg>
<svg height="24px" width="24px" viewBox="0 0 24 24" fill="currentColor">
	<path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</svg>

To make a sprite from them, you need to:

  1. Create an SVG element (container).

    <svg style="display: none;" aria-hidden="true">
    </svg>
  2. Replace the original SVG code with a symbol. Also, add the id attribute (which we will refer to SVG later).

    This code:

    <svg height="24px" width="24px" viewBox="0 0 24 24" fill="currentColor">
    	<path d="M19 13H5v-2h14v2z"/>
    </svg>

    will be transformed into:

    <symbol id="minus" height="24px" width="24px" viewBox="0 0 24 24" fill="currentColor">
    	<path d="M19 13H5v-2h14v2z"/>
    </symbol>
  3. Place the symbol in the container (in the sprite).

    <svg style="display: none;">
    
    	<symbol id="minus" height="24px" width="24px" viewBox="0 0 24 24" fill="currentColor">
    		<path d="M19 13H5v-2h14v2z"/>
    	</symbol>
    
    	<symbol id="plus" height="24px" width="24px" viewBox="0 0 24 24" fill="currentColor">
    		<path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
    	</symbol>
    
    </svg>

Now you can add this code to HTML, and then display an individual icon by referring to it by id:

<svg height="50" width="50"><use xlink:href="#minus"></use></svg>

Or you can create a file from this code, for example, sprite.svg and also display an individual icon by referring to it by id:

<svg height="50" width="50"><use xlink:href="/sprite.svg#minus"></use></svg>

The difference between these two approaches, among other things:

  • When we add SVG to the HTML code of the page, the sprite becomes part of the DOM tree, and therefore the sprite elements can have their color specified via CSS or can inherit color from the parent element - thanks to the attribute fill="currentColor".

  • And when the sprite is included as a file, the file is an external element, and therefore its elements are not connected to the current DOM tree, and they cannot have their color specified via CSS or inherit color from parents.

Therefore, it is better to include the sprite directly in HTML, especially if the sprite is small. It is also important to hide the container so that the browser does not try to render it. This can be done by adding style="display: none;" to the container.

<svg style="display: none;" aria-hidden="true">
	<symbol id="minus" viewBox="0 0 24 24" fill="currentColor">
		<path d="M19 13H5v-2h14v2z"/>
	</symbol>
</svg>

A more sophisticated container structure that is suggested on the internet, I haven't investigated its advantages, but it might be better to use it:

<svg
	aria-hidden="true"
	style="position: absolute; width: 0; height: 0; overflow: hidden;"
	xmlns="http://www.w3.org/2000/svg"
	xmlns:xlink="http://www.w3.org/1999/xlink"
>
	<defs>
		<symbol ...>
		<symbol ...>
		<symbol ...>
	</defs>
</svg>

The property stroke-dasharray

Defines the structure of dashes and gaps used to draw the outline of a shape.

The attribute stroke-dasharray can be used as a CSS property.

Syntax:
// SVG (HTML) attribute
stroke-dasharray="none | [dasharray]"
// CSS
stroke-dasharray: none | [dasharray];
[dasharray]

A list of numbers specifying the length of dashes and the length of gaps. Specified by commas or spaces.

stroke-dasharray="3 1";      // 3 dash length, 1 gap length
stroke-dasharray="3 1, 2 1"; // 3 dash length, 1 gap length, 2 dash, 1 gap

Percentage values can be specified:

stroke-dasharray="3 1%"

If an odd number of values is specified, the list of values is repeated to obtain an even number of values. Thus 5 3 2 will turn into 5 3 2 5 3 2:

stroke-dasharray="5 3, 2"

// will turn into
stroke-dasharray="5 3, 2 5, 3 2"
Example:
<svg viewBox="0 0 30 10" stroke="tomato" style="width: 10em;">

	<!-- No dashes nor gaps -->
	<line x1="0" y1="1" x2="30" y2="1" />

	<!-- Dashes and gaps of the same size -->
	<line stroke-dasharray="4"  x1="0" y1="3" x2="30" y2="3"/>

	<!-- Dashes and gaps of different sizes -->
	<line stroke-dasharray="4 1"  x1="0" y1="5" x2="30" y2="5"/>

	<!-- Dashes and gaps of various sizes with an odd number of values -->
	<line stroke-dasharray="4 1, 2"  x1="0" y1="7" x2="30" y2="7"/>

	<!-- Dashes and gaps of various sizes with an even number of values -->
	<line stroke-dasharray="4 1, 2 3"  x1="0" y1="9" x2="30" y2="9"/>
</svg>

We will get:

Example of a Pie Chart (pie-chart) in SVG using the stroke-dasharray property:

More examples on codepen: https://codepen.io/tag/stroke-dasharray

Embedding SVG in CSS

Sometimes there is a need to embed an SVG image inline as the value of some property in CSS.

For example, icons as background images:

background-image: url('data:image/svg+xml;base64,A1B2...C3=')

Stoyan Stefanov reminds that almost all browsers (except for old ones like IE) need to encode only 3 characters: <, > and #. Therefore, there is no need to do a full base64 encoding — it is not readable, not editable, and bloats the bundle. Let gzip do its job.

Yulia Bukhalova has a ready tool for this:
https://yoksel.github.io/url-encoder/ - converts a larger number of characters but is more reliable.

Read more on the topic: https://www.phpied.com/truth-encoding-svg-data-uris/