SVG-icons - a lot and with style
A little story about how our team decided to organize icons in the upcoming project. A little bit of a historical excursion, glances around (on PNG and vector fonts) and a story about how we all settled down in the end.
We use icons, and actively - a well-chosen icon replaces words and sentences (and a fig-matched icon can be used as a tooltip, but let's not talk about sad things)
In general, there are (and continue to be created) icons. You need to put them on a web page. We must do this so that then the head does not hurt about them for the rest of the project and a couple of years in support. Well, there are additional Wishlist:
- I want a vector. Well, okay, vector is a means, not an end. The goal is not to worry at all about resizing, retina displays, saving images in different formats for different purposes.
- I want to stylize the icons. Because we have at least two sets of themes out of the box (light and dark), or even contrast, for people with substandard vision, or even some orange-colored one will appear closer to the New Year ... In general, the same thing the icon should look slightly different depending on the theme selected on the page.
- I want a dynamic stylization of the icons. Statics are not enough for us. This is enough for screenshots and brochures, but not for live users. And we wanted life! We wanted a hover! We wanted selection !!! And disable, disable all of them! .. Sorry.
- I don’t want JavaScript to participate in this in any form or manifestation. Icons are the look and feel of HTML + CSS. Well, okay, I’m ready to hang the selected class on the elements, but this is the last border ...
There are factors that make the task easier. Icons now (2015, autumn, starting to snow) in fashion are flat, strict. If five years ago the icons were full of colors, now it has gone under the influence of MS, Apple, Design Material ...
tl; dr Attention. The next few sections are the spread of ideas on the tree, and in breadth, an overview of solutions (including unsuccessful ones) and a cat from different angles.
If you want technical details of what came out in the end, please come here .
What classic solutions did not satisfy
- We can make a bunch of png-icons and put them inside the image tags. And replace mouse over on JS events. When I made the site in my third year, this method really worked. It was good, and there was no need to take care of the many connections to the server. Maybe when the circle closes and HTTP 2.0 wins ... in the meantime, it's overkill. Let's go further.
- PNG sprites + CSS / background-image - good, but not enough. Our colleagues from DevExtreme have lived like this for some time ... but they have come up against the need for at least some styling. After all, with the PNG icon the trouble, you can’t even paint it red on the client ! They switched to Font Icons, and we? ..
- Font Icons for writing an application (not a large library, namely an application) turned out to be slightly inconvenient to work with. Changing icons requires some maintenance (collecting icons, saving to a font file, all kinds of hints ...) If the Internet already has all the icons you need as part of Font Awesome, then you shouldn't look for a better option. But if you need your own icons ... we have gone further.
- Unicode characters for icons. He joked, he laughed.Though...although I can not help but note that I love Pts to use them in development, before design and release. Quickly, simply, Ctrl + C, Ctrl + V, font-size, color,: hover, .selected {color:} - and now you have a beautiful icon with hover and selection for free, without SMS ...
- SVG + CSS / background-image - we have normal scaling. We do not have the stylization of the icon itself. No, we can round this up - the hover state is basically made by changing the background color, and the disabled state is made to some extent by changing the opacity. This is a working version, this was our first version uploaded to the repository. But we cannot stylize the drawing itself. Because he is not in the DOMe. And when there is something
missing in the house, it’s a disaster ... For what is not part of the document, you don’t apply CSS styles, you will not tint, you will not change it.
And let's put SVG in the HOUSE?
Of course, we can do this. Copy and paste each icon and paste it wherever you need it into each piece of HTML markup.
Cat Code
And if it changes, then re-paste to all places of use.
Or pretend and write for our project a highly specialized solution, which during assembly, or during deployment, or during execution will understand by magical attributes that there should be an icon, and inject (inject, I don’t know how to translate) the contents of one file inside the contents of another file.
It sounds a lot of fun and very annoying in support.
Unfortunately or fortunately, in DevExpress this way does not fit us by definition. We do not write (almost) final software solutions, we write what other people will use in their decisions.
Imagining the faces of these people whom we would ask to inject our SVGs onto their pages with pens, we abruptly moved on to the next possible solution ...
And if you put it in the DOM, but a little bit, or better, automatically?
Well, that is, to connect some kind of storage to our document, an analog of a sprite with icons, in which all the icons would lie.
And where they are needed, we would say - and give us, dear browser, the kotik icon!
Yes, you can do it, and people do it. We collect all our icons file-by-file and put them all inside one large SVG-sprite, which contains only icon templates. Technically, the symbol element is used for this .
Pro symbol
This element is designed as a template. Very self-sufficient, in terms of capabilities - almost like a small svg-file. Allows you to define your conditional "sizes" - viewBox, to which the coordinates of the elements will be applied. That is, the problem of comparing our sizes with the dimensions of the icon will completely disappear, which is a plus. A little bit of detail . Now supported out of the box with gulp / grunt bulldozers .
Symbolic cat
The result of wrapping a cat in a symbol with the gulp-svgstore plugin . Actually, almost nothing has changed.
This item is not displayed anywhere - by design. It is just a mask for future real icons.
We can take this template and put it on the page, referring to it from the use element .
That's it, cat here.
White-tailed, common.
And we can make it more interesting. Template - he is already at home. I mean in the DOM. And it can already be styled quite like a real one. Using the names of svg-elements (
path
, circle
, rect
etc.), we can apply to them the CSS-rule and modify the attributes (color through fill
and stroke
, thickness and line style).tail { color: orange; }
And now all cats referencing this template will become orange tails. So, our last method has already given us two of the three points of our Wishlist. But when I tried to stabilize one particular icon, I was initially disappointed.
Wonder stories about use, xlink: href and trees together
As soon as we try to customize one taken cat in the forehead, everything stops working.
#barsik .tail {
fill: orangered;
}
Alas, Barsik’s tail does not ginger.
The reason for this is interesting. Barsika is actually not there.
Barsik is in the shade.
HOUSE OF SHADOWS
Shadow DOM - the thing is no longer new. Browser manufacturers began to use it in order to blind input type = datebox, but we did not know about it. At that moment, they were not yet aware that they were using the Shadow DOM, he got the name and form a bit later ...
The use element - in modern terms - uses exactly what the Shadow DOM is.
The elements that we * clone * inside * the root * use - are placed in our DOM ... but not completely.
In particular, CSS rules cannot be applied to them.
But the root of the shadow tree , the element
- it is like on the one hand in our main tree, and on the other - is the ancestor of everything that lies in the tree. From the first side we will apply CSS-style to it.
On the other hand, he will forward the CSS properties given to him to his descendants. If we tell the template to listen to it.
//явно указываем на уровне шаблона, что хвост должен унаследовать цвет заливки от своего предка
.tail {
fill: inherit;
}
//стилизуем предка
#barsik use {
fill: orangered;
}
So Barsik acquires an orange color, and Vaska becomes smoky white. (unless the parts and elements of his feline SVG body are specified otherwise. The priority of the inherited CSS properties is rather low, below the attributes and certainly below the other rules applied to the template - and the template lives completely in the DOM, without any reservations. Details below ) And then we can already use any variations.
.cat-house:hover #barsik use {
fill: red;
}
Thus, we can already customize one color completely freely and in full accordance with the letter CSS. Realizing hover highlighting is easy .
How to apply styles, properties, and attributes
At this moment, from a habit, it begins to become incomprehensible, so I will try to paint again.
For me, this was a little stumbling block.
First approach, no CSS
An SVG element may have an attribute indicating its color. For most shapes (path, circle, ellipsis) this is fill, less commonly used stroke (to indicate the color of the borders of the shape).
If an element does not have this attribute, it tries to get it from its ancestors. It goes up its parents until it finds someone with the specified attribute.
Two circles, fill is not specified, take from the parent. Very successful - the first parent, the group in which they are lying, has a fill. Both circles turn blue.
The second approach. The appearance of styling
As soon as we apply styles, they win. The rule
circle {
fill: orange;
}
Turns both circles orange. It is just stronger ...
The third approach. Stylization kills attributes so that elements use attributes
This code will give us a purple ellipse.
However, adding a CSS rule
ellipse {
fill: inherit;
}
It will make him forget his own color and start taking it from his ancestors.
This is how the whole example looks. Any matches are random. The ellipse will turn orange. In general, most of the examples are based on this trick. There may still be inline styles and! Important, but there everything is already going by analogy Well and a little more magic
Stylization of the second color
Using a hack trick based on the SVG variable currentColor , we can customize two colors already:
.tail {
fill: inherit;
}
.body {
fill: currentColor;
}
svg use {
fill: brown;
color: orange;
}
svg:hover use {
fill: orange;
color: brown;
}
Something like this.
The invisible cat trick
Another minor thing that, in principle, may sometime come in handy is to hide image elements under certain conditions.
Directly, I could not achieve this - the option is
visibility
like that, all or nothing ... But I managed, using the same colors, to paint the element in a transparent color. Very beautiful, the main thing is to choose the right shade.
Technical stuff
SVG sprite must be in the DOMe. Most browsers could show templates from a linked file, but not IE. Therefore, we pump through AJAX and insert it into the HOUSE. There is an article .
Template engines can work weirdly. The xlink: href attribute lives in its namespace (in fact, in the xlink namespace, it says so), and not everyone likes it. For example, Knockout cannot bind it out of the box. There is a workaround . He is working .
I can assume that similar problems may arise in other template engines. I can assume that they can be solved in a similar way.
What happened in the end
- Our icons are stored and lie in separate SVG files, small, favorite in VCS, understandable in diffs and opened in the browser
- Our icons at the time of the build are going inside one big file - icons.svg. What was a file becomes a template.
- This file must be put inside the HTML markup. Hands, build tool or javascript
- Icons can be referenced using this design:
The design is more explicit and more semantically correct than when creating an icon using background-image - The icon template lies inside the DOM and can be modified via CSS
path.tail { fill: darkgrey; }
- A specific icon is made on the basis of the template, it does not fall into the DOM itself, but it falls into the shadow DOM and can be styled thanks to the inheritance of CSS properties from the parent anchor element use.
#dvorovayBreed.selected use { fill: darkgreen; }
- Иконку можно стилизовать как угодно на уровне документа – задавать внутренним элементам SVG классы и красить/модифицировать для всего документа как душе угодно и как CSS позволяет
- Для одной конкретной иконки можно модифицировать два цвета – ровно два. Один – цивилизованно, второй – благодаря магии. Магия очень сильная и работает везде, но магия имеет свою цену – будьте аккуратны в продакшене!
- JavaScript нужен максимум один раз, в процессе жизни страницы больше не используется
The solution turned out not to be tied excessively to the specifics of the bulldozer, well styled.
Works in IE9 +, webkits, Amazon Kindle reader and Samsung TV.
All examples of styling SVG icons are on the github . I gave links to the GitHub Pages of this repository .
I hope someone is interested in this story.
UPD Based on the results of the question, I added another page showing the stylization of 122 real icons , only 500 copies on the page. The
icons for this example are taken on www.flaticon.com
Acknowledgments
When preparing a blog post, not a single animal was injured.
The cat, originally a raster , was translated into SVG terms in an online editor ( source ).
I got the skill of drawing seals by drawing seals for my son, who was extremely pleased with them.
I refuse to accept complaints about the asymmetry of the ears.
List of references
A very, very, very detailed story about the stylization of shadow SVG
About SVG icons in principle , as well as why the symbol is better than a group
The history of the theme icons on the hub - SVG, Iconfonts vs PNG
SVG icons - different approaches , also with cats
How to load the SVG sprite into the DOM
SVG chart drawing library . She has nothing to do with icons, but there are seals too, including my cat (which helped me write articles and served as a model for drawing ).