a customer is swearing and demanding that by 2023 standards I use all icons inside the svg file. And icons both for background images and for normal icons that can be changed.
I am using an svg sprite of the following format:
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol fill="none" viewBox="0 0 24 24" id="arrow-up-and-down" xmlns="http://www.w3.org/2000/svg">
<path d="M10.45 6.72 6.73 3 3.01 6.72M6.73 21V3M13.55 17.281l3.72 3.72 3.72-3.72M17.27 3v18"
stroke="#29354D" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
</symbol>
</svg>
To use in the layout I use the following template:
`<svg class="arrow-link__icon">
<use xlink:href="./src/images/svg/symbol/sprite.svg#arrow-up-and-down" />
</svg>`
Everything inserts perfectly! The file is stored separately, so I get the images easily and simply. But what about the styles? How can I take some similar icon and insert it into the styles?
`
&-item__text {
background: url('../images/svg/symbol/sprite.svg#arrow-up-and-down') top left/cover
no-repeat,
$darkBlue;
height: 100%;
}
`
now I'm prescribing the following, but it's not working! I can't find the right answer on the internet and my boss is getting angrier and angrier. Help!
As commented by Robert Longson: you can't reference a <symbol>
in <img>
sources - same applies to CSS background images.
For images you can use fragment identifiers – this requires to tweak your sprite svg.
Sprites for use with fragment identifiers need rendered elements.
Here is an example of a hybrid sprite svg working both with <use>
and <img>
elements.
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<style>
/**
* show only targeted element
* as definded by fragment identifier
* e.g: sprite.svg#use_up_down
*/
use {
display: none;
}
use:target {
display: block;
}
</style>
<!-- icons for use with <use> references -->
<symbol fill="none" viewBox="0 0 24 24" id="arrow-up-and-down" >
<path d="M10.45 6.72 6.73 3 3.01 6.72M6.73 21V3M13.55 17.281l3.72 3.72 3.72-3.72M17.27 3v18"
stroke="#29354D" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
</symbol>
<symbol fill="none" viewBox="0 0 24 24" id="arrow-up" >
<path d="M10.45 6.72 6.73 3 3.01 6.72M6.73 21V3"
stroke="#29354D" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
</symbol>
<symbol fill="none" viewBox="0 0 24 24" id="arrow-down" >
<path d="M13.55 17.281l3.72 3.72 3.72-3.72M17.27 3v18"
stroke="#29354D" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
</symbol>
<!-- icons for use with images - hidden by default -->
<use id="use_up_down" href="#arrow-up-and-down" />
<use id="use_up" href="#arrow-up" />
<use id="use_down" href="#arrow-down" />
</svg>
Basically you need to add a <use>
instance for each symbol.
Then you add a stylesheet to hide all use elements except the targeted element.
use {
display: none;
}
use:target {
display: block;
}
Now we can use both sprite concepts:
<svg class="arrow-link__icon" viewBox="0 0 24 24">
<use href="sprite.svg#arrow-up-and-down" />
</svg>
<img src="sprite.svg#use_up" />
<img src="sprite.svg#use_down" />
<!-- nothing selected -->
<img src="sprite.svg" />
See also plnkr example.