I wanted to use icons with the ability to change their color and size on the fly with CSS. I decided to go with SVG icons, inspired by the way CSS Tricks uses SVG icons on their site.
Here is how I did it (similar to CSS Tricks):
In my footer template I added something like:
<footer>
<!-- Amazing footer -->
<!-- ... -->
<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0" display="none">
<symbol id="icon-search" viewBox="0 0 470 470">
<title>icon-search</title>
<path d="M447.05,428l-109.6-109.6c29.4-33.8,47.2-77.9,47.2-126.1C384.65,86.2,298.35,0,192.35,0C86.25,0,0.05,86.3,0.05,192.3 s86.3,192.3,192.3,192.3c48.2,0,92.3-17.8,126.1-47.2L428.05,447c2.6,2.6,6.1,4,9.5,4s6.9-1.3,9.5-4 C452.25,441.8,452.25,433.2,447.05,428z M26.95,192.3c0-91.2,74.2-165.3,165.3-165.3c91.2,0,165.3,74.2,165.3,165.3 s-74.1,165.4-165.3,165.4C101.15,357.7,26.95,283.5,26.95,192.3z"></path>
</symbol>
</svg>
</footer>
And now I can use the icons anywhere I want like so:
<form>
<input type="text" name="q" placeholder="Search here...">
<button type="submit">
<svg class="icon-svg icon-search" width="22px" height="22px">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-search"></use>
</svg>
</button>
</form>
And it works... however sometimes on page load some random icons simply won't show. So far this issue is on chrome, doesn't seem to be in firefox for example.
Any idea what could cause that? Is there anything wrong with my implementation?
Thanks.
I've had to debug this before, the missing icons would always load after a reload. It lead me to find that, if the page load stalls a bit and the icons are located near the end of the page, the <use xlink:href="..."> element can't find the symbol it's referencing.
Placing the SVG Icons near the top of the page fixes the issue (before any instance of <use>).
Related
I have a sprite of SVGs and a list of icons/logos in my database.
I loop through all of them and use a templating engine to generate my icons, such as:
<div class="partsvg__container">
<svg class="partsvg__wt-icon partsvg__wt-icon--{{icon}}">
<use xlink:href="svg/icons.svg#wt-icon-{{icon}}"></use>
</svg>
</div>
I might not have a SVG for every item in the database, and in that case the template renders an empty space.
How do I do so that if (for instance) svg/icons.svg#wt-icon-stackoverflow is not present in the spite, to still show a default one (ie: svg/icons.svg#wt-icon-default)?
I found a solution!
You can insert a symbol in your svg for the "not found case". In this way, if the symbol isn't found, a placeholder will be draw in the background.
<div class="partsvg__container">
<svg class="partsvg__wt-icon partsvg__wt-icon--{{icon}}">
<use xlink:href="svg/icons.svg#wt-icon-{{'Placeholder'}}"></use>
<use xlink:href="svg/icons.svg#wt-icon-{{icon}}"></use>
</svg>
</div>
Edit: this questions is irrelevant in case you're using Font Awesome v. >= 5.8.0 because its maintainers (after a long discussion:)), agreed that the "title" should be removed from the svg files and it's done in v. 5.8.0 : https://github.com/FortAwesome/Font-Awesome/issues/14595
Now, back to the original question:
I just tried the Font Awesome (5) in its 'svg sprites' version, following the official, pretty simple tutorial: https://fontawesome.com/how-to-use/on-the-web/advanced/svg-sprites
Everything's working as expected, except I can see a title popping up when I hover on the image (which is bad). I mean the one we see when we have e.g. <div title = "blah"></div>.
So, in compliance with the docs (I guess), I have copied the 'sprites/regular.svg' file to my server and:
<svg class = 'fa-svg-icon' title = 'my failed attempt to overwrite the title'>
<use xlink:href="icons/font-awesome/sprites/solid.svg#user"></use>
</svg>
The '.fa-svg-icon' class, for the sake of completeness:
.fa-svg-icon{
width:1em;
height:1em;
}
What I see, when hoovering the image, is a title "User" showing up. That's is because this is what is declared in the svg file, in "our" fragment:
<symbol id="user" viewBox="0 0 448 512">
<title id="user-title">User</title>
<path d="M224 256c70.7 0 ......"></path>
</symbol>
I tried adding title = 'something' to both the svg element, and the <use> one, but nothing works o.O
This happens on both FX and Chrome.
Edit 1: I made a test page: https://kpion.github.io/stuff/font-awesome-issue/
I'm pretty sure I'm missing something obvious here, because apparently I'm the only one in this world having this problem 😮 Or google is broken. One or the other :)
Edit 2:
To answer a question from comments, here is what my dev tools -> elements in chrome shows (after 'importing' the svg symbol):
<svg class="fa-svg-icon" title="my -not-working-title for user">
<use xlink:href="icons/font-awesome/sprites/solid.svg#user" title="blah - doesn't work either"></use>
#shadow-root (closed)
<svg id="user" viewBox="0 0 448 512" width="100%" height="100%">
<title id="user-title">User</title>
<path d="M224 256c70.7 0 128-57.3 128-..."></path>
</svg>
</svg>
And no, it does not change when hovering, please bear in mind there is no js involved, either mine or from font awesome.
I'm not able to recreate your code environment in a fiddle to try it myself, but you may try the following CSS code, to get the pointer-events only when the icon has a link:
.fa-svg-icon{
pointer-events: none;
}
.fa-svg-icon a {
pointer-events: auto;
}
I'm looking for an advice about work with SVG images, respectively icons.
What I've tried
If I'm using PNG icons, the CSS is like:
elem:after {background: url('icon.png'); ...}
I've tried the same way
elem:after {background: url('icon.svg'); ...}
but it isn't what I'm looking for. This solution lose advantages of SVG icons (they're small and blured, fuzzy).
What I have
I've generated this code online using Icomoon app.
<svg aria-hidden="true" style="position: absolute; width: 0; height: 0; overflow: hidden;" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<symbol id="icon-love" viewBox="0 0 33 32">
<title>love</title>
<path d="M32.916 15.597c0.604-0.66 ..."></path>
</symbol>
<symbol id="icon-shop" viewBox="0 0 34 32">
<title>shop</title>
<path d="M17.148 27.977c-..."></path>
</symbol>
</defs>
</svg>
<svg class="icon icon-shop">
<use xlink:href="#icon-shop"></use>
</svg>
My question
Is it semantically correct to put icons into HTML markup, instead of putting them into CSS?
Across whole website there is about 60 icons, any unique, any are repeated more times. Generated markup above has about 50kB.
Can I put all icons into general layout template and load them all in whole website, or include just icons I use in the page?
Here I've found How to change color of SVG image using CSS (jQuery SVG image replacement)? (3 years ago), but don't know if it's the right way.
How to cache SVG properly? Is it posible when I use it like I'm writing above?
I read many articles, but not definitely sure how to do that best way.
Thanks for advice.
I have a webpage with lots of SVG icons that will be in the HTML. Rather than include them as an IMG tag and possibly slow the page with those HTTP requests, I'm placing the SVG code like this:
<svg xmlns="http://www.w3.org/2000/svg" width="9" height="9" viewBox="0 0 9 9"><path fill="#C5C2BD" fill-rule="nonzero" d="M4.5 3.435L1.286.22A...LOTS OF CODE HERE..."/></svg>
Note: where it says "lots of code here", there is a huge string of numbers/letters that make up the path for this SVG.
The issue this creates is it's very ugly when not easily maintainable in the HTML (to the point where my editor bogs own because these SVG strings are so long).
Is there a cleaner, simpler way to include these SVG icons in my HTML while still eliminating the extra HTTP requests?
Thanks for your time.
The most proven way is to collect all the icons SVG in one file - the sprite SVG
Creating a Sprite and connecting it to HTML
The action plan is as follows:
Creating a Sprite
Connecting it to HTML
Calling SVG images from the sprite
Styling icons
Creating a Sprite
The main task of the sprite is to be a repository for icons that before the call to a specific place HTML pages should be invisible.
To do this,the code for each icon is wrapped with <symbol id =" .. "> ... </ symbol> tags with a unique identifier, which will be followed by the <use>
Template Sprite:
<div id="container">
<svg version="1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 126 126" >
<symbol id="picasa">
<path d="M113.5 57.... 72.8z" />
</symbol>
<symbol id="wordpress" viewBox="0 0 126 126">
<path stroke ="black" d="M113.5 57.7l-8.5-11.4 .. 86.1 62.9z"/>
</symbol>
<symbol id="twitter">
<path d="M113.5 57.6l-8.5-11.4.... 7.4-2.4V85.4z"/>
</symbol>
<symbol id="apple">
<path d="M113.5 57.7l-8.5-11.4... 78.5 78.7 82z"/>
</symbol>
</div>
As you can see, all <path> attributes are removed for later styling of icons from an external CSS file.
Adding a sprite file to HTML
There are several ways to add SVG files to HTML, but the most reliable way is to add it using the <object>
<object type="image/svg+xml" data="Sprite.svg" width="200" height="200">
Your browser does not support SVG
</object>
Adding icons from the sprite
<div id="container">
<svg viewBox="0 0 126 126" >
<use xlink:href="#apple"></use>
</svg>
</div>
The viewBox attributes should be like thesvg icon or change the scaling inside HTML if necessary.
Icons as links
For this, in SVG, unlike HTML, its own form of record
<svg viewBox="0 0 126 126" >
<a xlink:href="https://www.apple.com/ru/"><use xlink:href="#apple"></use></a>
</svg>
Styling icons
When using the <use> command, the icon falls into the shadow DOM and its attributes behave strangely, - there is an icon of the icon, but it can not be controlled from the outside.
In addition, the icon attributes for example: style = "fill: gray; stroke: crimson;" have the highest priority. Therefore, we deleted these attributes. see the example of the sprite above.
To solve the problem of inheritance of parental properties by objects in shadow DOM, you must use forced inheritance
svg path{
fill:inherit;
stroke:inherit;
}
and then to the icons you can already apply CSS rules from the external table
svg path:hover{fill:yellow;}
#picasa{fill:black;}
#apple{fill:purple;}
#twitter{fill:black;}
#wordpress{fill:blue;}
If you go for the first time along this path, then inevitably there will be many questions.
Ask, do not be shy.
All sooner or later it turned out to be done and customized sprite.
The main recommendation is to do everything yourself manually for the first time, to understand how it is arranged, and then you can already openly use special utilities to automatically create sprites.
You should convert all your .svg files to one font file, here is how:
How to convert .svg files to a font?
I'm keen to figure out a good system for organising SVG's. This seems really good, basically all my SVGs are in a file call SVGs.svg, which is included with PHP at the top of every page, then I use 'use' to display whichever one I want on the page.
SVGs.svg file:
<svg>
<defs>
<g id="MOlogo">
...
</g>
<g id="icon">
...
</g>
</defs>
HTML to use an SVG:
<svg viewBox="0 0 100 100">
<use xlink:href="#MOlogo"></use>
</svg>
The trouble is, when I include the SVGs.svg file in my page I get a massive gap before the content of my page. Anyone know what might be causing that?
Cheers