svg external stylesheet not work - html

I am new svg learner and try to animate svg file with external style sheet but fail fail to style my object 'Cube'.
[index.html file]
<head>
<link rel="stylesheet" type="text/css" href="cube.css">
</head>
<body>
<img src="cube-motion.svg" height="350px" />
<div class="logo">
<h1>SVG Cube Animation</h>
</div>
[cube-motion.svg file]
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/css" href="cube.css" ?>
<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 200 200" style="enable-background:new 0 0 200 200;" xml:space="preserve">
<g>
<polygon id="l1" class="st0" points="105.3,92.7 86.3,103.3 67.3,92.9 67.1,71.9 86,61.2 105.1,71.6 "/>
<polyline id="l2" class="st1" points="67.1,71.9 86.2,82.5 86.3,103.3 67.1,93.1 66.9,71.9 "/>
<animateTransform
attributeName="transform"
type="translate"
from="0 0"
to="0 75"
begin="0s"
dur="3s"
repeatCount="indefinite"
/>
</g>
</svg>
[external stylesheet file cube.css]
.st0 {
fill:#FF00FF;
stroke:#000000;
stroke-miterlimit:10;
}
.st1 {
fill:#23D83C;
stroke:#000000;
stroke-miterlimit:10;
}
.logo {
position: absolute;
left: 400;
top: 150;
}

You are on the right track with the inclusion of the external stylesheet inside the SVG:
<?xml-stylesheet type="text/css" href="cube.css" ?>
The reason it doesn't work is because the SVG is loaded in the HTML as an <img> which - rightfully - does not allow additional external assets to be processed.
If you're adamant on having the CSS from an external file, you have two options, either embed the SVG inside the html or use <object data=file.svg type=image/xml+svg></object>.
Depending on your use case, you basically have three ways to use CSS for styling:
<img src="my.svg">
Images are not interactive and are not allowed to load any other assets within themselves. Simple presentation of the referenced image file only.
It does allow to use CSS, but only from a <style>-element inside the SVG.
<object data="my.svg" type="image/svg+xml"></object>
Objects can do more than images, such as loading additional assets and even include isolated (within the loaded SVG) interactions (e.g. the CSS :hover-pseudoclass)
Loading an external CSS file is done as you have it in the example code, the <?xml-stylesheet...?>-instruction goes before the <svg>-tag
<svg...>...</svg>
Fully embedded in the HTML document, this is allows for full integration within the page (this may have benefits on the interaction side and downsides on the CSS side, as you'll then have to take style isolation into consideration), but also the least re-usable as you'd basically have to repeat the entire SVG, which doesn't matter if used once on a page.
Note that in order to embed the SVG inside the HTML document, you cannot put any of the SVG doctype and/or xml declarations in the HTML (<?xml...?>, <!DOCTYPE svg...> and <?xml-stylesheet...?>).
With embedded SVG, you can simply import (or inline) the style using the usual HTML <link> or <style> nodes, where the <style> element may also still be inside the <svg>-element.
Here's a quick sample of the difference between <img> and <object>

Related

Is there a way to fix the HTML validation error? While keeping using the SVG as the source code of the `<img>` tag?

Is there a way to fix the HTML validation error? While keeping using the SVG as the source code of the <img> tag?
Error: Bad value data:image/svg+xml;utf8,<svg
xmlns='http://www.w3.org/2000/svg' height='10px' width='20px'></svg>
for attribute src on element`
My source code:
<img alt="homepage" src="data:image/svg+xml;utf8,<svg
xmlns='http://www.w3.org/2000/svg' height='10px' width='20px'></svg>"
/>
To use an SVG as a data URI within an <img> element, the SVG code needs to be escaped:
<img alt="homepage" src="data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' height='10px' width='20px'%3E%3C/svg%3E">
There are several free tools for doing this, such as URL-encoder for SVG.
If you want a non-interactive svg, use with script fallbacks to png version (for older IE and android < 3). One clean and simple way to do that:
<img src="your.svg" onerror="this.src='your.png'">
your.svg being the path to your svg.
This will behave much like a GIF image, and if your browser supports declarative animations (SMIL) then those will play.
If you want an interactive svg, use either <iframe> or <object>.
If you need to provide older browsers the ability to use an svg plugin, then use <embed>.
For svg in css background-image and similar properties, modernizr is one choice for switching to fallback images, another is depending on multiple backgrounds to do it automatically:
div {
background-image: url(fallback.png);
background-image: url(your.svg), none;
}
An additional good read is this blogpost on svg fallbacks.
For inline SVG; <svg> tags can be inserted as <svg> elements directly into the HTML and not part of the <img> tag. As it is inline SVG the <img> tag is pretty redundant as all the required parameters can be held inside the <SVG>.
Read about it here
Example:
<html>
<head>
<title>SVG Demo</title>
</head>
<body>
<svg
viewBox="0 0 100 100" preserveAspectRatio="xMidYMid slice"
style="width:35%; height:35%; position:absolute; top:0; left:0; z-index:-1;">
<linearGradient id="gradient">
<stop class="begin" offset="0%"/>
<stop class="end" offset="100%"/>
</linearGradient>
<rect x="0" y="0" width="100" height="100" style="fill:#cc9966;" />
<circle cx="50" cy="50" r="30" style="fill:#f9f333;" />
</svg>
</body>
</html>

Is there a way to have SVG as data URL that contains an image with source from a non-data URL? [duplicate]

I have a page, that includes several SVG files. To synchronize the styling of those SVG files I wanted to create a single stylesheet to hold all styling information.
However, when including the SVG like below, the CSS wont get applied. Anybody having a solution to this or is it just not possible to link to other (CSS) files in an SVG referenced by <img src="..." />?
See the example code below. When loading pic.svg directly in the browser, all styles get applied and one can see a green rectangle. But when opening page.htm all there is to see is a black rectangle. So obviously none of the defined styles was applied.
page.htm
<!DOCTYPE html>
<html>
<body>
<img src="pic.svg" style="width: 100px; height: 100px;" />
</body>
</html>
pic.svg
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<?xml-stylesheet type="text/css" href="styles.css" ?>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 100 100"
>
<rect x="10" y="10" width="80" height="80" />
</svg>
styles.css
rect {
stroke: black;
fill: green;
}
EDIT
From an answer, that for a short time appeared here, I got this link to the spec and the following citation. In my opinion this states, that the above code should work!
Stand-alone SVG document embedded in an HTML or XML document with the ‘img’, ‘object’ (HTML) or ‘image’ (SVG) elements
[...]
Citing from your link "Style sheets defined anywhere within the referenced SVG document (in style elements or style attributes, or in external style sheets linked with the style sheet processing instruction) apply across the entire SVG document, but do not affect the referencing document (perhaps HTML or XHTML)."
An alternative is to use the <object> tag in your html :-
<object type="image/svg+xml" data="pic.svg" width="100" height="100"></object>
It's a BIG shame the <img> tag won't work. I don't want to mess about hacking with converting the SVG to a data URI. It's to do with cross-site vulnerabilities on indirectly loading resources and the use of an "Open Redirector".
Note that in my testing lastnight, the <img> tag method DOES work in IE10, but neither Chrome nor FireFox.
I don't know why <object> is allowed and <img> isn't. An oversight?
For privacy reasons images must be standalone files. You can use CSS if you encode the stylesheet as a data uri. E.g.
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<?xml-stylesheet type="text/css" href="data:text/css;charset=utf-8;base64,cmVjdCB7IA0KICAgIHN0cm9rZTogYmxhY2s7DQogICAgZmlsbDogZ3JlZW47DQp9" ?>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 100 100"
>
<rect x="10" y="10" width="80" height="80" />
</svg>
There are various online converters for data URIs.
The answers above are great. I found it simplest, though, to just embed the raw SVG tag itself on my webpage. This allowed the SVG to inherit font-family styles declared in my page's CSS without issue...

SVG image embedded in web page doesn't show

I'm trying to embed a set of SVG images in a blank web page.
<html><head></head>
<body>
<img width="117px" src="img/icone/phone_hex034F84.svg" alt="image">
<img width="320px" src="img/illustrazioni/SHIPPER3.svg" alt="image">
</body>
</html>
Both files are self-contained svg generated by Illustrator.
While the first does render in the browser the second (SHIPPER3.svg) doesn't.
See the code: http://104.155.112.173/land/img/illustrazioni/SHIPPER3.svg
You can download the full source from the previous link as I cannot embed it in the question (too large). Although, I'll embed here just the preamble.
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 20.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="_x5B_SHIPPER1_x5D_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
y="0px" viewBox="0 0 733.3 587.8" style="enable-background:new 0 0 733.3 587.8;" xml:space="preserve">
<style type="text/css">
.st0{clip-path:url(#SVGID_2_);}
.st1{fill:#EDEDED;}
.st2{fill:#F2F2F2;}
If I copy and paste SHIPPER3.svg in http://www.freecodeformat.com/svg-editor.php it does render. I can also open it in Sketch with no problems.
I tried to embed SHIPPER3.svg also as inline svg but same, again, no show.
What I am missing?
Several problems in your SHIPPER3.svg:
all your top-level groups has class st0 which is said to be clipped out by clipPath that is outside entire viewBox
clipPath #SVGID_2_ has style="display:none;" what also hides it
See:
<svg version="1.1" viewBox="0 0 733.3 587.8">
<style type="text/css">
.st0{clip-path:url(#SVGID_2_);}
/* ... */
</style>
<defs>
<ellipse id="SVGID_1_" cx="1085.6" cy="279.3" rx="251.8" ry="233.4"/>
</defs>
<clipPath id="SVGID_2_">
<use xlink:href="#SVGID_1_" style="display:none;overflow:visible;"/>
</clipPath>
<g class="st0">
<!-- ... -->
</g>
</svg>
Further to a comment I left above, you may wish to replace the <clippath id='SVGID_2_' element with the following:
<clipPath xmlns="http://www.w3.org/2000/svg" id="SVGID_2_">
<ellipse xmlns="http://www.w3.org/2000/svg" id="SVGID_1_" cx="360" cy="290" rx="325" ry="260"/>
</clipPath>
This does 2 things. (0) it removes the link to the SVGID_1_ element by inserting the data that was inside it directly. (1) repositions and sizes the ellipse

How to move svg path out of html

I am using this example from Chris Coyer
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" mlns:xlink="http://www.w3.org/1999/xlink" style="display: none;">
<defs>
<g id="icon-image">
<path class="path1" d="M0 4v26h32v-26h-32zM30 28h-28v-22h28v22zM22 11c0-1.657 1.343-3 3-3s3 1.343 3 3c0 1.657-1.343 3-3 3-1.657 0-3-1.343-3-3zM28 26h-24l6-16 8 10 4-3z"></path>
</g>
</defs>
</svg>
<h1>
<svg viewBox="0 0 32 32">
<use xlink:href="#icon-phone"></use>
</svg>
Call me
However, I would like the path definitions to NOT be in the html as they will be used throughout the app.
Is this possible? (Note: I have read the answer that suggests javascript to manually inject the svg into the html. I don't want to do that either.)
I know there are many ways of embedding/linking SVG paths and files. And I have tried them all. In particular, I need to be able to style it to the currentColor. As covered in detail in this blog post, this cannot be done with external SVG files which are then used in an img tag.
So the closest thing I have found is this example above. However, I still don't want the path embedded in the html. If I could somehow get it in an external file of some type so it is reusable, that would be great.
Another option would be to convert SVG to a font
Searching the internet for "convert SVG to font" will give you a lot of sites/tools doing that, like:
https://icomoon.io/app/#/select
https://glyphter.com/
http://fontastic.me/
Also "HTML entities" have some reusable icons etc.
https://dev.w3.org/html5/html-author/charref
There's only one remaining option here. You don't want to embed the svg manually, you don't want to inject it with javascript and you don't want to use it in an img tag since you want to modify the properties with css. The only remaining solution would be to use your server-side language to inject it.
If you're using php, you can simply echo the content of your svg file where you want:
<?php echo file_get_contents(file_path); ?>
Another option I found is SVG Sprites, explained in detail by Chris Coyier
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8"/>
<style>
.icon {
width: 125px;
height: 125px;
background: #eee;
fill: currentColor;
}
body {
padding: 20px;
}
</style>
</head>
<body>
<div style="color: red">
<svg class="icon"><use xlink:href="menu.svg#beaker"/></svg>
</div>
<div style="color: brown">
<svg class="icon"><use xlink:href="menu.svg#fish" /></svg>
</div>
</body>
</html>
And then this in a separate file called menu.svg:
<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
<symbol id="fish" viewBox="0 26 100 48">
<path d="M98.5,47.5C96.5,45.5,81,35,62,35c-2.1,0-4.2,0.1-6.2,0.3L39,26c0,4.5,1.3,9,2.4,12.1C31.7,40.7,23.3,44,16,44L0,34
c0,8,4,16,4,16s-4,8-4,16l16-10c7.3,0,15.7,3.3,25.4,5.9C40.3,65,39,69.5,39,74l16.8-9.3c2,0.2,4.1,0.3,6.2,0.3
c19,0,34.5-10.5,36.5-12.5S100.5,49.5,98.5,47.5z M85.5,50c-1.4,0-2.5-1.1-2.5-2.5s1.1-2.5,2.5-2.5s2.5,1.1,2.5,2.5
C88,48.9,86.9,50,85.5,50z" />
</symbol>

Reference an svg embedded in html in html document in same folder

I would like to reference an svg embedded in one html document in another html document in the same folder. I don't need a fallback, but I would prefer one. I have seen: HTML - pick images of Root Folder from Sub-Folder, and How to link html pages in same or different folders?, and Do I use <img>, <object>, or <embed> for SVG files?.
I have one html document with the svg that I would like to reference here: (this document is called "pd_unit_red_fighter_v.0.0" and is located in the same folder)
<!doctype html>
<html>
<head>
<title>Title</title>
</head>
<body>
<svg id="red_fighter" width="480" height="480" viewBox="0 0 24 24">
<g stroke-width=".25" stroke="#000" fill="#ccc" >
<circle cx="12" cy="12" r="11.5" fill="#800" />
</g>
</svg>
</body>
</html>
I have another html document and I would like this document to reference the svg in the other one:
<!doctype html>
<html>
<head>
<title>test</title>
</head>
<body>
<object data="red_fighter.svg" type="image/svg+xml">
<img src="./pd_unit_red_fighter_v.0.0.html" />
<a href="#./pd_unit_red_fighter_v.0.0.html" >
<img class="logo" src="red_fighter.svg" width="240" height="240"/>
</a>
</object>
</body>
</html>
I have tried both the object tag and but I cannot get it to work. Is there another tag I should use or am I using the wrong information? I am new to this so I apologize for my lack of knowledge.
When you reference an SVG file using an object or image tag it must actually be an SVG file and not svg data embedded in an html file so you want red_fighter.svg to be
<svg xmlns="http://www.w3.org/2000/svg" id="red_fighter" width="480" height="480" viewBox="0 0 24 24">
<g stroke-width=".25" stroke="#000" fill="#ccc" >
<circle cx="12" cy="12" r="11.5" fill="#800" />
</g>
</svg>
Note the namespace attribute which is mandatory for standalone SVG files.
Then you can reference it using an object or img tag.
Take care that the svg file is served with the correct mime-type (try viewing it directly to check it works first).