Shadow root closed svg как исправить

I am not creating Shadow dom explicitly any where in code. But in Edge I see #shadow-root (Closed)==$0 . Due to this svg graphic feature is not working .But in IE it working   IE HTML   <g xmlns="http://www.w3.org/2000/svg" class="taskpanel" id="General_RecordApplicationInfoSubFlowchart_2_0" data-bi...

I am not creating Shadow dom explicitly any where in code. But in Edge I see #shadow-root (Closed)==$0 .
Due to this svg graphic feature is not working .But in IE it working

IE HTML

<g xmlns=»http://www.w3.org/2000/svg» class=»taskpanel» id=»General_RecordApplicationInfoSubFlowchart_2_0″ data-bind=»event: { click: toggleTaskPanel, mouseover: mouseOver, mouseout: mouseOut }»>
<desc>Record Application Information</desc>

<g opacity=»1″ data-bind=»attr: { opacity: opacity }»>
<rect class=»taskcard» style=»cursor: pointer;» fill=»#ecebeb» stroke=»#61605d» x=»0″ y=»0″ width=»300″ height=»106″ rx=»10″ data-bind=»attr: { fill: fill, stroke: stroke }» data-originalwidth=»300″ data-originalheight=»106″ />
<line class=»taskcard» stroke=»#61605d» x1=»15″ y1=»0″ x2=»15″ y2=»106″ data-bind=»attr: { stroke: stroke }» />
<line class=»taskcard» stroke=»#61605d» x1=»285″ y1=»0″ x2=»285″ y2=»106″ data-bind=»attr: { stroke: stroke }» />
<text font-weight=»bold» style=»cursor: pointer;» text-anchor=»middle» x=»150″ y=»57″ data-originaly=»57″>Record Application Information</text>
<text class=»annotation» style=»cursor: pointer;» text-anchor=»start» x=»22″ y=»102″>Risk.Admin</text>
<image style=»» x=»267″ y=»2″ width=»16px» height=»16px» xmlns:xlink=»http://www.w3.org/1999/xlink» xlink:href=»/UI/ODI.Risk.UI/images/active.gif» data-bind=»visible: markComplete» />
</g>

<use class=»content» style=»display: none;» x=»40″ y=»50″ xmlns:xlink=»http://www.w3.org/1999/xlink» xlink:href=»#recordApplicationInformationWorkflow» />
</g>

Edge HTML

<use xlink:href=»#General_ProcessApplicationSubFlowchart_2_0″ x=»339″ y=»266″>
#shadow-root (Closed)==$0
<g id=»General_RecordApplicationInfoSubFlowchart_2_0″ class=»taskpanel» data-bind=»event: { click: toggleTaskPanel, mouseover: mouseOver, mouseout: mouseOut }»>
<desc>Record Application Information</desc>

<g opacity=»1″ data-bind=»attr: { opacity: opacity }»>
<rect class=»taskcard» x=»0″ y=»0″ rx=»10″ width=»300″ height=»106″ data-bind=»attr: { fill: fill, stroke: stroke }» fill=»#e5e5e5″ stroke=»#61605d»></rect>
<line class=»taskcard» x1=»15″ y1=»0″ x2=»15″ y2=»106″ data-bind=»attr: { stroke: stroke }» stroke=»#61605d»></line>
<line class=»taskcard» x1=»285″ y1=»0″ x2=»285″ y2=»106″ data-bind=»attr: { stroke: stroke }» stroke=»#61605d»></line>
<text x=»150″ y=»57″ text-anchor=»middle» font-weight=»bold»>Record Application Information</text>
<text class=»annotation» x=»22″ y=»102″ text-anchor=»start»>Risk.Admin</text>
<image x=»267″ y=»2″ width=»16px» height=»16px» xlink:href=»/UI/ODI.Risk.UI/images/active.gif» style=»» data-bind=»visible: markComplete»></image>
</g>

<use xlink:href=»#recordApplicationInformationWorkflow» class=»content» x=»40″ y=»50″ style=»display: none»></use>
</g>
</use>

One of the most common use cases for SVG graphics is icon systems, and one of the most commonly-used SVG spriting techniques is one that uses the SVG <use> element to “instantiate” the icons anywhere they are needed in a document.

Instantiating icons or any other SVG element or image using the <use> element introduces some challenges when it comes to styling the instance of that element. The aim of this article is to give you an overview of some of the possible ways to work around the styling limitations introduced by <use>.

But before we get started, let’s take a quick look into SVG’s main structuring and grouping elements that will gradually take us into the world of use, the shadow of its DOM, and then bring us back into the light with CSS. We’ll go over why styling <use> content can be challenging and ways to work around that.

Quick Overview of SVG Structuring, Grouping and Referencing (Re-using) Elements in SVG

There are four main elements in SVG that are used to define, structure and reference SVG code within the document. These elements make reusing elements easy, while maintaining clean and readable code. Because of the nature of SVG, some of these elements have the same functionality as certain commands in graphics editors.

The four main SVG grouping and referencing elements are: <g>, <defs>, <use> and <symbol>.

The <g> element (short for “group”) is used for logically grouping together sets of related graphical elements. In terms of graphics editors, such as Adobe Illustrator, the <g> element serves a similar functionality as the Group Objects function. You can also think of a group as being similar to the concept of a layer in a graphics editor, since a layer is also a grouping of elements.

Grouping elements together is useful for when you want to apply a style and have that style be inherited by all the elements in the group, and is particularly useful for when you want to animate a group of elements while maintaining their spatial relationships with each other.

The <defs> element is used to define elements that you want to reuse later. Defining elements with <defs> is useful for when you want to create sort of a “template” that you want to use multiple times throughout the document. Elements defined inside a <defs> element are not rendered on the canvas except if you “call” them somewhere in the document.

<defs> is useful for defining many things, but one of the main use cases is defining patterns like gradients, for example, and then using those gradients as stroke fills on other SVG elements. It can be used to define any elements that you want to render anywhere on the canvas by reference.

The <symbol> element combines the benefits of both the <defs> and the <g> elements in that it is used to group together elements that define a template that is going to be referenced elsewhere in the document. Unlike <defs>, <symbol> is not usually used to define patterns, but is mostly used to define symbols such as icons, for example, that are referenced throughout the document.

The <symbol> element has an important advantage over the other two elements: it accepts a viewBox attribute which allows it to scale-to-fit inside any viewport it is rendered in.

The <use> element is the element you use to reference any element defined elsewhere in the document. It lets you reuse existing elements, giving you a similar functionality to the copy-paste functionality in a graphics editor. It can be used to reuse a single element, or a group of elements defined with the <g> element, the <defs> element, or a <symbol>.

To use an element you pass a reference to that element—an ID—inside the use‘s xlink:href attribute, and you position that element using x and y attributes. You can apply styles to the use element and those styles will cascade into the contents of the use element.

But what is the content of <use>? Where is it cloned? And how does the CSS cascade work with that content?

Before we answer these questions, and since we only covered a quick overview of SVG’s structuring and grouping elements, it’s worth mentioning a couple of articles to learn more about these elements and about the viewBox attribute used with <symbol>:

  • Structuring, Grouping, and Referencing in SVG — The <g>, <use>, <defs> and <symbol> Elements
  • Understanding SVG Coordinate Systems (Part 1): The Viewport, viewBox and PreserveAspectRatio

SVG <use> and The Shadow DOM

When you reference an element with <use>, the code might look something like this:

<symbol id="my-icon" viewBox="0 0 30 30">
	<!-- icon content / shapes here -->
</symbol>

<use xlink:href="#my-icon" x="100" y="300" />

What is rendered on the screen is the icon whose content is defined inside <symbol>, but it’s not that content that got rendered, but rather the content of the <use>, which is a duplicate—or clone—of the <symbol>’s content.

But the <use> element is only one element and it is self-closing—there is no content somewhere between an opening and closing use tag, so where has the <symbol> content been cloned?

The answer to that is: the Shadow DOM. (Somehow the Shadow DOM always reminds me of the Batman. I don’t know why.)

What is the Shadow DOM?

The Shadow DOM is similar to the normal DOM except that, instead of being part of the main document subtree, nodes in the Shadow DOM belong to a document fragment which is basically just another subtree of nodes which are not as vulnerable to scripts and styles as normal DOM nodes are. This gives authors a way to encapsulate and scope styles and scripts when creating modular components. If you’ve ever used the HTML5 video element or the range input type and wondered where the video controls or range slider components came from, then you’ve already come across the Shadow DOM before.

In the case of the SVG <use> element, the contents of the referenced element are cloned into a document fragment that is “hosted” by <use>. <use>, in this case, is called a Shadow Host.

So, the contents of <use> (the clone or copy of whatever element it is referencing) are present inside a shadow document fragment.

In other words, they are there, but they are not visible. They are just like normal DOM content, but instead of being available in the “high-level” DOM which is accessible by CSS selectors and JavaScript in the main document, they are copied into a document fragment that is hosted by <use>.

Now, if you’re a designer, you might be thinking: “OK, I get it but is there a way to inspect that sub-document to actually see into its contents?” The answer is: Yes! You can preview the contents of the shadow DOM using Chrome’s developer tools. (Inspecting the contents of a shadow DOM is currently not possible in Firefox.) But in order to do that, you need to first enable shadow DOM inspection in the “General” tab inside the Settings panel that can be opened by clicking on the Cog icon. You can learn more about how to do that here.

Once you’ve enable shadow DOM inspection in the dev tools, you can see the cloned elements in the Elements panel, just like you would with normal DOM elements. The following image shows an example of a <use> element referencing the contents of a <symbol>. Notice the “#shadow-root” and the contents of that fragment when expanded—they are a copy of the contents of the <symbol>.

Using Chrome's developer tools, you can inspect the contents of the <use> element inside the shadow DOM (see the "#shadow-root"  in grey). This screenshot inspects the Codrops logo from an example we will go over in the next section.

Using Chrome’s developer tools, you can inspect the contents of the <use> element inside the shadow DOM (see the “#shadow-root” in grey). This screenshot inspects the Codrops logo from an example we will go over in the next section.

Looking at the inspected code, you can see that the shadow DOM is pretty much the same as the normal DOM, except that is has different characteristics when it comes to handling with CSS and JavaScript from the main document. There are also other differences between them, but the shadow DOM cannot possibly be covered in this section because it is too big of a concept, so if you want to read and learn more about it, I recommend the following articles:

  • Intro to Shadow DOM
  • What the Heck is Shadow DOM?
  • Shadow DOM 101
  • Introduction to Shadow DOM (Video)

For me, and considering how limited my interaction with the shadow DOM is, I think of it as being just like the normal DOM, except that it needs to be handled differently when it comes to accessing its elements for styling with CSS (and JavaScript). This is what matters to us as SVG developers: how the existence of the contents of <use> inside a shadow DOM affects that content when it comes to applying or changing styles, because we want to be able to style them. The whole point of using <use> is being able to create different “copies” of an element, and in a lot of cases, what we want is to be able to style each copy differently. For example, think about a logo with two styles (inverted color themes) or multi-coloured icons of which each has its own theme. So, it would only make sense for us to expect to be able to do that using CSS.

That being said, we mentioned earlier that the contents of the shadow DOM are not vulnerable to CSS like the normal DOM is. So how do we style its content? We cannot target a path descendant of <use> like this:

use path#line {
    stroke: #009966;
}

because we cannot access the shadow DOM using regular CSS selectors.

There are a couple of special selectors that allow you to penetrate the shadow DOM boundaries to apply styles to nodes inside of it, but those selectors are not only not well supported, but they are limited compared to the long list of selectors provided in CSS for selecting and styling regular DOM elements.

Moreover, we want a simpler way to style the contents of an SVG <use> without having to get our hands dirty with shadow DOM specifics—using simple CSS and SVG only.

In order to achieve that and get a little more control over styling the contents of <use>, we need to think from a different angle, and start by leveraging the CSS cascade and taking advantage of its inheritance capabilities.

The Style Cascade

Since SVG elements can be styled using CSS using one of three different ways: external CSS styles (in an external style sheet), internal style blocks (<style> elements) and inline styles (in a style attribute), it only makes sense that the cascade governs how these styles are applied to these elements.

In addition to CSS properties, SVG elements can also be styled using presentation attributes. Presentation attributes are a shorthand for setting a CSS property on an element. Think of them as special style properties. Their nature is what makes them contribute to the style cascade, but maybe in a less expected way.

In the following code snippet which simply displays a pink circle with a yellow stroke, stroke, stroke-width, and fill are all presentation attributes.

<svg viewBox="0 0 100 100">
    <circle fill="deepPink" stroke="yellow" stroke-width="5" cx="50" cy="50" r="10"></circle>
</svg>

In SVG, a subset of all CSS properties may be set by SVG attributes, and vice versa. This means that not all CSS properties can be specified on an SVG element as presentation attributes, and not all presentation attributes available in SVG (there are a lot of them!) can be specified in CSS.

The SVG specification lists the SVG attributes that may be set as CSS properties. Some of these attributes are shared with CSS (already available as CSS properties), such as opacity and transform, among others, while some are not, such as fill, stroke and stroke-width, among others.

In SVG 2, this list will include x, y, width, height, cx, cy and a few other presentation attributes that were not possible to set via CSS in SVG 1.1. The new list of attributes can be found in the SVG 2 specification.

If you’re like me, then you would expect presentation attributes to have a higher specificity than all other style declarations. I mean, after all, external styles are overridden by internal styles in style blocks, and style block declarations are overridden by inline styles in a style attribute.. so it seems as though the more “internal” the styles get, the more specificity they have, and so when a property gets its own attribute, it makes it more powerful and thus it would override all other style declarations. Although that still makes sense to me, this is not how it really works.

As a matter of fact, presentation attributes count as low-level “author style sheets” and are overridden by any other style definitions: external style sheets, document style sheets and inline styles. The only power presentation attributes have in the style cascade is over inherited styles. That is, presentation attributes can only override inherited styles on an element, and are overridden by any other style declaration.

Great, now that that’s been cleared up, let’s get back to the <use> element and its content.

We now know that we cannot set styles on the elements inside <use> using CSS selectors.

We also know that, just like with the <g> element, styles you apply to <use> will be inherited by all its descendants (those in the shadow DOM).

So a first attempt to change the fill color of an element inside <use> would be to apply that fill color to the <use> element itself and let inheritance and the cascade do its thing.

However, that brings up two issues:

  1. The fill color will be inherited by all the descendants of <use>, even those you may not want to style. (If you have only one element inside <use>, then this won’t be an issue.)
  2. If you’ve exported an SVG from a graphics editor and/or got an SVG from a designer who did that and for any reason you can’t touch the SVG code, then you’re likely to end up with SVG elements with presentation attributes applied (unless you explicitly specified that you don’t want this to happen upon exporting the SVG, but that’s another topic), and the values of these attributes are going to override any styles you apply on <use>. Now, I’m assuming that if you are specifying styles on <use> then you want those styles to be inherited by its descendants, so presentation attributes would be causing an inconvenience in this case.

And even if you do have access to the SVG code and you can get rid of the presentation attributes, I highly recommend against that because:

  1. Removing the attributes used to set certain properties will reset those properties to their initial browser-default values—which, in most cases, is all black fills and strokes (if we’re talking about colors, for example).
  2. By resetting all values you force yourself into specifying styles for all the properties set, so unless you want to do just that, then you don’t want to get rid of those presentation attributes.
  3. The presentation attributes that are initially available are a great fallback mechanism for when the external styles you set are not applied for any reason. If the CSS fails to load because something was messed up, your icon will at least have some default nice styles to fall back to. I highly recommend keeping them.

OK so now we have those attributes but we also want to style different instances of our, say, icon, differently.

The way to do that is to make sure we force the presentation attributes into inheriting the styles set on <use> or find a way to work around them overriding those values. And in order to do that, we need to take advantage of the CSS cascade.

Let’s start with the simplest of examples and gradually move on to more complex scenarios.

Overriding Presentation Attribute Values From CSS

Presentation attributes are overridden by any other style declaration. We can take advantage of this and have an external style declaration force the presentation attribute into overriding its value with the inherited value from use.

By using the CSS inherit keyword, this becomes quite simple. Take a look at the following example where we have an ice cream icon made up of just one path whose fill color we want to change for different instances. The icon is Created by Erin Agnoli from the Noun Project.

<svg>
  <symbol id="ic">
    <path fill="#000" d="M81,40.933c0-4.25-3-7.811-6.996-8.673c-0.922-5.312-3.588-10.178-7.623-13.844  c-2.459-2.239-5.326-3.913-8.408-4.981c-0.797-3.676-4.066-6.437-7.979-6.437c-3.908,0-7.184,2.764-7.979,6.442  c-3.078,1.065-5.939,2.741-8.396,4.977c-4.035,3.666-6.701,8.531-7.623,13.844C22.002,33.123,19,36.682,19,40.933  c0,2.617,1.145,4.965,2.957,6.589c0.047,0.195,0.119,0.389,0.225,0.568l26.004,43.873c0.383,0.646,1.072,1.04,1.824,1.04  c0.748,0,1.439-0.395,1.824-1.04L77.82,48.089c0.105-0.179,0.178-0.373,0.225-0.568C79.855,45.897,81,43.549,81,40.933z   M49.994,11.235c2.164,0,3.928,1.762,3.928,3.93c0,2.165-1.764,3.929-3.928,3.929s-3.928-1.764-3.928-3.929  C46.066,12.997,47.83,11.235,49.994,11.235z M27.842,36.301c0.014,0,0.027,0,0.031,0c1.086,0,1.998-0.817,2.115-1.907  c0.762-7.592,5.641-13.791,12.303-16.535c1.119,3.184,4.146,5.475,7.703,5.475c3.561,0,6.588-2.293,7.707-5.48  c6.664,2.742,11.547,8.944,12.312,16.54c0.115,1.092,1.037,1.929,2.143,1.907c2.541,0.013,4.604,2.087,4.604,4.631  c0,1.684-0.914,3.148-2.266,3.958H25.508c-1.354-0.809-2.268-2.273-2.268-3.958C23.24,38.389,25.303,36.316,27.842,36.301z   M50.01,86.723L27.73,49.13h44.541L50.01,86.723z"/>
  </symbol>
</svg>

The ice cream icon’s contents (the path) are defined in a <symbol> element, which means that they won’t be directly rendered on the SVG canvas.

Then, we render multiple instances of the icon using <use>.

<svg class="icon" viewBox="0 0 100 125"> 
    <use class="ic-1" xlink:href="#ic" x="0" y="0" />
</svg>
<svg class="icon" viewBox="0 0 100 125"> 
    <use class="ic-2" xlink:href="#ic" x="0" y="0" />
</svg>

And we set the width and height of the icons from CSS. I am using the same dimensions as the viewBox dimensions but they don’t have to be identical. However, to avoid getting any excess white space inside the SVG, make sure you maintain the same aspect ratio between them.

.icon {
    width: 100px;
    height: 125px;
}

Using the above code, you get the following result:

Screen Shot 2015-07-15 at 13.21.02

Note that I have added a black border to the SVGs so you can see the boundaries of each one and to show you that the contents of the first SVG where we defined the icon contents are not rendered. This is to make a point here: the SVG document where you define your symbols will still be rendered on the page, even if it contains no rendered shapes. In order to avoid that, make sure you set display: none on the first SVG. If you don’t hide the SVG containing the icon definitions, it will be rendered even if you don’t explicitly set any dimensions for it—the browser will default to 300 pixels by 150 pixels, which is the default size for non-replaced elements in CSS, so you will end up with a white area on the page that you do not want.

Now let’s try to change the fill color for each icon instance:

use.ic-1 {
    fill: skyblue;
}
use.ic-2 {
    fill: #FDC646;
}

The fill color of the icons still does not change because the inherited color values are being overridden by the fill="#000" on the path element. To prevent that from happening, let’s force the path into inheriting the color value:

svg path {
    fill: inherit;
}

And voila!—the colors we set on the <use> elements are now applied to the path in each one. Check the live demo out and play with the values creating more instances and changing their colors as you go:

See the Pen f15cec4a61e753259bd768de2e20500b by Sara Soueidan (@SaraSoueidan) on CodePen.

Now this technique is useful when you want to force the contents of <use> to inherit the styles you set on it. But in most cases, this may not be exactly what you want. There are other styling scenarios, so we’ll go over some of them next.

Styling <use> Content with the CSS all Property

A while back I was working on an icon referenced with use and I wanted one of the elements inside of it to inherit all the styles I set on <use> like fill, stroke, stroke-width, opacity and even transform. Basically, I wanted to be able to control all of those attributes from CSS while also keeping the presentation attributes in the markup as fallback.

If you find yourself in such a scenario as well, you will probably find it time-consuming to have to do this in the CSS:

path#myPath {
    fill: inherit;
    stroke: inherit;
    stroke-width: inherit;
    transform: inherit;
    /* ... */
}

Looking at the above snippet, you can see a pattern and it would only make sense for us to be able to combine all of those properties into one property and set that property’s value to inherit.

Fortunately, this is where the CSS all property helps. I have written about using the all property to style SVG <use> content in property’s CSS Reference entry, but it is worth a second look here since we’re in the right context.

Using the all property, we can do this:

path#myPath {
    all: inherit;
}

This works great in all browsers that support the all property (see property’s entry for details), however there is something important to keep in mind: this declaration will set literally all of the properties on the element to inherit their values from their ancestor, even those you might not have wanted to target. So unless you want to style all the properties of your element from your CSS, then you do not want to use this—it is an extreme measure and is particularly useful for when you want to “bare-bone” your element and have complete control over its styling properties in CSS, which may not be too often. If you use this declaration and don’t specify values for all of the properties in your CSS, they will go up and cascade until they find a value to inherit, which in most cases will be the default browser styles from the default user agent style sheet.

Note that this will only affect the attributes that can be set in CSS, not the SVG-only attributes. So if an attribute can be set as a CSS property, it will be set to inherit, otherwise it won’t.


Being able to force the presentation attributes to inherit from <use> styles is powerful, but what if you have an icon with multiple elements and you don’t want all of those elements to inherit the same fill color from use? What if you want to apply multiple different fill colors to different use descendants? Setting one style on use no longer suffices. We need something else to help us cascade the right colors to the right elements..

Using the CSS currentColor Variable For Styling <use> Content

Using the CSS currentColor variable in conjunction with the above technique, we can specify two different colors on an element, instead of just one. Fabrice Weinberg wrote about this technique on his Codepen blog a little less than a year ago.

The idea behind this technique is to use both the fill and the color properties on <use>, and then have these colors cascade into the contents of <use> by taking advantage of the variable nature of currentColor. Let’s jump right into a code example to see how this works.

Suppose we want to style this minimal Codrops logo using two colors—one for the front drop and one for the back drop—for every instance of that logo.

StylingSVGuse_codropsdrops

First, let’s start with the code for the above screenshot: we have the symbol containing our icon definition and then three <use> instances creating the three logo instances.

<svg style="display: none;">
<symbol id="codrops" viewBox="0 0 23 30">
    <path class="back" fill="#aaa" d="M22.63,18.261c-0.398-3.044-2.608-6.61-4.072-9.359c-1.74-3.271-3.492-5.994-5.089-8.62l0,0   c-1.599,2.623-3.75,6.117-5.487,9.385c0.391,0.718,0.495,1.011,0.889,1.816c0.143,0.294,0.535,1.111,0.696,1.43   c0.062-0.114,0.582-1.052,0.643-1.162c0.278-0.506,0.54-0.981,0.791-1.451c0.823-1.547,1.649-2.971,2.469-4.33   c0.817,1.359,1.646,2.783,2.468,4.33c0.249,0.47,0.513,0.946,0.791,1.453c1.203,2.187,2.698,4.906,2.96,6.895   c0.292,2.237-0.259,4.312-1.556,5.839c-1.171,1.376-2.824,2.179-4.663,2.263c-1.841-0.084-3.493-0.887-4.665-2.263   c-0.16-0.192-0.311-0.391-0.448-0.599c-0.543,0.221-1.127,0.346-1.735,0.365c-0.56-0.019-1.095-0.127-1.599-0.313   c1.448,3.406,4.667,5.66,8.447,5.78C19.086,29.537,23.469,24.645,22.63,18.261z"/>
    <path class="front" fill="#ddd" d="M6.177,11.659c0.212,0.367,0.424,0.747,0.635,1.136c0.164,0.303,0.333,0.606,0.512,0.927   c0.683,1.225,1.618,2.898,1.755,3.937c0.144,1.073-0.111,2.056-0.716,2.769c-0.543,0.641-1.315,1.014-2.186,1.067   c-0.87-0.054-1.643-0.43-2.186-1.067c-0.604-0.713-0.858-1.695-0.715-2.771c0.137-1.036,1.072-2.712,1.755-3.936   c0.18-0.32,0.349-0.623,0.513-0.927C5.752,12.404,5.964,12.026,6.177,11.659 M6.177,5.966L6.177,5.966   c-1.02,1.649-2.138,3.363-3.247,5.419c-0.932,1.728-2.344,3.967-2.598,5.88c-0.535,4.014,2.261,7.09,5.846,7.203   c3.583-0.113,6.379-3.189,5.845-7.203c-0.255-1.912-1.666-4.152-2.598-5.88C8.314,9.329,7.196,7.617,6.177,5.966L6.177,5.966z"/>
</symbol>
</svg>
<svg height="90px" width="69px">
  <use xlink:href="#codrops" class="codrops-1"/>
</svg>
<svg height="90px" width="69px">
  <use xlink:href="#codrops" class="codrops-2"/>
</svg>
<svg height="90px" width="69px">
  <use xlink:href="#codrops" class="codrops-3"/>
</svg>

If we were to set the fill color on the <use> element for each instance, that color would be inherited by both paths (drops) and they would both end up having the same color—which is not what we want.

So instead of specifying only the fill color and having it cascade the default way, we are going to use the currentColor variable to make sure the small drop in the front gets a different color value: the value specified using the color property.

First, we need to insert the currentColor where we want that color value to be applied; it goes into the markup where the icon contents are defined, inside the <symbol>. So the code looks like this:

<svg style="display: none;">
	<symbol id="codrops" viewBox="0 0 23 30">
		<path class="back" fill="#aaa" d="..."/>
		<path class="front" fill="currentColor" d="..."/>
	</symbol>
</svg>

Next we need to remove the fill presentation attribute from the other drop, and let it inherit the fill color from use without using the inherit technique.

If we were to use the inherit keyword to force the presentation attributes into inheriting their values from use, both paths will inherit the same value and the currentColor will no longer have an effect. So, in this technique, we do need to remove the attribute we want to set in CSS, and only keep the one whose value we want to set using currentColor.

<svg style="display: none;">
	<symbol id="codrops" viewBox="0 0 23 30">
		<path class="back" d="..."/>
		<path class="front" fill="currentColor" d="..."/>
	</symbol>
</svg>

Now, using fill and color properties on <use>, we style the drops:

.codrops-1 {
  fill: #4BC0A5;
  color: #A4DFD1;
}
.codrops-2 {
  fill: #0099CC;
  color: #7FCBE5;
}
.codrops-3 {
  fill: #5F5EC0;
  color: #AEAFDD;
}

Each <use> element gets its own fill and color values. For each one, the fill color cascades and is inherited by the first path which does not have a fill attribute, and the value of the color property is used as a value for the fill attribute on the second path.

So what happened here is that the current color value was leaked into the innards of the <use> element, using the currentColor variable. Pretty neat, right?

Here is the live demo for the above code:

See the Pen 9cb698c206c6b572264f9b0509b0156f by Sara Soueidan (@SaraSoueidan) on CodePen.

This two-color variation technique is quite useful for simple bicoloured logos. In Fabrice’s article, he created three different variations of the Sass logo by changing the color of the text versus that of the background.

The currentColor keyword is the only available CSS variable in CSS today. However, if we had more variables, wouldn’t it make it possible for us to distribute and leak even more values into the <use> content? Yes, it would. Amelia Bellamy-Royds introduced this very concept in a Codepen blog post a little less than a year ago as well. Let’s take a look at how that works.

The Future: Styling <use> Content with CSS Custom Properties a.k.a CSS Variables

Using CSS Custom Properties (a.k.a CSS Variables), you can style the contents of <use> without having to force the browser into overriding any presentation attribute values.

As defined on MDN, CSS Variables are entities defined by authors, or users, of Web pages to contain specific values throughout a document. They are set using custom properties and are accessed using a specific functional notation var(). They are very similar to CSS preprocessor (like Sass) variables, but are more flexible and can do things preprocessor variables can’t. (An entry on CSS Variables will soon be added to the Codrops CSS Reference, so stay tuned.)

Variables, be it CSS variables or preprocessor variables, can have many usage examples, but theming (colors) is one of the most common use cases. And in this section we’ll go over how that can be done when styling SVGs.

We’ll start with one image defined in a symbol and instantiated with use and apply this technique to one image only; the concepts applied to style the contents of <use> in this example can be applied to as many <use> elements as you want.

So, suppose we have the following cute hipster robot illustration designed by Freepik.

Screen Shot 2015-07-15 at 22.32.43

The code for the robot contains the colors that make it up.

<svg style="display: none">
    <symbol id="robot" viewBox="0 0 340 536">
        <path d="..." fill="#fff" />
        <path d="..." fill="#D1312C" />
        <path d="..." fill="#1E8F90" />
        <path d="..." fill="#1E8F90" />
        <path d="..." fill="#fff" />
        <path d="..." fill="#6A4933" />
        <path d="..." fill="#1E8F90"  />
        <path d="..." fill="#6A4933" />
        <path d="..." fill="#fff" />
        <path d="..." fill="#6A4933" />
        <path d="..." fill="#F2B42B" />
        <path d="..." fill="#fff" />
     
       <!-- rest of the shapes -->
    </symbol>
</svg>

Now, we are not going to use the CSS Variables as values for the fill attribute of each path; instead, we’re going to use them as fill color values using the CSS fill property, and we’re going to keep the fill attributes in place. The attributes will be used as a fallback for browsers that don’t support CSS Variables, so the image will still look as it initially did if the variables fail to work in those browsers.

With the variables added, the above code will look like so:

<svg style="display: none">
    <symbol id="robot" viewBox="0 0 340 536">
        <path d="..." fill="#fff" />
        <path d="..." fill="#D1312C" />
        <path d="..." fill="#1E8F90" style="fill: var(--primary-color)" />
        <path d="..." fill="#1E8F90" style="fill: var(--primary-color)" />
        <path d="..." fill="#fff" />
        <path d="..." fill="#6A4933" style="fill: var(--tertiary-color)" />
        <path d="..." fill="#1E8F90" style="fill: var(--primary-color)" />
        <path d="..." fill="#6A4933" style="fill: var(--tertiary-color)" />
        <path d="..." fill="#fff" />
        <path d="..." fill="#6A4933" style="fill: var(--tertiary-color)" />
        <path d="..." fill="#F2B42B" style="fill: var(--secondary-color)" />
        <path d="..." fill="#fff" />
       
        <!-- rest of the shapes -->
    </symbol>
</svg>

Since inline style tags override presentation attributes, browsers that support CSS Variables will use those variables as fill colors for the shapes. Browsers that do not support CSS variables will use the fill attribute values instead.

Next, we need to define the values for the variables in CSS. First, the illustration will be instantiated using use:

<svg width="340" height="536">
    <use xlink:href="#robot" id="robot-1" />
</svg>

Then, the variables will be defined on use so that they cascade into its contents. The colors you choose for the variables will make up the color scheme of the contents of your illustration. So, for the above robot, there were three main colors making up the graphic, so I named them primary, secondary and tertiary.

#robot-1 {
  --primary-color: #0099CC;
  --secondary-color: #FFDF34;
  --tertiary-color: #333;
}

You can still use the fill and color properties alongside these variables, but you may not need to or simply not want to. So, given the above colors defined for the variables, the robot now looks like this:

Screen Shot 2015-07-15 at 22.54.53

You can have as many copies of the image as you want, and for each use define a set of different colors to be used, and end up with different themes. This is particularly useful for when you want to style a logo in different ways depending on the context, or for any other similar use cases.

Now, we mentioned that browsers that don’t support CSS Variables are going to fall back to the initial styles defined in the presentation attributes, and browsers that do support the variables will use the variables in the fill properties to override the attributes. Great. But what happens if the browser does support CSS Variables but the author fails to provide them with a value for a specific variable or if the value they provided is invalid?

For our hipster robot here, we defined three variables, and only a few elements inside of the image did not get any variables because the colors used were complimentary and would go with pretty much any color theme used. So, if you display the above code in a browser that supports CSS variables (currently only Firefox) and remove the variable declarations from the CSS, you will end up with this:

Screen Shot 2015-07-15 at 22.59.37

If the values provided for the variables are either not set or invalid, the browser will default to its own colors, which is usually black for fill and stroke colors in SVG.

A way to avoid that is to provide another fallback color for supporting browsers. Indeed, the CSS variables syntax comes with a way to do just that: instead of providing only the variable name inside the var() function as an argument, you provide two comma-separated arguments: the variable name and a fallback color value—which in this case is the value we have in the presentation attributes.

So, going over the above code for the robot, it will look like this:

<svg style="display: none">
    <symbol id="robot" viewBox="0 0 340 536">
        <path d="..." fill="#fff" />
        <path d="..." fill="#D1312C" />
        <path d="..." fill="#1E8F90" style="fill: var(--primary-color, #1E8F90)" />
        <path d="..." fill="#1E8F90" style="fill: var(--primary-color, #1E8F90)" />
        <path d="..." fill="#fff" />
        <path d="..." fill="#6A4933" style="fill: var(--tertiary-color, #6A4933)" />
        <path d="..." fill="#1E8F90" style="fill: var(--primary-color, #1E8F90)" />
        <path d="..." fill="#6A4933" style="fill: var(--tertiary-color, #6A4933)" />
        <path d="..." fill="#fff" />
        <path d="..." fill="#6A4933" style="fill: var(--tertiary-color, #6A4933)" />
        <path d="..." fill="#F2B42B" style="fill: var(--secondary-color, #F2B42B)" />
        <path d="..." fill="#fff" />

         <!-- rest of the shapes -->
    </symbol>
</svg>

And that’s it. For any variable that fails to load its defined value or that does not have one, the browser will fall back to the initial color defined in the markup. Wonderful.

Using this technique, you can now reference the robot anywhere you want on the page with <use>, and for every new instance define a set of variable values in the CSS, and you’ll have a different color theme per instance.

You can play with the above demo, create as many copies of the robot as you want and assign different variable values to them in this live demo, just make sure you use Firefox at this time because it’s the only browser supporting CSS Variables at the time of writing of this article:

See the Pen c30e270090b2460ba6e6833c611e5a76 by Sara Soueidan (@SaraSoueidan) on CodePen.

If you view the demo in Firefox, you will see the blue + yellow version of the robot that we defined with CSS variables. Make sure you check the demo in Chrome to see how it falls back to the initial colors (green version), and try removing the variable declarations from the CSS in Firefox to also see how the fallback works.

Summing Up

Phew. That was a lot.

By taking advantage of the CSS cascade, styling the contents of <use>—though in a shadow DOM—can become less complicated. And with CSS variables (be it currentColor alone or the custom properties) we can penetrate the lines of the shadow DOM and customize our graphics to our liking while also providing very good fallback for when anything goes wrong.

Personally, I am incredibly excited about the CSS Variables + SVG combination. I love how powerful they are together, especially given the great fallback mechanism we have with it. They are currently only supported in Firefox, as we mentioned, but if you want to see them get wider support you can start by voting for them in other browsers such as on the MS Edge User Voice forums.

We may even get other ways to style use content in the future as well since there are already discussions going on about using CSS Variables as SVG parameters; so this article, though long, might have not covered everything there is to know about this topic. If you have any other ideas, please feel free to share them in the comments below.

Dealing with the contents of reused SVG elements has been one of those SVG topics that many people seem to find some hardship with, because of the nature of how the cloned code behaves and where it is cloned to. There are a lot more topics to cover that are related to that, but those are topics for other articles.

I hope you enjoyed this article and found it useful. Thank you for reading.

Я пробовал анимировать svg-спрайт с помощью CSS. Я создал спрайт и ввел его из глотка:

gulp.task('svgstore', function () {
var svgs = gulp
    .src('app/svg/*.svg')
    .pipe(svgmin(function (file) {
        return {
            plugins: [{
                cleanupIDs: {
                    minify: true
                }
            }]
        }
    }))        
    .pipe(svgstore({ inlineSvg: true }));

function fileContents (filePath, file) {
    return file.contents.toString();
}   

return gulp
    .src('app/*.html')
    .pipe(inject(svgs, { transform: fileContents }))
    .pipe(gulp.dest('app/'))
});

… И вставил изображения из спрайта в HTML:

<svg class="icon-ufo" >
    <use xlink:href="img/sprite.svg#ufo" aria-hidden="true"></use>
</svg>

И это работает хорошо, но на следующем изображении показано, что теневой DOM закрыт.

svg shadow dom

Как я могу анимировать некоторые стили этого SVG без JavaScript? Но если JavaScript — единственный способ, как это сделать лучше?

2 ответа

Лучший ответ

DOM ссылочного элемента не является частью DOM ссылающейся HTML-страницы. Он имеет изолированные таблицы стилей.

Но теневой элемент наследует стили от ссылающегося элемента <use>. Это означает, что до тех пор, пока указанный элемент не устанавливает стили в спрайте или в таблице стилей, связанной со спрайтом, вы можете изменить (и анимировать) каждое наследуемое свойство стиля значка, задав стиль <use> элемент.


14

ccprog
10 Дек 2017 в 22:49

Вы можете использовать свойство currentColor в атрибуте fill для стилизации: icon.svg

И стили для класса «icon-ufo» будут похожи на

.icon-ufo {
    color: green;
}

.icon-ufo:hover {
   color: red;
}


4

Evgeniy Boytsov
31 Май 2019 в 13:07

Если вы из тех разработчиков, кто только задумывается о внедрении в свой проект svg-спрайтов или из тех, кто давно хотел, но не знает с чего начать, эта статья определенно будет вам полезна. Об удобстве и пользе спрайтов вообще и SVG-спрайтов в частности немало информации как на родном, так и на иностранном языке. Поэтому, в этой статье, мы не будем останавливаться на вопросах целесообразности их использования, а перейдем непосредственно к сути.

SVG-спрайты бывают разные. Самый простой вариант – это склеивание всех иконок в один файл и последующее использование его в виде фоновой картинки со смещением background-position для каждой иконки. Все, кто работал ранее с растровыми спрайтами, знакомы с такой технологией и найдут ее для себя простой и понятной. К сожалению, в таком варианте спрайта масштабирование и управление цветом будет недоступно, также, как и возможность использовать спрайт в теге img.

Другие виды svg-спрайтов выглядят интереснее. Об их разновидностях, преимуществах и недостатках хорошо изложено в этой статье на Хабре. Там же рассказывается о библиотеке svg-sprite, к которой мы позднее вернемся.

Сегодня, мы рассмотрим генерацию и использование спрайтов, на примере символьного SVG-спрайта. Выбор в его пользу был сделан не случайно, это именно тот вариант спрайта, который имеет на сегодняшний день наилучшую поддержку браузерами, а также позволяет свободно управлять размером и цветом иконки.

Устройство спрайта

Символьный svg-спрайт, представляет собой один корневой элемент svg, внутри которого создаются области symbol, внутри которых содержится код svg-иконки. Каждому элементу symbol назначается уникальный id, по которому к нему в дальнейшем можно будет обратиться в документе.

Symbol создает шаблон из любых svg-объектов, который в дальнейшем можно многократно использовать с помощью тэга use. Контент, расположенный внутри symbol, не отображается на странице.
Предположим, у нас имеются две разные svg-иконки:

 
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 64 64">
<path id="Cloud" fill="#42adf4" d="M48.147892,18.941c-1.2983971,0-2.5535965,0.1753006-3.7612991,0.4729996
	C40.9443932,15.4881001,35.9338951,13,30.3371944,13c-8.1797009,0-15.119194,5.2947998-17.6996002,12.6723003
	c-0.0374994-0.0002995-0.0735941-0.0056-0.1110992-0.0056C5.608295,25.6667004,0,31.3377991,0,38.3334007
	C0,45.3288994,5.608295,51,12.526495,51c3.0087996,0,32.4916,0,35.6213989,0C56.9027939,51,64,43.8232994,64,34.9705009
	C64,26.1175995,56.9027939,18.941,48.147892,18.941z M48.147892,48.9006004H12.526495
	c-5.749495,0-10.4271002-4.7404022-10.4271002-10.5671997c0-5.8087006,4.6484995-10.5377998,10.3733997-10.5672016
	c0.0489006,0.0031013,0.0979004,0.0051003,0.1476002,0.0055008l1.5026999,0.0123005l0.4962006-1.4185009
	c2.3568993-6.7385998,8.673399-11.2660999,15.7178993-11.2660999c4.7499981,0,9.2954998,2.0771008,12.4708042,5.6987
	l0.8415947,0.9598999l1.2396011-0.3055992c1.1086998-0.2733994,2.205101-0.4120007,3.2586975-0.4120007
	c7.5833015,0,13.7527008,6.2490005,13.7527008,13.9301014S55.7311935,48.9006004,48.147892,48.9006004z"/>
</svg>

<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 64 64">
<g id="Refresh_1_">
	<path fill="#42adf4" d="M48.7919998,22.6142502c-0.4766006,0-0.9570999,0.0224991-1.4336014,0.0664005
		c-2.7841988-7.0195007-9.6025848-11.6797009-17.2167988-11.6797009c-9.6581993,0-17.5868988,7.3096008-18.4403992,16.8076
		C5.1699009,28.2822495,0.0010008,33.7431488,0.0010008,40.3867493c0,6.9550018,5.6629996,12.6123009,12.6240005,12.6123009
		h36.1669998c8.3857002,0,15.2070007-6.8154984,15.2070007-15.1924019
		C63.9990005,29.4296494,57.1777,22.6142502,48.7919998,22.6142502z M48.7919998,51.0009499H12.625001
		c-5.8594003,0-10.6260004-4.7616997-10.6260004-10.6142006c0-5.8516006,4.7665997-10.6132984,10.6406002-10.6132984
		c0.5362139,0,0.9765997-0.4229012,0.9990997-0.9580002c0.3603001-8.8691998,7.6093006-15.8164005,16.5028992-15.8164005
		c7.0342159,0,13.3076,4.4589996,15.6093998,11.0946999c0.1581993,0.4550991,0.6268997,0.7313995,1.089817,0.6620998
		c0.6444817-0.0946999,1.3007812-0.1434994,1.9511833-0.1434994c7.2831993,0,13.2089996,5.9188995,13.2089996,13.1942978
		S56.0751991,51.0009499,48.7919998,51.0009499z"/>
	<path fill="#42adf4" d="M32.4968147,25.40415l0.7804871-0.6707001c0.4189987-0.3603992,0.4667969-0.9913006,0.1075134-1.4102001
		c-0.3604164-0.419899-0.9922142-0.4657993-1.4102154-0.107399l-2.8262005,2.4277
		c-0.4188995,0.3603992-0.4667988,0.9911995-0.107399,1.4101982l2.4277,2.8271008
		c0.1982994,0.2304993,0.4776001,0.3486004,0.7588005,0.3486004c0.2314987,0,0.4628983-0.0790997,0.6513977-0.2411995
		c0.4189148-0.3603001,0.4668007-0.9912014,0.1074028-1.4101009l-1.0659008-1.2411003
		c3.7255001,0.3786011,6.6420994,3.5335007,6.6420994,7.3573017c0,4.0780983-3.3174019,7.3964996-7.3955002,7.3964996
		s-7.3955002-3.3184013-7.3955002-7.3964996c0-0.5527-0.4473-1-1-1c-0.5527992,0-1,0.4473-1,1
		c0,5.1815987,4.2147999,9.3964996,9.3955002,9.3964996c5.1805992,0,9.3955002-4.214901,9.3955002-9.3964996
		C40.5625,29.9661503,37.0483017,26.0535507,32.4968147,25.40415z"/>
		</g>
</svg>

Для того, чтобы объединить их в спрайт, достаточно код каждой из них обернуть в элемент symbol, к нему добавить атрибут viewbox и указать уникальный id. Вот так выглядит самый простой символьный svg-спрайт.

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <symbol id="cloud" viewBox="0 0 64 64">
        <path id="cloud" fill="#42adf4"  d="M48.147892,18.941c-1.2983971,0-2.5535965,0.1753006-3.7612991,0.4729996
        	C40.9443932,15.4881001,35.9338951,13,30.3371944,13c-8.1797009,0-15.119194,5.2947998-17.6996002,12.6723003
        	c-0.0374994-0.0002995-0.0735941-0.0056-0.1110992-0.0056C5.608295,25.6667004,0,31.3377991,0,38.3334007
        	C0,45.3288994,5.608295,51,12.526495,51c3.0087996,0,32.4916,0,35.6213989,0C56.9027939,51,64,43.8232994,64,34.9705009
        	C64,26.1175995,56.9027939,18.941,48.147892,18.941z M48.147892,48.9006004H12.526495
        	c-5.749495,0-10.4271002-4.7404022-10.4271002-10.5671997c0-5.8087006,4.6484995-10.5377998,10.3733997-10.5672016
        	c0.0489006,0.0031013,0.0979004,0.0051003,0.1476002,0.0055008l1.5026999,0.0123005l0.4962006-1.4185009
        	c2.3568993-6.7385998,8.673399-11.2660999,15.7178993-11.2660999c4.7499981,0,9.2954998,2.0771008,12.4708042,5.6987
        	l0.8415947,0.9598999l1.2396011-0.3055992c1.1086998-0.2733994,2.205101-0.4120007,3.2586975-0.4120007
        	c7.5833015,0,13.7527008,6.2490005,13.7527008,13.9301014S55.7311935,48.9006004,48.147892,48.9006004z"/>
    </symbol>

    <symbol id="cloud-computing" viewBox="0 0 64 64">
        <g id="Refresh_1_">
            <path fill="#42adf4" d="M48.7919998,22.6142502c-0.4766006,0-0.9570999,0.0224991-1.4336014,0.0664005
        		c-2.7841988-7.0195007-9.6025848-11.6797009-17.2167988-11.6797009c-9.6581993,0-17.5868988,7.3096008-18.4403992,16.8076
        		C5.1699009,28.2822495,0.0010008,33.7431488,0.0010008,40.3867493c0,6.9550018,5.6629996,12.6123009,12.6240005,12.6123009
        		h36.1669998c8.3857002,0,15.2070007-6.8154984,15.2070007-15.1924019
        		C63.9990005,29.4296494,57.1777,22.6142502,48.7919998,22.6142502z M48.7919998,51.0009499H12.625001
        		c-5.8594003,0-10.6260004-4.7616997-10.6260004-10.6142006c0-5.8516006,4.7665997-10.6132984,10.6406002-10.6132984
        		c0.5362139,0,0.9765997-0.4229012,0.9990997-0.9580002c0.3603001-8.8691998,7.6093006-15.8164005,16.5028992-15.8164005
        		c7.0342159,0,13.3076,4.4589996,15.6093998,11.0946999c0.1581993,0.4550991,0.6268997,0.7313995,1.089817,0.6620998
        		c0.6444817-0.0946999,1.3007812-0.1434994,1.9511833-0.1434994c7.2831993,0,13.2089996,5.9188995,13.2089996,13.1942978
        		S56.0751991,51.0009499,48.7919998,51.0009499z"/>
            <path fill="#42adf4" d="M32.4968147,25.40415l0.7804871-0.6707001c0.4189987-0.3603992,0.4667969-0.9913006,0.1075134-1.4102001
        		c-0.3604164-0.419899-0.9922142-0.4657993-1.4102154-0.107399l-2.8262005,2.4277
        		c-0.4188995,0.3603992-0.4667988,0.9911995-0.107399,1.4101982l2.4277,2.8271008
        		c0.1982994,0.2304993,0.4776001,0.3486004,0.7588005,0.3486004c0.2314987,0,0.4628983-0.0790997,0.6513977-0.2411995
        		c0.4189148-0.3603001,0.4668007-0.9912014,0.1074028-1.4101009l-1.0659008-1.2411003
        		c3.7255001,0.3786011,6.6420994,3.5335007,6.6420994,7.3573017c0,4.0780983-3.3174019,7.3964996-7.3955002,7.3964996
        		s-7.3955002-3.3184013-7.3955002-7.3964996c0-0.5527-0.4473-1-1-1c-0.5527992,0-1,0.4473-1,1
        		c0,5.1815987,4.2147999,9.3964996,9.3955002,9.3964996c5.1805992,0,9.3955002-4.214901,9.3955002-9.3964996
        		C40.5625,29.9661503,37.0483017,26.0535507,32.4968147,25.40415z"/>
        </g>
    </symbol>
</svg>

Использование на странице

Чтобы иметь возможность использовать иконки из символьного svg-спрайта, в первую очередь, нужно добавить этот спрайт на страницу. Берем спрайт, полученный нами в предыдущем разделе, и вставляем на страницу.

После того, как спрайт находится на странице, вывести нужную иконку можно с помощью тэга use:

<svg class="inline-svg-icon">
  <use xlink:href="#cloud"></use>
</svg>

<svg class="inline-svg-icon">
  <use xlink:href="#cloud-computing"></use>
</svg>

See the Pen Symbol SVG Sprite detail guide — simple SVG sprite example by dreamhelg (@dreamhelg) on CodePen.dark

Управление с помощью CSS

Перед тем, как переходить к стилизации иконок средствами CSS, нужно удалить из спрайта атрибуты fill, stroke, style. Эти атрибуты в svg имеют больший приоритет и переписать их средствами CSS не получится. В нашем примере это атрибут fill. После его удаления, иконки станут черными:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <symbol id="cloud" viewBox="0 0 64 64">
        <path id="cloud" d="M48.147892,18.941c-1.2983971,0-2.5535965,0.1753006-3.7612991,0.4729996
        	C40.9443932,15.4881001,35.9338951,13,30.3371944,13c-8.1797009,0-15.119194,5.2947998-17.6996002,12.6723003
        	c-0.0374994-0.0002995-0.0735941-0.0056-0.1110992-0.0056C5.608295,25.6667004,0,31.3377991,0,38.3334007
        	C0,45.3288994,5.608295,51,12.526495,51c3.0087996,0,32.4916,0,35.6213989,0C56.9027939,51,64,43.8232994,64,34.9705009
        	C64,26.1175995,56.9027939,18.941,48.147892,18.941z M48.147892,48.9006004H12.526495
        	c-5.749495,0-10.4271002-4.7404022-10.4271002-10.5671997c0-5.8087006,4.6484995-10.5377998,10.3733997-10.5672016
        	c0.0489006,0.0031013,0.0979004,0.0051003,0.1476002,0.0055008l1.5026999,0.0123005l0.4962006-1.4185009
        	c2.3568993-6.7385998,8.673399-11.2660999,15.7178993-11.2660999c4.7499981,0,9.2954998,2.0771008,12.4708042,5.6987
        	l0.8415947,0.9598999l1.2396011-0.3055992c1.1086998-0.2733994,2.205101-0.4120007,3.2586975-0.4120007
        	c7.5833015,0,13.7527008,6.2490005,13.7527008,13.9301014S55.7311935,48.9006004,48.147892,48.9006004z"/>
    </symbol>

    <symbol id="cloud-computing" viewBox="0 0 64 64">
        <g id="Refresh_1_">
            <path d="M48.7919998,22.6142502c-0.4766006,0-0.9570999,0.0224991-1.4336014,0.0664005
        		c-2.7841988-7.0195007-9.6025848-11.6797009-17.2167988-11.6797009c-9.6581993,0-17.5868988,7.3096008-18.4403992,16.8076
        		C5.1699009,28.2822495,0.0010008,33.7431488,0.0010008,40.3867493c0,6.9550018,5.6629996,12.6123009,12.6240005,12.6123009
        		h36.1669998c8.3857002,0,15.2070007-6.8154984,15.2070007-15.1924019
        		C63.9990005,29.4296494,57.1777,22.6142502,48.7919998,22.6142502z M48.7919998,51.0009499H12.625001
        		c-5.8594003,0-10.6260004-4.7616997-10.6260004-10.6142006c0-5.8516006,4.7665997-10.6132984,10.6406002-10.6132984
        		c0.5362139,0,0.9765997-0.4229012,0.9990997-0.9580002c0.3603001-8.8691998,7.6093006-15.8164005,16.5028992-15.8164005
        		c7.0342159,0,13.3076,4.4589996,15.6093998,11.0946999c0.1581993,0.4550991,0.6268997,0.7313995,1.089817,0.6620998
        		c0.6444817-0.0946999,1.3007812-0.1434994,1.9511833-0.1434994c7.2831993,0,13.2089996,5.9188995,13.2089996,13.1942978
        		S56.0751991,51.0009499,48.7919998,51.0009499z"/>
            <path d="M32.4968147,25.40415l0.7804871-0.6707001c0.4189987-0.3603992,0.4667969-0.9913006,0.1075134-1.4102001
        		c-0.3604164-0.419899-0.9922142-0.4657993-1.4102154-0.107399l-2.8262005,2.4277
        		c-0.4188995,0.3603992-0.4667988,0.9911995-0.107399,1.4101982l2.4277,2.8271008
        		c0.1982994,0.2304993,0.4776001,0.3486004,0.7588005,0.3486004c0.2314987,0,0.4628983-0.0790997,0.6513977-0.2411995
        		c0.4189148-0.3603001,0.4668007-0.9912014,0.1074028-1.4101009l-1.0659008-1.2411003
        		c3.7255001,0.3786011,6.6420994,3.5335007,6.6420994,7.3573017c0,4.0780983-3.3174019,7.3964996-7.3955002,7.3964996
        		s-7.3955002-3.3184013-7.3955002-7.3964996c0-0.5527-0.4473-1-1-1c-0.5527992,0-1,0.4473-1,1
        		c0,5.1815987,4.2147999,9.3964996,9.3955002,9.3964996c5.1805992,0,9.3955002-4.214901,9.3955002-9.3964996
        		C40.5625,29.9661503,37.0483017,26.0535507,32.4968147,25.40415z"/>
        </g>
    </symbol>
</svg>

Если вы не хотите, чтобы иконки по умолчанию были черными, можно сделать отдельный файл стилей, содержащий дефолтные настройки для каждой иконки. Это хороший способ сэкономить немного времени и стилизовать только отдельные иконки по мере необходимости.

  .inline-svg-icon{
       display: inline-block;
       width: 150px;
       height: 150px;
       fill: #7db958;
       margin-right: 30px;
   }

Обращаясь к классу элемента svg, с помощью CSS можно указать нужный размер, изменить цвет, назначить эффект наведения, добавить анимацию, применить svg-фильтры.

See the Pen Symbol SVG Sprite detail guide — SVG sprite with CSS styling by dreamhelg (@dreamhelg) on CodePen.dark

Список свойств, доступных для изменения через CSS, есть на сайте W3C

Стилизация отдельных частей иконки

При непосредственном встраивании svg-картинки на страницу, мы можем управлять различными частями изображения, обращаясь к назначенных им классам. Возникает резонный вопрос, можно ли такой же фокус провернуть с svg-спрайтом? Ответ — нет.

Все дело в теге use, с помощью которого мы встраиваем иконку на страницу. Фактически, use вставляет на страницу не саму иконку, а копию именованной области на которую мы ссылаемся в атрибуте xlink:href. Где бы эта область не находилась (на этой же странице или во внешнем файле), тег use найдет ее и скопирует. При этом код иконки не станет частью документа, а будет помещен в теневой DOM. Поэтому, можно сколько угодно назначать классы отдельным частям иконки — результат останется прежним. Ограничения теневого DOM не дадут стилизовать внутренние части изображения.

Но кое-что сделать все же можно.

Есть два способа, которыми можно добиться желаемого. И один из них даже имеет неплохую поддержку современными браузерами.

Предположим, что вам не требуется глубокая стилизация частей изображения, и вы вполне можете ограничиться двумя цветами. В этом случае, вполне можно обойтись использованием currentColor. Как говорится в спецификации о currentColor:

Это ключевое слово, содержащее значение свойства color. currentColor можно использовать в любых свойствах, принимающих значение color

То есть, если у нас есть элемент, в котором один и тот же цвет используется сразу в нескольких свойствах, достаточно указать его только один раз, а дальнейшее упоминание доверить ключевому слову currentColor:

h1{
       color: aquamarine;
       box-shadow: 3px 2px 1px 20px currentColor;
       text-shadow: 3px 2px 1px currentColor;
       border-bottom: solid 2px currentColor;
}

Этот же прием, можно использовать в svg-спрайте. Предположим, нам необходимо раскрасить две части иконки в разные цвета. Удаляем атрибуты fillу тех элементов, что красятся в основной цвет средствами CSS. А в той части, которая планируется быть раскрашенной другим цветом – наоборот добавим атрибут fill, со значением currentColor. После этого, достаточно в CSS указать два значения: fill для цвета основной иконки и color для цвета ее второй части.

<symbol id="cloud-computing" viewBox="0 0 64 64">
        <g id="Refresh_1_">
            <path d="M48.7919998,22.6142502c-0.4766006,0-0.9570999,0.0224991-1.4336014,0.0664005
        		c-2.7841988-7.0195007-9.6025848-11.6797009-17.2167988-11.6797009c-9.6581993,0-17.5868988,7.3096008-18.4403992,16.8076
        		C5.1699009,28.2822495,0.0010008,33.7431488,0.0010008,40.3867493c0,6.9550018,5.6629996,12.6123009,12.6240005,12.6123009
        		h36.1669998c8.3857002,0,15.2070007-6.8154984,15.2070007-15.1924019
        		C63.9990005,29.4296494,57.1777,22.6142502,48.7919998,22.6142502z M48.7919998,51.0009499H12.625001
        		c-5.8594003,0-10.6260004-4.7616997-10.6260004-10.6142006c0-5.8516006,4.7665997-10.6132984,10.6406002-10.6132984
        		c0.5362139,0,0.9765997-0.4229012,0.9990997-0.9580002c0.3603001-8.8691998,7.6093006-15.8164005,16.5028992-15.8164005
        		c7.0342159,0,13.3076,4.4589996,15.6093998,11.0946999c0.1581993,0.4550991,0.6268997,0.7313995,1.089817,0.6620998
        		c0.6444817-0.0946999,1.3007812-0.1434994,1.9511833-0.1434994c7.2831993,0,13.2089996,5.9188995,13.2089996,13.1942978
        		S56.0751991,51.0009499,48.7919998,51.0009499z"/>
            <path fill="currentColor" d="M32.4968147,25.40415l0.7804871-0.6707001c0.4189987-0.3603992,0.4667969-0.9913006,0.1075134-1.4102001
        		c-0.3604164-0.419899-0.9922142-0.4657993-1.4102154-0.107399l-2.8262005,2.4277
        		c-0.4188995,0.3603992-0.4667988,0.9911995-0.107399,1.4101982l2.4277,2.8271008
        		c0.1982994,0.2304993,0.4776001,0.3486004,0.7588005,0.3486004c0.2314987,0,0.4628983-0.0790997,0.6513977-0.2411995
        		c0.4189148-0.3603001,0.4668007-0.9912014,0.1074028-1.4101009l-1.0659008-1.2411003
        		c3.7255001,0.3786011,6.6420994,3.5335007,6.6420994,7.3573017c0,4.0780983-3.3174019,7.3964996-7.3955002,7.3964996
        		s-7.3955002-3.3184013-7.3955002-7.3964996c0-0.5527-0.4473-1-1-1c-0.5527992,0-1,0.4473-1,1
        		c0,5.1815987,4.2147999,9.3964996,9.3955002,9.3964996c5.1805992,0,9.3955002-4.214901,9.3955002-9.3964996
        		C40.5625,29.9661503,37.0483017,26.0535507,32.4968147,25.40415z"/>
        </g>
    </symbol>
.cloud-computing{
   fill: #103f6f;
   color: #6fb1f5;
}

See the Pen Symbol SVG Sprite detail guide — SVG sprite coloring in two colors with CSS by dreamhelg (@dreamhelg) on CodePen.dark

Как я уже упоминала выше, currentColor, на сегодняшний день, имеет неплохую поддержку всеми современными браузерами и IE11+. Если вам не требуется работа в старых версиях браузеров, смело можно брать этот прием на вооружение.

Есть и второй способ, гораздо более гибкий. В дело вступают CSS-переменные и здесь уже нет ограничений по количеству стилизуемых элементов. А принцип остается тот же: ко всем элементам, которые вы планируете изменять средствами CSS, добавляем нужные вам атрибуты.

<symbol id="browser" viewBox="0 0 64 64">
        <g>
            <path fill="var(--star-fill)" d="M25.0956993,39.8096008L24.2402,46.8065987c-0.0429993,0.3487015,0.1074009,0.6944008,0.392601,0.9014015
		c0.1679993,0.1221008,0.3680992,0.1846008,0.5692997,0.1846008c0.1386986,0,0.2793121-0.0293007,0.4091988-0.089901L32,44.8261986
		L38.3895988,47.8027c0.3194008,0.1474991,0.6944008,0.1114006,0.9785004-0.0946999
		c0.285202-0.2070007,0.4356003-0.5527,0.392601-0.9023018l-0.8563995-6.9960976l4.8046989-5.157299
		c0.1669006-0.1787033,0.2597008-0.4150009,0.2597008-0.6601028c0-0.7987976,0-0.7987976-4.4648018-1.6689987L36.2666016,31.6924
		l-3.4190025-6.1620998C32.6767006,25.2217007,32.3525009,25.0312004,32,25.0312004
		c-0.3525887,0-0.6767998,0.1905003-0.8477001,0.4990997L27.7334118,31.6924l-6.9190006,1.3486004
		c-0.3457108,0.0673981-0.6269112,0.3163986-0.736311,0.6514015c-0.1084003,0.3348999-0.0272999,0.7030983,0.2129002,0.9598999
		L25.0956993,39.8096008z M28.5468006,33.5088005c0.2803001-0.0546989,0.5234985-0.2304993,0.662199-0.4814987L32,27.9971008
		l2.7900009,5.030201c0.1386986,0.2509995,0.3817978,0.4267998,0.6620979,0.4814987c0,0,3.4756012,0.6767006,5.6485023,1.1006012
		l-3.9219017,4.2098999c-0.1952858,0.2089996-0.2881012,0.4941978-0.2528992,0.7783966L37.625,45.3075981l-5.2158012-2.4296989
		C32.2793007,42.8184013,32.1395988,42.7881012,32,42.7881012c-0.1396999,0-0.2793007,0.0303001-0.4092007,0.089798
		l-5.2148991,2.4296989l0.6982994-5.7108994c0.0351009-0.2831993-0.0576-0.5683975-0.2528992-0.7773972l-3.9218884-4.2098999
		L28.5468006,33.5088005z"/>
            <path d="M60,5h-56C1.7908008,5,0.0000008,6.7908001,0.0000008,9v5v2v39c0,2.2090988,1.7908,4,3.9999998,4h56
		c2.2090988,0,4-1.7909012,4-4V16v-2V9C64,6.7908001,62.2090988,5,60,5z M62,55c0,1.1027985-0.8972015,2-2,2h-56
		c-1.1027997,0-1.9999998-0.8972015-1.9999998-2V16h60V55z M62,14h-60V9c0-1.1027999,0.8972001-2,1.9999998-2h56
		c1.1027985,0,2,0.8972001,2,2V14z"/>
            <path fill="var(--dot-left)" d="M6.0000005,9c-0.9649997,0-1.75,0.7849998-1.75,1.75c0,0.9649,0.7850003,1.75,1.75,1.75c0.9649,0,1.75-0.7851,1.75-1.75
		C7.7500005,9.7849998,6.9649005,9,6.0000005,9z M6.0000005,11.5c-0.4141998,0-0.75-0.3358002-0.75-0.75s0.3358002-0.75,0.75-0.75
		c0.4142003,0,0.75,0.3358002,0.75,0.75S6.4142008,11.5,6.0000005,11.5z"/>
            <path fill="var(--dot-right)" d="M16,9c-0.9649992,0-1.75,0.7849998-1.75,1.75c0,0.9649,0.7850008,1.75,1.75,1.75c0.964901,0,1.75-0.7851,1.75-1.75
		C17.75,9.7849998,16.964901,9,16,9z M16,11.5c-0.4141998,0-0.75-0.3358002-0.75-0.75S15.5858002,10,16,10s0.75,0.3358002,0.75,0.75
		S16.4141998,11.5,16,11.5z"/>
            <path fill="var(--dot-center)" d="M11.000001,9c-0.9650002,0-1.75,0.7849998-1.75,1.75c0,0.9649,0.7849998,1.75,1.75,1.75c0.9649,0,1.75-0.7851,1.75-1.75
		C12.750001,9.7849998,11.964901,9,11.000001,9z M11.000001,11.5c-0.4142008,0-0.75-0.3358002-0.75-0.75s0.3357992-0.75,0.75-0.75
		c0.4141998,0,0.75,0.3358002,0.75,0.75S11.4142008,11.5,11.000001,11.5z"/>
        </g>
    </symbol>

В качестве значений указываем CSS-переменные, через которые и проводим стилизацию в CSS:

.browser{
   width: 250px;
   height: 250px;
   fill: #89edcd;
    
  //CSS-переменные, в коде SVG-иконки
   --star-fill: #f3eb04;
   --dot-left: #f6214e;
   --dot-center: #2153f6;
   --dot-right: #53f621;
}

See the Pen Symbol SVG Sprite detail guide — SVG sprite coloring in many colors with CSS Variables by dreamhelg (@dreamhelg) on CodePen.dark

Конечно, настолько подробную стилизацию вряд ли удобно производить подобным способом. В таких случаях, думаю удобнее обходиться без спрайта вообще, но всегда полезно иметь представление о доступных возможностях.

С поддержкой CSS-переменных дела обстоят немного хуже, в случае некоторых версий IE, Opera Mini и Android Browser, она отсутствует вовсе.

Вообще о стилизации svg элементов через use есть замечательная статья на английском, в которой очень подробно и с примерами изложена эта тема.

Использование внешней ссылки на спрайт

Давайте представим, что вы дошли до текущего раздела и все у вас прекрасно работает. Не радует только необходимость держать спрайт в теле страницы. На самом деле, ничего плохого в этом нет.
Если вас все устраивает, можно продолжать в том же духе.

При таком способе подключения есть только один существенный недостаток – отсутствие кэширования спрайта. К счастью, эта проблема легко решаема. Внутри атрибута xlink:href достаточно прибавить к идентификатору путь, по которому расположен ваш спрайт:

<svg class="inline-svg-icon browser">
  <use xlink:href="sprite-manual.svg#browser"></use>
</svg>

Как уже упоминалось выше, элементу use совершенно все равно где находится нужный фрагмент, в теле документа или во внешнем файле. И все бы хорошо, если бы не всеми любимый браузер. IE, вплоть до одиннадцатой версии, не поддерживает использование внешней ссылки на спрайт в теге use. Но и это не проблема, так как есть замечательный скрипт под названием SVG for Everybody. Использовать его очень легко. Подключаем скрипт и делаем вызов, готово:

<script src="/path/to/svg4everybody.js"></script>
<script>svg4everybody();</script>

Этот скрипт добавляет поддержку ссылок на внешние svg-файлы не только в IE, но и в любых других браузерах, не поддерживающих подобный функционал.

Однако, несмотря на такую радужную картинку с подключением внешнего svg-спрайта, не спешите убирать его со страницы. Сейчас узнаете почему.

«Я все сделал как в статье, а у меня не работает»

Очень распространенная ситуация, когда все вроде бы правильно, но не работает. Причин может быть множество и не всегда можно сразу увидеть, что не так. Начать нужно с проверки примеров, приведенных выше. Вставляете себе на страницу спрайт и выводите точно, как в примере, любую иконку. Если с этим проблем не возникло, следовательно что-то не так с вашим спрайтом.

Что же может не работать? Давайте рассмотрим несколько примеров.

Иконка не отображается совсем или отображается частично

Вставляем тэг use на страницу, а ничего не происходит. Если используете ссылку на внешний svg-файл – отключите и вставьте спрайт на страницу. Внимательно сверьте id символа иконки и атрибута xlink:href.

Попробуйте добавить в ваш спрайт одну из иконок, приведенных в примерах выше. Если она выводится без проблем, скорее всего проблема в ваших иконках. В этом случае, первое, что нужно сделать – это взять отдельную иконку и проверить в браузере. Если с отображением вне спрайта проблем нет, значит следует получше к ней присмотреться.

Внимательный осмотр может показать, что возможно часть элементов иконки или вся она использует в качестве фона градиент. И это тот самый момент, когда можно подкатывать глаза и начинать страдать.

Практически во всех статьях про SVG вообще и спрайты в частности (эта не исключение), в качестве примеров используются простые и красивые иконки с хорошо читаемой разметкой. В жизни же все далеко не так прекрасно и в качестве исходного материала для спрайта, вы вполне можете встретить, например, такое:

<?xml version="1.0" encoding="UTF-8"?>
<svg width="83px" height="70px" viewBox="0 0 83 70" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <!-- Generator: sketchtool 42 (36781) - http://www.bohemiancoding.com/sketch -->
    <title>68284BF1-E5AB-4CFC-9D01-D12772182903</title>
    <desc>Created with sketchtool.</desc>
    <defs>
        <linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-1">
            <stop stop-color="#B7E351" offset="0%"></stop>
            <stop stop-color="#96C226" offset="100%"></stop>
        </linearGradient>
        <path d="M58,54.8873365 C72.0133163,53.6213679 83,41.8430042 83,27.5 C83,12.30883 70.6906485,0 55.5062939,0 L27.4937061,0 C12.3139475,0 0,12.3121694 0,27.5 C0,42.69117 12.3155587,55 27.5075703,55 L38.4840531,55 L39.25,55 L58,70 L58,54.8873365 Z" id="path-2"></path>
        <mask id="mask-3" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="83" height="70" fill="white">
            <use xlink:href="#path-2"></use>
        </mask>
        <rect id="path-4" x="19" y="31" width="21" height="2"></rect>
        <mask id="mask-5" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="21" height="2" fill="white">
            <use xlink:href="#path-4"></use>
        </mask>
        <rect id="path-6" x="19" y="21" width="42" height="2"></rect>
        <mask id="mask-7" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="42" height="2" fill="white">
            <use xlink:href="#path-6"></use>
        </mask>
    </defs>
    <g id="ОС---Компания" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
        <g id="О-нас" transform="translate(-427.000000, -6104.000000)" stroke-width="4">
            <g id="СПРАВКА" transform="translate(0.000000, 5975.000000)">
                <g id="Иконка" transform="translate(427.000000, 129.000000)">
                    <use id="Combined-Shape" stroke="url(#linearGradient-1)" mask="url(#mask-3)" xlink:href="#path-2"></use>
                    <use id="Rectangle-251" stroke="#A2D136" mask="url(#mask-5)" xlink:href="#path-4"></use>
                    <use id="Rectangle-251" stroke="#A2D136" mask="url(#mask-7)" xlink:href="#path-6"></use>
                </g>
            </g>
        </g>
    </g>
</svg>

Обратите внимание, в этом коде мы видим блок defs, внутри которого определяется градиент для последующего использования внутри атрибута fill или любого другого атрибута. Этот внешний градиент и является, в нашем случае, корнем всех зол. Если вот этот код, не меняя, обернуть элементом symbol и добавить в спрайт, вы заработаете как минимум одну проблему, а возможно и больше.

Самая очевидная и известная проблема в браузере Firefox (версия 51.01). Независимо от того используете ли вы ссылку на внешний файл или встроили спрайт на страницу, он просто не отобразит градиент, находящийся внутри блока symbol. Есть один способ решения, люди советуют просто вынести блок defs c градиентом за пределы элемента symbol.

<symbol id="instagram" viewBox="0 0 42 42">
        <title>AE825A6C-57C0-4A3E-AE27-3FEDBA635E69</title>
        <desc>Created with sketchtool.</desc>
        <g id="ОС---Общее" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
            <g id="Главная-страница-Красота" transform="translate(-959.000000, -4630.000000)" fill="url(#radialGradient-1)">
                <g id="Присоединяйтесь" transform="translate(378.000000, 4513.000000)">
                    <g id="Group-2" transform="translate(0.000000, 88.000000)">
                        <path d="M617,40 C617,41.6570313 615.656641,43 614,43 C612.343359,43 611,41.6570313 611,40 C611,38.3429687 612.343359,37 614,37 C615.657031,37 617,38.3429687 617,40 L617,40 Z M602,57 C598.133971,57 595,53.8660292 595,50 C595,46.1339708 598.133971,43 602,43 C605.866029,43 609,46.1339708 609,50 C609,53.8660292 605.866029,57 602,57 L602,57 Z M602,39 C595.924814,39 591,43.9248136 591,50 C591,56.0751864 595.924814,61 602,61 C608.075186,61 613,56.0751864 613,50 C613,43.9248136 608.075186,39 602,39 L602,39 Z M602.000162,33 C607.53696,33 608.192731,33.0210599 610.379068,33.1208512 C612.400814,33.2131905 613.498842,33.5507962 614.229457,33.8349422 C615.197238,34.2111036 615.888002,34.6604885 616.613757,35.3862434 C617.339512,36.1116744 617.788896,36.8024376 618.165058,37.7705429 C618.44888,38.5011578 618.786809,39.5991862 618.879149,41.6209322 C618.97894,43.807593 619,44.4633644 619,50.000162 C619,55.5369596 618.97894,56.192731 618.879149,58.3790678 C618.786809,60.4008138 618.449204,61.4988422 618.165058,62.2294571 C617.788896,63.1972384 617.339512,63.8880016 616.613757,64.6137566 C615.888326,65.3395115 615.197562,65.7888964 614.229457,66.1650578 C613.498842,66.4488798 612.400814,66.7868095 610.379068,66.8791488 C608.192731,66.9789401 607.53696,67 602.000162,67 C596.46304,67 595.807269,66.9789401 593.620932,66.8791488 C591.599186,66.7868095 590.501158,66.4492038 589.770543,66.1650578 C588.802762,65.7888964 588.111998,65.3395115 587.386243,64.6137566 C586.660812,63.8883256 586.211104,63.1975624 585.834942,62.2294571 C585.55112,61.4988422 585.213191,60.4008138 585.120851,58.3790678 C585.02106,56.192407 585,55.5366356 585,50.000162 C585,44.4633644 585.02106,43.807593 585.120851,41.6209322 C585.213191,39.5991862 585.550796,38.5011578 585.834942,37.7705429 C586.211104,36.8027616 586.660488,36.1119984 587.386243,35.3862434 C588.111674,34.6604885 588.802438,34.2111036 589.770543,33.8349422 C590.501158,33.5511202 591.599186,33.2131905 593.620932,33.1208512 C595.807593,33.0210599 596.463364,33 602.000162,33 L602.000162,33 Z M602,29 C596.296859,29 595.581547,29.0242813 593.341766,29.1263281 C591.106578,29.228375 589.579813,29.5834062 588.244344,30.1025 C586.863266,30.6389844 585.692188,31.35725 584.524719,32.5247187 C583.35725,33.6921875 582.638984,34.8632656 582.1025,36.2443437 C581.583406,37.5801406 581.228375,39.1065781 581.126328,41.3417656 C581.024281,43.5815469 581,44.2968594 581,50 C581,55.7031406 581.024281,56.4184531 581.126328,58.6582344 C581.228375,60.8934219 581.583406,62.4198594 582.1025,63.7556563 C582.638984,65.1367344 583.35725,66.3078125 584.524719,67.4752812 C585.692188,68.64275 586.863266,69.3606875 588.244344,69.8975 C589.580141,70.4165938 591.106578,70.771625 593.341766,70.8736719 C595.581547,70.9757187 596.296859,71 602,71 C607.703141,71 608.418453,70.9757187 610.658234,70.8736719 C612.893422,70.771625 614.419859,70.4165938 615.755656,69.8975 C617.136734,69.3606875 618.307812,68.64275 619.475281,67.4752812 C620.64275,66.3078125 621.360688,65.1367344 621.8975,63.7556563 C622.416594,62.4198594 622.771625,60.8934219 622.873672,58.6582344 C622.975719,56.4184531 623,55.7031406 623,50 C623,44.2968594 622.975719,43.5815469 622.873672,41.3417656 C622.771625,39.1065781 622.416594,37.5801406 621.8975,36.2443437 C621.360688,34.8632656 620.64275,33.6921875 619.475281,32.5247187 C618.307812,31.35725 617.136734,30.6393125 615.755656,30.1025 C614.419859,29.5834062 612.893422,29.228375 610.658234,29.1263281 C608.418453,29.0242813 607.703141,29 602,29 L602,29 Z" id="Instagram"></path>
                    </g>
                </g>
            </g>
        </g>
    </symbol>

    <defs>
        <radialGradient cx="14.9305469%" cy="100.347188%" fx="14.9305469%" fy="100.347188%" r="127.774922%" id="radialGradient-1">
            <stop stop-color="#FFB140" offset="0%"></stop>
            <stop stop-color="#FF5445" offset="25.59%"></stop>
            <stop stop-color="#FC2B82" offset="59.9%"></stop>
            <stop stop-color="#8E40B7" offset="100%"></stop>
        </radialGradient>
    </defs>

Это действительно поможет Firefox и не навредит остальным браузерам, но только лишь в том счастливом случае, если ваш спрайт присутствует на странице. Если же, вы используете внешнюю ссылку на спрайт, то после вышеуказанных манипуляций, вместо градиента иконка в IE (версия 11) приобретет сплошной черный цвет.

Далее, Chrome (версия 55) также, при использовании внешней ссылки на спрайт, проигнорирует градиент. И здесь тот же фокус, что и с Firefox уже не действует. Внятных объяснений такому поведению в хроме я не нашла. Если сталкивались с подобной проблемой и нашли решение, делитесь в комментариях.

Подводя итоги по градиентам, напрашивается довольно простой вывод. Если необходимо использовать иконки с градиентами в символьном svg-спрайте – не используйте ссылку на внешний файл, и выносите блок с градиентом за пределы symbol.

Не получается изменить цвет иконки

Здесь все довольно просто. Если иконка у вас выводится без проблем, но смена цвета средствами CSS не работает, скорее всего у какого-нибудь из внутренних элементов остались атрибуты fill, stroke или style. Еще раз проверьте всю разметку иконки на наличие оставшихся атрибутов. Даже если их не осталось в корневом элементе, они могут присутствовать в дочерних. После удаления их удаления проблема должна решиться.

Использование в качестве background-image

Я думаю, ни один верстальщик не любит лишней HTML-разметки. Инлайновый SVG это конечно хорошо и замечательно, но далеко не всегда удобно. Как же быть со старым добрым background-image? Думаю, правильным ответом на этот вопрос, будет «это невозможно». Но оказывается, все же возможно. Хотя придется, конечно, потрудиться.

Известно, что в качестве фона можно указывать внешний svg-файл. Поскольку код внутри symbol не отображается на странице, понадобиться комбинация из тегов view и use для каждой иконки.

То есть для каждой иконки, которую вы хотите использовать в качестве инлайнового svg и в качестве фона, нужно будет добавить вот такой код:

 
    <view id="cloud-view" viewBox="0 0 64 64" />
    <view id="cloud-computing-view" viewBox="0 60 64 64" />
   
    <use xlink:href="#cloud" width="64" height="64" x="0" y="0"></use>
    <use xlink:href="#cloud-computing" width="64" height="64" x="0" y="60"></use>

Обратите внимание на атрибуты viewbox и значение y элементов view и use. Начиная со второй иконки, нужно добавить сдвиг по оси y (или x), чтобы иконки на наползали друг на друга. Модифицированный таким образом спрайт, можно увидеть на странице. После этого, можно ссылаться на иконку в свойстве background:

.sprite-background-icon{
    width: 150px;
    height: 150px;
    display: inline-block;
    margin-right: 30px;
}

.cloud{
    background: url('sprite-remote.svg#cloud-view') top left no-repeat;
}

.cloud-computing{
    background: url('sprite-remote.svg#cloud-computing-view') top left no-repeat;
}

See the Pen Symbol SVG Sprite detail guide — SVG sprite symbol in background-image by dreamhelg (@dreamhelg) on CodePen.dark

И о чудо, действительно картинка выводится в фоне и масштабируется исходя из размеров блока. Плохие новости – управлять цветом через CSS не получится. При острой необходимости, можно создать для одной и той же иконки несколько вариантов view и use, атрибутами style, где указать разные варианты цветов. Браузеры Firefox, Chrome, IE11 – все работает. Есть информация, что не работает в Safari.

Как видите, технология пока сыровата, и полной поддержки браузерами не наблюдается. Сложно сказать, приживется ли она в будущем, но знать о такой возможности всегда полезно.

Автоматическая генерация спрайта

Если вы как и я, не любитель собирать спрайты вручную, можно автоматизировать этот процесс с помощью плагина gulp-svg-sprite. Плагин имеет множество опций и умеет не только символьные спрайты но и многие другие.

Ставим плагин

npm install gulp-svg-sprite

Редактируем gulpfile.js и создаем объект конфигурации, который в дальнейшем будем передавать плагину:

var gulp = require('gulp'),
    svgSprite = require('gulp-svg-sprite');

var config = {
    shape: {
        dimension: {         // Set maximum dimensions
            maxWidth: 500,
            maxHeight: 500
        },
        spacing: {         // Add padding
            padding: 0
        }
    },
    mode: {
        symbol: {
            dest : '.'
        }
    }
};

Свойство shape отвечает за настройки генерируемых svg-фигур. Здесь можно настраивать максимальные размеры, отступы, влиять на идентификаторы, которые генерируются автоматически и еще много чего.

В свойстве mode описываются виды спрайтов, которые требуется сгенерировать. Если нужно, можно указывать хоть все сразу, но мы остановимся на symbol. Указываем свойство dest, это папка для результирующего спрайта. В принципе, можно оставить это значение пустым. Тогда плагин по умолчанию создаст папку symbol а внутри нее папку svg и туда положит спрайт. У меня там точка, чтобы не создавать дополнительную папку symbol.

Создаем таск для спрайтов

gulp.task('svg-sprite', function (cb) {
    return gulp.src('svg-separate/*.svg')
        .pipe(svgSprite(config))
        .pipe(gulp.dest('sprites'));
});

Все просто, отдельные svg-иконки лежат в папке svg-separate. Указываем путь к ним, запускаем плагин с объектом конфигурации, и помещаем результат в папку sprites. Плагин генерирует id для элементов symbol из имен файлов svg-картинок. Поэтому, было бы неплохо давать им осмысленные имена, с тем чтобы не испытывать сложностей в дальнейшей работе.

Заключение

SVG-спрайты – прекрасная альтернатива растровым спрайтам и иконочным шрифтам. Даже не смотря на имеющиеся ограничения и небольшие проблемы, это определенно перспективная технология, которая улучшается с каждым днем. Не поленитесь потратить немного времени на ее изучение. В этой статье, я постаралась максимально подробно собрать и рассмотреть возможные проблемы при использовании символьных svg-спрайтов, а также способы их решения. Надеюсь, мой опыт будет вам полезен.

Автор svg-иконок из примеров — Elias Bikbulatov

Понравилась статья? Поделить с друзьями:
  • Shadow of the tomb raider ошибка internal error 0x0d interface not found steamuser023
  • Shadow of the tomb raider internal error 0x0d interface not found steamclient022
  • Shadow of the tomb raider error while reading game data
  • Shadow of the colossus ошибка 0xc000007b
  • Shadow fight 2 ошибка соединения