I've found a rather cool SVG loader-thingie on codepen, and it works, but I'm having trouble figuring out how to get it into the center of the screen. Regular 'ole Css is not working, so I'm kind of stuck.
This is the SVG/HTML:
<svg width="300px" height="320px">
<path class="tri1" d="M11.7 118L9.719 118 72.5 9.259 135.281 118z"></path>
<path class="tri2" d="M12.2 118L9.719 118 54.602 40.259 99.486 118z"></path>
<path class="tri3" d="M48.8 118L46.496 118 72.991 72.11 99.486 118z"></path>
</svg>
And this is the Css that matters:
svg {
vertical-align: bottom;
display: inline-block;
}
Please help and thanks in advance!
Assuming all your code is in one file (everything in the HTML) and you are not loading the SVG using img or via background-image, try this:
<style>
#loadingSVG { position: absolute; top:50%; left:50%; }
</style>
<svg width="300px" height="320px" id="loadingSVG">
<path class="tri1" d="M11.7 118L9.719 118 72.5 9.259 135.281 118z"></path>
<path class="tri2" d="M12.2 118L9.719 118 54.602 40.259 99.486 118z"></path>
<path class="tri3" d="M48.8 118L46.496 118 72.991 72.11 99.486 118z"></path>
</svg>
See it here: http://jsfiddle.net/993eL/
Now, assumptions aside, the game changes if you are trying to load it as an external file or if you want to use an external stylesheet. If you want to use external stylesheets, basically you have 2 options to be able to style your SVG.:
Have the SVG inline in the HTML document. It doesn't matter if you
insert it via server-side when generating the page or just copypaste
it in the document, it has to be inline.
Load the SVG as an object element so you don't have to insert it in the HTML, but you'll have to use a separate external stylesheet loaded from inside the SVG file.
Using external stylesheets
Example with method 1: inline SVG in the HTML document
In the HTML document:
<svg ... id="Layer_1">
<ellipse .../>
<path .../>
</svg>
In your stylesheet:
/*Center the SVG element*/
/*Option 1: have the element with an specific width so you can
use margin:0 auto;*/
#Layer_1 {
width: 500px;
margin: 0 auto;
}
/*Option 2: move the element anywhere with absolute positioning.
Note: Remember it will be relative to the parent element as long as
your parent element has position:relative set, else it will take
the body as a base for positioning*/
#Layer_1 {
position: absolute;
top: 50%;
left: 50%;
}
See the complete code: http://jsfiddle.net/Sg2Z5/
Example with method 2: load the SVG as an object
In your SVG file import the external stylesheet as an XML stylesheet (remember SVG is XML based):
<?xml-stylesheet type="text/css" href="stylesheet.css" ?>
<svg xmlns="http://www.w3.org/2000/svg">
In your HTML, load the SVG as an XML object:
<object type="image/svg+xml" data="YOUR-SVG-FILE.svg">
<!-- Put your fallback here -->
</object>
References and recommended readings
I recommend to read these articles as they explain all of this with more detail
Using SVG http://css-tricks.com/using-svg/
SVG styling http://blogs.adobe.com/webplatform/2013/01/08/svg-styling/
How to Style Scalable Vector Graphics Using CSS http://www.sitepoint.com/svg-styling-with-css/
Related
I see that you can reference the svg by id in some css/svg properties, as in:
<!-- the logo svg -->
<svg id="rect-container" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- left squares -->
<rect fill="url(#rect-fill)"/>
</svg>
does anyone know if we can use a svg from the page, in a css bg for example? to avoid encoding it on the css.
Something like this, which I already tried but did not seem to work the same way.
.myel {
background-image: url(#rect-svg-image);
}
First, there is a misconception to clear up.
fill: url(#source);
does not reference arbitrary SVG content, but a paint server, namely a gradient or pattern. Other uses of the CSS url() notation in SVG include the clip-path, mask and marker-start|mid|end properties that all also can only reference specific elements.
Currently, background-image needs an actual self-contained image resource or a CSS gradient. Referencing a SVG paint server with url() does not work.
But the CSS Images Module Level 4 also defines a element() functional notation that can reference fragments inside the page.
If you look at the text of the specification, there are still a lot of open questions listed to solve before this can become mainstream. There currently is only a Firefox implementation with vendor prefix, -moz-element(). You can point it to paint servers; that means you can (mis)use a <pattern> element. Although experimenting, I found there are some tradeoffs to make:
patternContentUnits="objectBoundingBox" needs all content drawn into a 1px*1px square, but makes the content scalable. Preserving the aspect ratio is not supported.
patternContentUnits="userSpaceOnUse" gives you preservation of the aspect ratio, but scaling is not supported.
svg {
display: block;
width: 0;
height: 0;
}
div {
width: 200px;
height: 150px;
border: 1px solid black;
background-image: -moz-element(#image);
background-size: cover;
}
<svg>
<pattern patternContentUnits="objectBoundingBox"
preserveAspectRatio="xMidYMid meet"
width="100%" height="100%" id="image">
<rect width=".5" height=".5" fill="red"/>
<rect width=".5" height=".5" x=".5" fill="yellow"/>
<rect width=".5" height=".5" y=".5" fill="green"/>
<rect width=".5" height=".5" x=".5" y=".5" fill="blue"/>
<circle r=".5" cx=".5" cy=".5" fill="white" opacity=".5"/>
</pattern>
</svg>
<div>
I know external svg files can be linked to background images:
background-image: url(Icon.svg);
and symbols id's can be targeted from an external svg file:
background-image: url(Icons.svg#Icon-Menu);
but how can I set a background image to an inline svg symbol? (As below)
My svg is at the top of my web page body and not in an external file.
I want .test background image to be the #Icon-Menu symbol.
.test{
background:#ddd url('../#Icon-Menu');
height:100px;
width:100px;
display:block;
}
<div style="height: 0; width: 0; position: absolute; visibility: hidden;">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="Icon-Menu" viewBox="0 0 512 512">
<title>Menu</title>
<path d="M93.417,5.333H6.583c-1.654,0-3,1.346-3,3v13.334c0,1.654,1.346,3,3,3h86.833c1.654,0,3-1.346,3-3V8.333 C96.417,6.679,95.071,5.333,93.417,5.333z" />
<path d="M93.417,40.333H6.583c-1.654,0-3,1.346-3,3v13.334c0,1.654,1.346,3,3,3h86.833c1.654,0,3-1.346,3-3V43.333 C96.417,41.679,95.071,40.333,93.417,40.333z" />
<path d="M93.417,75.333H6.583c-1.654,0-3,1.346-3,3v13.334c0,1.654,1.346,3,3,3h86.833c1.654,0,3-1.346,3-3V78.333 C96.417,76.679,95.071,75.333,93.417,75.333z" />
</symbol>
</svg>
</div>
<div class="test"></div>
#Robert Longson
thats right. But you can do it this way.
But symbol is not the way it will work. Unfortunatly you have to use "g" or something like that to reference.
body {
background: url(http://www.broken-links.com/tests/images/faces.svg#devil-view);
}
http://codepen.io/Type-Style/pen/ByvKJq
It will not work if the svg is in the Markup.
An image must be a complete file.
From the SVG specification...
The ‘image’ element indicates that the contents of a complete file are to be rendered...
The same is true for background-image etc.
(1) one possible way with inline SVG would be to use symbols and DIV absolute layering:
<a class="preview-modal__device-icon-link" ng-click="setPreviewWidth('phone')">
<svg class="preview-modal__device-icon"><use xlink:href="#icon-phone">
</use></svg>
</a>
(2) Second solution would be to use a Data URI:
there is a good info here: https://css-tricks.com/using-svg/
using this tool: Mobilefish.com online conversion tool
CSS:
.logo {
background: url("data:image/svg+xml;base64,[data]");
}
HTML:
<img src="data:image/svg+xml;base64,[data]">
Background
I have an SVG data URL as a background-image property of an HTML element inside a <foreignObject> inside an SVG data URL which serves as the source of an <img> element.
Problem
In Google Chrome, that inner SVG is not rendered at all; while if this whole business wasn't inside an image, it would have rendered. How can I solve this?
Wait, what? Why?
A why will be below, but first I want to complete the question by adding a tree structure and a code sample, to clarify the above convoluted paragraph.
Tree:
<img src="data:image/svg+xml;utf8, (exhibit A)
<svg> (exhibit B)
<foreignObject>
<html>
<div style="background: url('data:image/svg+xml;utf8,
<svg> (exhibit C)
Exhibit C is not rendered at all, as if it's not there. If I cut exhibit A out, though, so that exhibit B is the top-level element, then exhibit C is rendered fine.
Small code sample:
<div>Standalone:</div>
<svg xmlns="http://www.w3.org/2000/svg" width="75" height="50" style="position:relative"><circle cx="25" cy="25" r="25" fill="red" /><foreignObject style="width: 100%; height: 100%"><html xmlns="http://www.w3.org/1999/xhtml"><style>.x {position: absolute;background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='50'><circle cx='50' cy='25' r='25' fill='blue'/></svg>"); width: 100%; height: 100%;}</style><div class="x"></div></html></foreignObject></svg>
<div>As image source:</div>
<img style="position:relative" src='data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="75" height="50" style="position:relative"><circle cx="25" cy="25" r="25" fill="red" /><foreignObject style="width: 100%; height: 100%"><html xmlns="http://www.w3.org/1999/xhtml"><style>.x {position: absolute;background: url("data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="50"><circle cx="50" cy="25" r="25" fill="blue"/></svg>"); width: 100%; height: 100%;}</style><div class="x"></div></html></foreignObject></svg>'>
One final note: using a PNG data URL instead of an SVG data URL works well; it's when using SVG when this becomes broken.
Why?
Placing HTML inside an <img> allows that HTML to be rendered on a canvas by context.drawImage - and I follow that up by canvas.toDataURL in order to generate an image from the HTML, which is my ultimate goal. This is a terrible though standard approach, also employed by widely-used libraries such as https://github.com/tsayen/dom-to-image.
My HTML comes with its own embedded SVG, though, which creates the problem mentioned in the question. Until now I bypassed this by first repeating this flow for the innermost SVG data URLs, replacing them with PNG data URLs, and only then rendering the top-level HTML element. But now I want to add scaling to the mix, which greatly complicates things, since those PNGs won't scale smoothly and I can't scale first because then the images will be too big for their elements.
(well it works okay with background-image which scales, but not with clip-path which doesn't scale and I'm also converting).
Other browsers
IE and Edge do not support HTML inside <foreignObject>, so this is irrelevant for them.
Firefox does support it but for some reason its "standalone" version doesn't work either - which I would also like to solve but it might belong in a separate question.
Related but not duplicates:
Append foreignObject containing some HTML inside an SVG element - is about a missing namespace declaration.
img Inside a foreignObject Inside an svg Inside an img - is about external images, not data URLs.
You need to encode special characters, I don't know exactly which one was the culprit, but when using encodeURIComponent on the whole <CSSImage url>, then encoding again the whole markup to pass it in the <img>, everything works fine in Chrome.
<div>Standalone:</div>
<svg xmlns="http://www.w3.org/2000/svg" width="75" height="50" style="position:relative"><circle cx="25" cy="25" r="25" fill="red" /><foreignObject style="width: 100%; height: 100%"><html xmlns="http://www.w3.org/1999/xhtml"><style>.x {position: absolute;background: url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20width%3D'100'%20height%3D'50'%3E%3Ccircle%20cx%3D'50'%20cy%3D'25'%20r%3D'25'%20fill%3D'blue'%2F%3E%3C%2Fsvg%3E"); width: 100%; height: 100%;}</style><div class="x"></div></html></foreignObject></svg>
<div>As image source:</div>
<img style="position:relative" src="data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2275%22%20height%3D%2250%22%20style%3D%22position%3Arelative%22%3E%3Ccircle%20cx%3D%2225%22%20cy%3D%2225%22%20r%3D%2225%22%20fill%3D%22red%22%20%2F%3E%3CforeignObject%20style%3D%22width%3A%20100%25%3B%20height%3A%20100%25%22%3E%3Chtml%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxhtml%22%3E%3Cstyle%3E.x%20%7Bposition%3A%20absolute%3Bbackground%3A%20url(%22data%3Aimage%2Fsvg%2Bxml%3Butf8%2C%253Csvg%2520xmlns%253D'http%253A%252F%252Fwww.w3.org%252F2000%252Fsvg'%2520width%253D'100'%2520height%253D'50'%253E%253Ccircle%2520cx%253D'50'%2520cy%253D'25'%2520r%253D'25'%2520fill%253D'blue'%252F%253E%253C%252Fsvg%253E%22)%3B%20width%3A%20100%25%3B%20height%3A%20100%25%3B%7D%3C%2Fstyle%3E%3Cdiv%20class%3D%22x%22%3E%3C%2Fdiv%3E%3C%2Fhtml%3E%3C%2FforeignObject%3E%3C%2Fsvg%3E">
Also note that <foreingObject>'s width and height attributes are mandatory in SVG1.1, and thus, omitting them will work only in Chrome.
So for other browsers that still have to implement this new feature
<div>Standalone:</div>
<svg xmlns="http://www.w3.org/2000/svg" width="75" height="50" style="position:relative"><circle cx="25" cy="25" r="25" fill="red" /><foreignObject width="100%" height="100%"><html xmlns="http://www.w3.org/1999/xhtml"><style>.x {position: absolute;background: url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20width%3D'100'%20height%3D'50'%3E%3Ccircle%20cx%3D'50'%20cy%3D'25'%20r%3D'25'%20fill%3D'blue'%2F%3E%3C%2Fsvg%3E"); width: 100%; height: 100%;}</style><div class="x"></div></html></foreignObject></svg>
<div>As image source:</div>
<img style="position:relative" src="data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2275%22%20height%3D%2250%22%20style%3D%22position%3Arelative%22%3E%3Ccircle%20cx%3D%2225%22%20cy%3D%2225%22%20r%3D%2225%22%20fill%3D%22red%22%20%2F%3E%3CforeignObject%20width%3D%22100%%22%20height%3D%22100%%22%3E%3Chtml%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxhtml%22%3E%3Cstyle%3E.x%20%7Bposition%3A%20absolute%3Bbackground%3A%20url(%22data%3Aimage%2Fsvg%2Bxml%3Butf8%2C%253Csvg%2520xmlns%253D'http%253A%252F%252Fwww.w3.org%252F2000%252Fsvg'%2520width%253D'100'%2520height%253D'50'%253E%253Ccircle%2520cx%253D'50'%2520cy%253D'25'%2520r%253D'25'%2520fill%253D'blue'%252F%253E%253C%252Fsvg%253E%22)%3B%20width%3A%20100%25%3B%20height%3A%20100%25%3B%7D%3C%2Fstyle%3E%3Cdiv%20class%3D%22x%22%3E%3C%2Fdiv%3E%3C%2Fhtml%3E%3C%2FforeignObject%3E%3C%2Fsvg%3E">
I know external svg files can be linked to background images:
background-image: url(Icon.svg);
and symbols id's can be targeted from an external svg file:
background-image: url(Icons.svg#Icon-Menu);
but how can I set a background image to an inline svg symbol? (As below)
My svg is at the top of my web page body and not in an external file.
I want .test background image to be the #Icon-Menu symbol.
.test{
background:#ddd url('../#Icon-Menu');
height:100px;
width:100px;
display:block;
}
<div style="height: 0; width: 0; position: absolute; visibility: hidden;">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="Icon-Menu" viewBox="0 0 512 512">
<title>Menu</title>
<path d="M93.417,5.333H6.583c-1.654,0-3,1.346-3,3v13.334c0,1.654,1.346,3,3,3h86.833c1.654,0,3-1.346,3-3V8.333 C96.417,6.679,95.071,5.333,93.417,5.333z" />
<path d="M93.417,40.333H6.583c-1.654,0-3,1.346-3,3v13.334c0,1.654,1.346,3,3,3h86.833c1.654,0,3-1.346,3-3V43.333 C96.417,41.679,95.071,40.333,93.417,40.333z" />
<path d="M93.417,75.333H6.583c-1.654,0-3,1.346-3,3v13.334c0,1.654,1.346,3,3,3h86.833c1.654,0,3-1.346,3-3V78.333 C96.417,76.679,95.071,75.333,93.417,75.333z" />
</symbol>
</svg>
</div>
<div class="test"></div>
#Robert Longson
thats right. But you can do it this way.
But symbol is not the way it will work. Unfortunatly you have to use "g" or something like that to reference.
body {
background: url(http://www.broken-links.com/tests/images/faces.svg#devil-view);
}
http://codepen.io/Type-Style/pen/ByvKJq
It will not work if the svg is in the Markup.
An image must be a complete file.
From the SVG specification...
The ‘image’ element indicates that the contents of a complete file are to be rendered...
The same is true for background-image etc.
(1) one possible way with inline SVG would be to use symbols and DIV absolute layering:
<a class="preview-modal__device-icon-link" ng-click="setPreviewWidth('phone')">
<svg class="preview-modal__device-icon"><use xlink:href="#icon-phone">
</use></svg>
</a>
(2) Second solution would be to use a Data URI:
there is a good info here: https://css-tricks.com/using-svg/
using this tool: Mobilefish.com online conversion tool
CSS:
.logo {
background: url("data:image/svg+xml;base64,[data]");
}
HTML:
<img src="data:image/svg+xml;base64,[data]">
I have ImageMagick 6.8.5-6 up and running on MediaWiki 1.20.2 (Running on Server 2008 R2, IIS 7.5). It's doing it's thing and appears to be functioning perfectly. I'm trying to figure out how I can pass parameters to the SVG, either in wikicode or using the html tag to wrap the svg in an object tag.
Here is the SVG I'm using. (created on http://svg-edit.googlecode.com/) This is just a simple arrow or tag I'm going to use to point at stuff and label stuff.
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 200 100" width="100%" height="100%">
<path stroke="#000000" id="Arrow" d="m2.749992,2.750002l106.118515,0l88.431496,47.250097l-88.431496,47.249901l-106.118515,0l0,-94.499998z" stroke-width="3"/>
</svg>
I need to figure out how to pass the width, height, and fill parameters, so I can set the size and color of the tag.
Wikicode doesn't work from what I've tried, so I've enabled raw html and I'm calling it like this.
<html>
<object type="image/svg+xml" data="/wiki/images/3/32/Arrow.svg">
</object>
</html>
How I get those parameters from a wiki page into that svg I have no idea?
Edit:
Desktops in my environment are running IE8, which doesn't support SVG. I just have to figure out how to tell ImageMagick to 'fill' the svg with a given color before it generates the png thumbnail.
You can't pass parameters into SVG, but you can manipulate it with Javascript. If you just want to position it, you can just position the svg element in the right place just as if it was an image.
<html>
<head>
<script>
function pointAtMe(e) {
var svg = document.getElementById("arrow");
svg.style.display = "block";
svg.style.position = "absolute";
svg.style.top = (e.target.offsetTop - 40) + "px";
svg.style.left = (e.target.offsetLeft - 110) + "px";
}
</script>
<style>
OBJECT { position: absolute; display: none } /* hide initially */
BUTTON { display: block; margin: 100 auto }
</style>
</head>
<body>
<object id="arrow" width="100px" height="100px">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 200 100" width="100%" height="100%">
<path stroke="#000000" id="Arrow" d="m2.749992,2.750002l106.118515,0l88.431496,47.250097l-88.431496,47.249901l-106.118515,0l0,-94.499998z" stroke-width="3"/>
</svg>
</object>
<div>
<button onclick="pointAtMe(event)">Button 1</button>
<button onclick="pointAtMe(event)">Button 2</button>
</div>
</body>
</html>
Note that we have to wrap it in an object element because svg elements cannot be styled.
If you want to be more clever, such as altering the contents of the SVG dynamically, you can also do that with JS.