How to reference SVGs in html with access to css styling - svg

I have a number of different SVGs to include in my project (Angular 10).
Some of them are used multiple times with different sizes and fill colors etc.
I am trying to find a way to reference them in my html code and have access to via styling:
CSS:
.svg {
fill: red;
}
Referencing:
<svg>
<use></use>
</svg>
<object></object>
<img></img>
<embed></embed>
As yet, I have not been able to find a solution that allows me to reference them but also have the ability to access the fill property in the SVG itself as i can when adding inline.
Inline:
<svg>
<path>
</path>
</svg>
Adding them inline is going to be messy.
How is this usually handled?
Your help is appreciated!

You can't. CSS does not apply across document boundaries. If the CSS rules are in the HTML (or imported into the HTML via <link>) then it cannot affect the content of external files.
One solution people have used in the past is to use a bit of Javascript to inline SVG files at runtime.
Otherwise, you will need to put the CSS in the external SVG itself.

Related

Problem with imported stylesheet in svg file after webpack processing

According to https://www.w3.org/TR/SVG/styling.html#StylingWithCSS, in order to configure svg to use styles defined in an external stylesheet, you can import them as follows:
<svg xmlns="http://www.w3.org/2000/svg">
<style>
#import url(mystyles.css);
</style>
<rect .../>
</svg>
This works fine in Chrome when the files exist in their original format, whether served from a web server or read from the local filesystem, but after building with webpack the resulting app's svg elements have no styling, so clearly the stylesheet isn't getting found.
All of the searches I've done turn up lots of info on what is more or less the reverse operation - referencing svg files from within css (e.g., to specify an svg image as the background for an element).
Does anyone know of a webpack plugin and/or configuration specifically for this case?

Possible to use SVG sprites without needing <svg> for each instance?

I'm attempting to move from font icons (icomoon.io) to SVG sprites. Is it possible to use SVG sprites without needing < svg > markup for each icon instance?
What I really liked about the font icons was that I didn't have to clutter my HTML with any additional elements to get the icon to display. I usually just targeted a simple class on whatever element I wanted the icon to display and then used pseudo selectors to display the icon, e.g.:
<h1 class="news">News</h1>
h1.user:before {
font-family: 'icons';
content: '\news';
}
That made a lot of sense to me, and all of my icons were easily managed almost completely in CSS. I rarely had to touch my HTML as long as my markup contained appropriate classes.
I've since switched my build system to Grunt and thought I'd give SVG sprites a try. Almost every1 article2 I3 can4 find5 on the subject says you need to add an additional SVG element to your markup wherever you want each instance to display, e.g.:
<h1>
<svg class="icon">
<use xlink:href="#icon-news">
</svg>
News
</h1>
That seems like a step backwards to me, at least in the management of markup. To me, an icon is usually presentation that should be separate from document structure. Are we doing it this way simply because of the state of SVG support in browsers?
Ideally, I'd love to be able to do something like this:
<h1 class="news">News</h1>
h1.news:before {
display: inline-block;
width: px;
height: px;
background: url(icons.svg#news) no-repeat;
}
This post seems to be closer to what I'm looking for, but I'm not sure of browser support and how to do it automatically in a build system like Grunt.
SVGs can be loaded as files exactly the same way as other images using <img> tags or CSS background, and can be used as sprites exactly the same way too. The only difference is that you have to specify the size you want it (because it's scalable, so the browser doesn't automatically know how big it is like it does with PNGs).
Depending on how you want to use the image, loading them this way may or may not be suitable as some SVG features aren't available, but it can be done.

Why can't I reference an SVG linear gradient defined in an external file (paint server)?

Please have a look at this Pen:
http://codepen.io/troywarr/pen/VYmbaa
What I'm doing here is:
defining an SVG symbol (<symbol>)
defining an SVG linear gradient (<linearGradient>)
using the <use> element to reference the SVG symbol I've created
in the CSS, defining two classes:
external, which references the linear gradient defined in this external .svg file (right click and view source)
internal, which references the linear gradient defined in the local HTML (which is, I believe, effectively identical to the one in the external file)
Because I've applied the internal class to the <svg> element at the bottom of the HTML example, the gradient is applied, rendering a blue gradient checkmark. That's what I'm after.
But, if you switch the internal class to external in the HTML example, the checkmark is no longer visible:
http://codepen.io/troywarr/pen/vEymKX
When I watch Chrome Inspector's "Network" tab, I don't see the browser trying to load the SVG file at all. Is there a problem with my syntax, or is something else going on here?
It at least looks like I'm doing this right, based on a few references I've found:
http://www.w3.org/TR/SVG/painting.html#SpecifyingPaint
http://www.w3.org/TR/SVG/linking.html#IRIReference
https://stackoverflow.com/a/7118142/167911
But, nothing I've tried so far has allowed me to reference a linear gradient defined in an external .svg file.
Thanks for any help!
After more research, it looks like this is a browser support issue. See:
https://code.google.com/p/chromium/issues/detail?id=109212
https://bugs.webkit.org/show_bug.cgi?id=105904
Sadly, I'd come across this question before posting mine, and had thought that surely, in 5-1/2 years, browser support would have caught up - but that doesn't appear to be the case.
As of 2015, apparently Firefox and Opera are the only two browsers to support this in any substantial way.
Back to the drawing board...
You can use svg4everybody with polyfill: true option, it will insert all external symbols instead of use tags. But it will cause the second svg loading.
So you can download svg using an ajax request and then insert it on the page hiding with the styles.
<script>var ajax=new XMLHttpRequest;ajax.open("GET","/img/svg-sprite.svg",!0),ajax.send(),ajax.onload=function(a){var b=document.createElement("div");b.classList.add("hidden"),b.innerHTML=ajax.responseText,document.body.insertBefore(b,document.body.childNodes[0])};</script>
In this case:
/img/svg-sprite.svg — is your svg path.
.hidden class styles:
.hidden {
position: absolute !important;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(1px, 1px, 1px, 1px);
}
And your code might look like this:
<svg><use xlink:href="#logo"></use></svg>

SVG fill transition doesn't work when embeded by using <img> tag

I defined CSS transition rules in my svg. It's something like:
#mark #bg {
transition: fill 200ms;
fill: #245575;
}
#mark:hover #bg {
fill: #ff5c26;
}
When I drag it into browser's blank page and test it, the transition works fine. But if I embed the svg into my website using <img src="images/mark.svg" alt="">, the transition doesn't work.
Did I miss something?
Images either via <img> tags of via the CSS background-image image property cannot be interactive and have other restrictions in order to maintain user's privacy and security.
If you ask yourself "could I do this if the image was a .png or a .gif?" then you'll be on the right lines. Browsers have deliberately chosen to keep to the same mental model for SVG files so that the capability of images is easy to understand.
If you want transitions to work you'll need to use an <object> or <iframe> tag or embed the SVG inline in the html document.

Generating SVG font from multiple SVG graphics in Node.js

I'd like to create a Node.js app that allows users to combine a bunch of SVG icons into a custom web-font icon set. The only similar project I've found is this site which looks interesting but is pretty buggy.
Eventually I'd like this app to also output all the various cross-browser font files and the CSS to use these icons on a page using best practices. So the overal goal is to create an SVG icon framework.
But the first thing I want to get working is combining multiple SVG icons into a SVG font file. Must be possible if the above mentioned site is doing it but I'm having trouble finding any good info.
Could anyone point me in the right direction? Thanks!
Edit: I came across this service which looks very similar to my goal although I don't want to host the fonts and I'd like my service to be free (and possibly open-source as well).
Kind of late, but if anyone else will need it, i think this will do: https://github.com/sapegin/grunt-webfont
Like many of my big ideas, someone thought of it first :)
For anyone who may come across this, check out Keyamoon's font generator tool.
If you want to automate things there is an NPM package called svg-font-create.
Glyphter.com handles multi-path icons so that might be a good resource for you as well.
You may try svg-join for combine multiple SVG in one symbol collection.
This tool create two files for you.
The first is "svg-bundle.svg":
<svg ...>
<symbol id="svg1" ...>
<symbol id="svg2" ...>
</svg>
Every symbol is your separate SVG file.
The last one is "svg-bundle.css":
.svg_svg1,
.svg_svg2 {
width: 20px; // for example
height: 20px;
}
Now you may use it in your html:
<link rel="stylesheet" type="text/css" href="svg-bundle.css" />
...
<svg class="svg_svg1"><use xlink:href="svg-bundle.svg#svg1"></svg>
<svg class="svg_svg2"><use xlink:href="svg-bundle.svg#svg2"></svg>

Resources