Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I re-use the same SVG in a page and apply different CSS?

Tags:

html

css

svg

I have an SVG file that I want to use in a web page. I want the image to appear multiple times, but to apply different CSS styles to each one.

Is this possible?

Clarification

When I say "apply different CSS styles", I mean that I want to style the SVG contents (stroke, color, radius, etc), not just the width of an <img> or something.

Also, I don't consider "copy and paste the SVG contents" to be "re-using" it. I want to create a file like logo.svg and reference it from the HTML.

like image 473
Nathan Long Avatar asked Aug 01 '14 10:08

Nathan Long


People also ask

Can a SVG be used more than once?

An ability to define code in one location and reuse it in another helps you make your code more modular, maintainable, and readable. SVG provides that ability through elements that define the code and elements that reference it for reuse.

Does CSS affect SVG?

There are many Scalable Vector Graphics (SVG), but only certain attributes can be applied as CSS to SVG. Presentation attributes are used to style SVG elements and can be used as CSS properties. Some of these attributes are SVG-only while others are already shared in CSS, such as font-size or opacity .

What should you do to reuse an SVG image multiple times easily and clearly?

The SVG <use> element can reuse an SVG shape from elsewhere in the SVG document, including <g> elements and <symbol> elements. The reused shape can be defined inside the <defs> element (which makes the shape invisible until used) or outside.

Can SVGs be nested?

The SVG format allows for the nesting of SVG graphics. It is possible for an “<svg>” elements, to be placed within another “<svg>” element.


1 Answers

No, not currently

Styling the contents (stroke, fill, etc) of an SVG from a containing HTML document is currently not supported.

@RobertLongson was kind enough to point me to the SVG Parameters spec, which could provide a partial solution. It is not implemented in any browser, but can be used with a Javascript shim. However, when I emailed the SVG working group with a question about it, I was told:

The SVG Parameters doc is currently out-of-date. The plan at the moment is to integrate it with CSS Custom Properties and var(); the spec will then become an alternative way to define a custom property.

And

SVG <img>s are actually in a separate document entirely; it's basically the same as an <iframe>, just locked down more strictly. We don't allow direct selection across document boundaries for a combination of security, sanity, and performance reasons.

That said, it seems reasonable for the Parameters spec to define a way to take values from the referencing environment, so you'd set the property on the <img> itself and it would transfer through to the contained document at the document's request.

A non-spec-compliant hack: the use tag

For the record, the following seemed to accomplish my stated goals (technique borrowed from CSS-Tricks), but @RobertLongson let me know that it only worked in Firefox (I think I was using version 31) because Firefox was not compliant with the spec.

<!DOCTYPE html> <html>   <head>     <title>SVG Reuse Demo</title>     <meta charset="UTF-8" />     <meta http-equiv="Content-Type" content="text/html" />     <style type="text/css">       .circle   .uno { stroke: orange; stroke-width: 5px; }       .circle-1 .uno { fill: blue; }       .circle-2 .uno { fill: red; }       .circle-3 .uno { fill: green; }     </style>   </head>   <body>     <!-- Single definition of SVG -->     <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">       <symbol id="disc" viewbox="0 0 100 100">         <circle class="uno" cx="50" cy="50" r="40">       </symbol>     </svg>     <!-- Re-use; each is styled differently (see above) -->     <svg class="circle circle-1">       <use xlink:href="#disc">     </svg>     <svg class="circle circle-2">       <use xlink:href="#disc">     </svg>     <svg class="circle circle-3">       <use xlink:href="#disc">     </svg>   </body> </html> 

Even if it were standard, this technique would be less than ideal; the ideal solution would allow using an SVG defined in an external file, like circles.svg.

This is because:

  1. It is clutter to paste it into the HTML (my actual use case may be 300 lines of SVG)
  2. If it were a separate file, I could re-use it in other HTML documents
  3. I could edit it with SVG-specific syntax highlighting
  4. It could be requested and cached separately from the HTML document
  5. ... basically all the other reasons we normally put CSS and images in separate files instead of inline in HTML. :)
like image 126
Nathan Long Avatar answered Sep 21 '22 01:09

Nathan Long