Can I embed HTML into an HTML5 SVG fragment? - html

HTML5 supports the <svg> tag, allowing to embed SVG into HTML.
Digging a little deeper, can I nest some HTML inside my <svg> fragment? For example, I'd like to put a CSS'ed <table> in some part of my SVG graphics.
I made a small test and Chrome12 didn't like the HTML <p> inside the <svg>.
Is there some technique to make it work (such as maybe an html container tag?)?

Yes, with the <foreignObject> element, see this question for some examples.
Alternatively, if you have an html5 document you can also use CSS positioning and z-index to make parts of html visible where you want laid out on top of the svg. If you do it like that you don't need to nest the html inside the svg fragment. This will give you the most consistent behaviour across browsers in my experience.

Copied from bl.ocks.org (thank you, Janu Verma)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>HTML inside SVG</title>
<style type="text/css"></style></head>
<body>
<div>I'm a div inside the HTML</div>
<svg width="500" height="300" style="border:1px red solid" xmlns="http://www.w3.org/2000/svg">
<foreignobject class="node" x="46" y="22" width="100" height="100">
<div style="border:1px green solid">I'm a div inside a SVG.</div>
</foreignobject>
<circle cx="100" cy="160" r="50" fill="blue"></circle>
</svg>
<div>Interesting! But you a Foreign Object.</div>
</body>
</html>
UPDATE
Note that there is a 'camel error' in the above - it's supposed to be foreignObject (capital O), not foreignobject. It doesn't matter if the misspelling is in 'straight' HTML/SVG. But if you use JavaScript (.createElementNS), then it won't work without proper camel case (April 2020)

Foreign Objects are not supported on Internet explorer. Please check ForeignObject

Related

SVG code within HTML versus SVG embedded with <img> tag

Is there a technical (dis)advantage to including SVG-code in a HTML-file versus embedding it with an <img> tag?
I'm not asking about personal preference or opinion, but factual differences on the technical level.
Browser compatibility would be an example. Caniuse.com tells me there is virtually no difference in that respect (SVG as img vs inline SVG code). But maybe there are other factors that I'm not aware of?
SVG as part of the HTML code:
<html>
...
<body>
...
<svg version="1.1" ... >
...
</svg>
...
</body>
</html>
SVG embedded as image:
<html>
...
<body>
...
<img src="image.svg" ... >
...
</body>
</html>
There are a few advantages and disadvantages for both:
Pros for <svg> tag:
Fewer HTTP requests
You can use the CSS fill property and change the color of the SVG
SVG is part of the content, so it is clickable and you can insert text
Pros for <img> tag:
Svg files can be cached
You don't see multiple lines of irrelevant code in your files
If you need to change it later then you just change one file
Anyways, the <svg> tag appears to be more useful.
I recommend you to use that.

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...

Can I use alt and title properties within SVG elements?

To make my inline SVG image more searchable by google, can you add alt/title properties/attributes within svg elements such as "path" "circle" "line" etc?
I already know that you can use a title tag within the "svg" tag, like this..
<svg>
<title>this is a title tag.</title>
</svg>
Below is an example of what I am talking about.
<svg version="1.1" id="Layer_1">
<style type="text/css">
.st0{fill:none;stroke:#000000;stroke-width:5;stroke-linecap:round;stroke-miterlimit:10;}
</style>
<path class="st0" title=“this is what I am talking about” d="M567,1136.2l37,10.9c13.3,3.9,27.2,3.1,39.9-2.4l0.6-0.3"/>
<line id="hi2" class="st5" alt=“This is what I am Talking About” x1="72" y1="-169.7" x2="108" y2="-169.7"/>
</svg>
As far as I am aware, alt text cannot be used on SVGs. You are right in using <title> tags, but you can also add in <desc> to add more information.
Take a look at this answer here: https://stackoverflow.com/a/4756461/3909886 for a more detailed look into this issue.
title as an attribute has no meaning in SVG, its equivalent as you point out in the question is the <title> element.
alt as an attribute also has no meaning, the SVG equivalent is the <desc> element.

Not able to embed a SVG file using xlink:href

I need to embed a SVG file in a HTML document. File Example.svg is in the same directory of the HTMl file.
Using the following code, no SVG is inserted and nothing shown, but looking at network debut panel in Chrome DEV tools i can see the SVG is loaded.
What could be wrong and how to fix it?
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
</head>
<body>
<svg width="250" height="250">
<use xlink:href="Example.svg"></use>
</svg>
</body>
</html>
Content of my SVG file https://jsfiddle.net/900xLbor/
Same problem here: https://jsfiddle.net/900xLbor/2/
MDN article about xlink:href attribute on the <use> element :
An <IRI> reference to an element/fragment within an SVG document.
In other words, you need to set the id of the element to use into the href :
<use xlink:href="Example.svg#svg2"/>
Here is a plunker demonstration