I'm trying out the SVG stacking technique to enable multiple icons stacked in a single file, requiring only a single HTTP request from the browser. The technique is described pretty thoroughly here.
Basically the idea is that you put multiple SVG elements into a single SVG file, and use CSS styling to hide all icons, except for the icon you currently want to display. You select the icon you currently want to display using the CSS :target selector.
The technique works for me, except stacking multiple icons causes weird distortions in the displayed icon, even though all other icons are hidden.
In the example I'm working with, I simplified this to stacking only two icons: an US flag icon and an UK flag icon.
The (simplified) SVG file is:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="svg153" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="480" width="640" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
<svg:style
xmlns:svg="http://www.w3.org/2000/svg" type="text/css">
.i { display: none; }
.i:target { display: block; }
</svg:style>
<svg:svg id="uk" xmlns:svg="http://www.w3.org/2000/svg" class = "i" height="480" width="640" version="1.1">
<!-- SVG elements to draw UK flag -->
</svg:svg>
<svg:svg id="us" xmlns:svg="http://www.w3.org/2000/svg" class = "i" height="480" width="640" version="1.1">
<!-- SVG elements to draw US flag -->
</svg:svg>
</svg>
Note that the CSS is embedded within the SVG file, in a <svg::style> element. The CSS is simply:
.i { display: none; }
.i:target { display: block; }
This way, any svg::svg element with class="i" is automatically invisible, unless we specifically target it in the SVG url. So this way, to display a US flag icon, I would use the following HTML snippet:
<img
src="flags.svg#us"
width="80"
height="60"
alt="SVG Stacked Image"
/>
And of course, to display the UK flag I would change it to src="flags.svg#uk"
Anyway, all of this works wonderfully... except for a strange image distortion which occurs in both Firefox and Chrome when I stack the images.
Here's a screenshot of the US flag when I remove the (hidden) UK flag from the SVG file:
As you can see, it looks fine.
But when I stack it in front of the UK flag, it looks like:
As you can see, the image becomes strangely distorted - it almost looks like what happens to a low-quality JPEG when you get a lot of "artifacts" in the compressed image.
So why exactly is this happening? The other images stacked with the US flag icon are all invisible, so why should they effect the visible icon at all?
I Googled around a lot looking for answers, and although there are definitely many issues and "gotchas" with the SVG stacking technique, they all relate to cross-browser compatibility. However, the technique works fine on most newer browsers up to and including IE9. Also, the distortion happens in both Firefox and Chrome, so this isn't likely to be some cross-browser issue, but rather something I'm doing wrong.
So, what is causing this weird distortion when I apply the SVG stacking technique?
No idea about stacking and target. But I know two simple methods.. may be those can help you out in an easier way.
When you have chosen different svg icons from net or even from computer but each icon is separate.
There is a website 'icomoon.io', where we can choose different icons from online libraries or your custom svg icons from your computer.
Open 'https://icomoon.io/app/'
Choose 'import icons' to upload custom icons from your computer.
At bottom of the page it has 'Add Icons From Library…' to choose icons from online libraries.
From 'select' tool (At Top) select multiple icons as you like.
After selecting multiple icons choose 'Generate SVG,PNG,PDF' button at bottom.
Then to combine all of them in a single file, click on 'settings icon' located just next to the 'Download' option in first button at bottom left.
Choose 'Include Tiles (CSS Sprite) from it.
Put appropriate margins and number of icons in a row as you like and then download the combine sprite with its xml code in demo.html and css definitions in style.css.
When you have already created single SVG file of multiple icons using 'AI' or any other software.
Just upload(import) that file to icomoon.io and click on 'Generate SVG,PNG,PDF' button and download the sprite xml file.
I tried with my own simple svgs and it works fine, no weird distortion happening. So my guess is it's your svgs for uk and us.
http://pastebin.com/dxVtTQKF
Related
I have been developing a web page "game" on my PC based in HTML, SVG, and Javascript. It has a large image of the earth loaded into the SVG views through the SVG <image> tag. Testing on my PC this works with no problem, however recently I published it to a public web page (http://rbarryyoung.com/EarthOrbitalSimulator.html) and discovered that only the bottom right quarter of the SVG is rendering on both SVG views on my iPhone and iPad. Like this:
At first, I thought that it was just the image in the SVG viewports, but then I realized that the entire SVG viewport was black except for the lower-right quadrant. The SVG viewport is correctly fully sized, it just appears as if there is some black mask over 3/4s of it (or only 1/4 of it renders).
Here's what I think are the relevant HTML code lines, the containing Div tag for the first SVG view (line 67):
<div id="divSvg1"
style="position:relative; z-index:1; margin:15px;
top:100px;
width:640px; height:640px;
background-color:black;
float:left;"
>
The SVG tag (line 104):
<svg id="svgEa"
style="width:100%; height:100%;"
viewBox="-7500 -7500 15000 15000"
preserveAspectRatio="xMidYMid meet"
clip-path="url(#svgEaClip)"
transform="scale(1.0,1.0)"
version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- NOTE: All internal units are in KM (or %) -->
And the embedded Image tag (starting at line 160):
<g id="gEaAll" transform="scale(1.0,1.0)" >
<!-- ... -->
<g id="gEaSurfaceFacingBottom" class="eaSurfaceFacing">
<g id=gEarthImage>
<!-- ... -->
<image x="-6413" y="-6413" width="12826" height="12826" href="eosImages/globe-arctic 8bit.png" />
</g>
</g>
The second SVG view is a shadowed (<use..> tag), zoomed view of the first with the same problem.
I have tested this on my PC, on both screens in Chrome, Edge, and IE, where it works correctly on all of them. I have also tested this on my iPhone with both Safari and Edge and my iPad with Safari, Chrome, and Edge with the same failure on all of them. I have tried just a bare <img> tag of the PNG file outside of SVG and that works fine on these platforms.
I do not have any Android platforms to test with, so if anyone wants to try it and let me know, I can add those results here.
I have researched this, and though there's a bunch of stuff about iOS not rendering images, mostly those are a complete failure to render, rather than this very specific partial rendering, and much less specific stuff about SVG differences. Ultimately I didn't find anything that seemed to be the same problem.
To summarize then, my question is: what is causing this problem or what have I done wrong, and how can I fix it? (I do understand that I will need to have a different style/CSS layout for mobile, but I still need to know what needs to be changed to make this render correctly)
Add X and Y coordinates for your <rect />. In your case, your Clip-Path Rectangle is not in an exact coordinate.
Here is the code working for me
<clipPath>
<rect x="-7500px" y="-7500px" width="100%" height="100%" />
<cliPath>
replace this code with your <clipPath> on line 114 and 301.
Here is the Screenshot
Moreover here is a live demo that worked on my Mac Safari as well in windows Chrome, where I took one part of your code.
Update
Check the answer by #fussionweb.
Orignal answer:
You can try the -webkit- prefix before clip-path. It seems to be a safari issue related to clip-path.
First time posting here, so treat me gently. :)
I have an SVG image on my site which has a transparent background -
<img class="img-responsive center-block" src="images/pritchservices.svg" alt="Pritch Services Logo" />
Works beautifully on my site. However, due to the transparency, when that image loads in google image search results, due to the transparency, looks terrible.
I have an alternative image (using for fb Open Graph crawler) which is here -
Pritch Services Full Logo
In my crazy mind, this is what I had as a plan:
Redo the SVG in Illustrator to include the background color (as per the fb OPen Graph image) - this would then mean the image result in Google would be as expected
Have some CSS within my site to set the background color of the SVG to transparent, so it displays nicely (as it currently does on the site)
I am assuming I can't just put the SVG markup inline, as although this would give me what I wanted on the page, it wouldn't load the image AT ALL on google image search results?
Is this the way to go, if so, any suggestions on how to implement please; or is there an alternative solution I haven't thought of? Or am I just being too picky?!
Thanks in advance everyone...
You can't include an SVG via <img> and style it with CSS in your parent document.
You can't style the contents of an <img>, even if it is an SVG
CSS doesn't apply across document boundaries
You have a few options.
Include the version with a background in your page. And then hide it and replace it with the transparent-background version via CSS.
<div class="logo">
<img src="logo-with-background.svg" ... />
</div>
.logo img {
display: none;
}
.logo {
background-image: url(logo-without-background.svg);
}
Include the background version using <object> then use the DOM to find the background element and hide it.
var object = document.getElementById("myObject");
var svgDoc = myObject.contentDocument;
svgDoc.getElementById("bg").setAttribute("display", "none");
Apply a clipping path to the backgrounded version as #Obink suggests. It would work, but it is not the easiest solution though. And it won't work on older browsers that don't support clip paths.
Problem:
On page load, for a button, SVG which is being called in CSS background appears. On some event, I apply a class and to it call another SVG in CSS background. However that new SVG does not appear. If in debugger, I try to toggle the background, it then starts appearing.
What am I missing to get this working in IE11?
In Below picture, we are using <button> tag. On some event, the background SVG is changed.
CSS Code
.buttonIcons{
.svgicon-fields-add{ background-image:url('../assets/themes/svg/arrow_active.svg');
width: 16px;
height: 16px;
}
On disabled state, below is the CSS
.buttonIcons.disabled{
.svgicon-fields-add{ background-image:url('../assets/themes/svg/arrow_disabled.svg');
width: 16px;
height: 16px;
}
So initially all buttons are disabled, but if you see the first button needs to show active svg image, but it is not appearing. I can see it in IE11 console, and if in console, I toggle the property, it starts appearing.
The code works fine in Chrome
Thanks in advance for all the suggestions.
SVG file code
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="16" 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 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g>
<polygon fill="#00a6a0" points="7.6,1.6 6.7,2.4 12.3,8 6.7,13.6 7.6,14.4 14,8 "/>
<polygon fill="#00a6a0" points="2.6,1.6 1.7,2.4 7.3,8 1.7,13.6 2.6,14.4 9,8 "/>
</g>
</svg>
Based on the small number of views, this is an esoteric case, but I'm having the same problem. I've been on it for days. I also had a double problem where IE would not display the background on toggling the style in developer tools.
I thought it was initially a memory issue, where IE was allocating memory for the icon but not actually putting anything there.
So I applied the SVG as an xml-encoded string directly in the class itself. This solved one instance of an SVG background not appearing, but it didn't solve the problem mentioned here. Furthermore, this allowed me to see the toggle event you mentioned.
So I now believe that it is NOT a memory issue, but an issue with IE10/11's SVG rendering engine. The fact that this problem only happens with certain SVG's reinforces the idea that the IE rendering engine is crapping the bed with certain inputs. It also only happens when a CSS SVG background is being overridden by another class's SVG background.
I thus tried setting the object to display:none, then display:block in the hopes of forcing a re-render of the element. This didn't help. I destroyed the element then rebuilt it and appended it back where it was supposed to go. That didn't work.
To make things even more confusing, I was never able to replicate the problem locally. It would only ever manifest in certain environments, leading me to believe that it is a combination of the browser and some server settings. I have no idea what.
Regardless, the point is that IE is remarkably resilient it not re-rendering what it has rendered. And since the SVG engine is apparently separate from the DOM rendering engine, screwing around with the DOM will have no effect on what the SVG renderer has stored. You have to give it quantifiably different data to force the SVG engine to re-render.
The only solution I found was to have my two CSS classes then give IE different image data than what it found on page load.
.Class1 {
background-image: url("data:image/svg+xml,image-data...");
}
.Class2 {
background-image: url("data:image/svg+xml,image-data...");
}
These classes allow default page load states to be covered. Then when JS events change the appearance, instead of changing the class, assign an in-line CSS style with the XML-ified SVG image data with a slight difference. Anything will work. I used an extra space.
onclick="function(){
element.style.backgroundImage = "url(\"data:image/svg+xml,slightly-different-data...\")"
}
To reiterate, it is an SVG rendering problem that occurs on page load. You can force SVG to re-render the image by giving it slightly different data in-line. I would imagine that you could do the same thing with a third class that contains a reference to a slightly different SVG file from the initial one, but I didn't do this.
Make sure the SVG file has the width and height property.
And if there's a 'responsive' option in it, you should remove it.
The option resets the CSS width and height.
I am trying to do something that 'should' be fairly simple. My program (Java, using SWT) has a button that when clicked, opens up a dialog with a browser component. This component hits one of our web-services using some specialized input, and the html that comes back contains a inline SVG image and some basic html (a table essentially). Some sample of what this looks like is as follows (truncated for ease of reading)
<!DOCTYPE html>
<head>
<style>
table { border-collapse: collapse; width: 100%;}
table, td, th { border: 1px solid black;}
svg { top:0; left:0; width:612px; height:450px; display:block; margin:auto;}
</style>
</head>
<body><h1><b>Sample Heading</b></h1>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 244.8 180" enable-background="new 0 0 244.8 180" xml:space="preserve" preserveAspectRatio="xMinYMin meet">
<!-- A whole lot of SVG commands here. -->
</svg>
<table border="1"><tr><th>Col1</th><th>Col2</th><th>Col3</th><th>Col4</th></tr>
<tr bgcolor="EDFEED"><td align="center">1</td><td>2</td><td>3</td><td>4</td></tr>
</table>
</body>
</html>
NOTE: The CSS line for SVG is there because I was playing with how to auto-adjust the visual display size in the webpage. During the course of my debugging/testing, this has been added/modified/removed multiple times in various forms.
NOTE2: The SVG viewbox size comes from the initial SVG files I'm using. These come from outside of my process.
This works perfectly fine for display in my dialog but where I'm having trouble is I want to allow my user to print the browser contents using a print button at the bottom of the dialog (So what they should get is the Image at the top, ideally scaled to fill a page width while preserve aspect ratio, with the table of supplementary information below it.) If I make a Javascript call from SWT of window.print();, it will print, but two peculiarities tend to occur.
The first is that if I leave that CSS line with the alterations to the SVG, it sometimes ends up writing off the page. I'm fairly sure this has to do with me doing something idiotic with SVG CSS styles that I can't seem to figure out.
The second is that it frequently ends up overwriting the top of the table element. This seems to happen even if I remove the CSS SVG line that is adjusting the image scale/size.
In addition, if I right-click in IE, and choose print-preview, it looks fine at least with the 'not overwriting the top of the table', but when it actually prints, the paper that is produced does not match what preview shows me. This behavior is consistent if I try this from outside my program in a normal IE window.
The HTML is generated dynamically upon the request to the webservice., but if similar HTML is fed into FireFox or Chrome, neither bug occurs (at least in my barebones testing.) Our app will always run on Windows PCs, and SWT uses IE (I'm using version 11 right now) under the hood, which is why I believe I'm running into this problem. I'm not a Web Developer or CSS guru, and I know enough to get myself into trouble, but I'm not sure how to fix this issue at the moment.
Any guidance or others who have dealt with HTML/SVG printing with IE would be appreciated. Thank you.
I'm trying to apply a Gaussian blur to an element which has some child nodes containing some content.
For Chrome I did in the applied style:
-webkit-filter: blur(2px);
Firefox doesn't support this. What firefox does support is applying SVG to elements. Knowing this I searched google for an example where they would explain how to use SVG to apply a gaussian blur to an element. I found this example with this demo.
I brewed up the following CSS:
#div-with-content{
-webkit-filter: blur(2px);
filter: url('#blur');
}
And put this into the corresponding HTML file:
<svg:svg>
<svg:filter id="blur">
<svg:feGaussianBlur stdDeviation="2"/>
</svg:filter>
</svg:svg>
But when I went to test the page I saw that div-with-content wasn't there anymore. It had disappeared. Everytime I remove the blur style from div-with-content it appears again.
Could anyone please help me out on this one, I've really tried everything within my knowledge.
I don't know if it's your apostrophes or your svg: but this version works perfectly in Firefox:
CSS:
#div-with-content{
filter: url("#blur");
}
HTML:
<svg>
<filter id="blur">
<feGaussianBlur stdDeviation="2"/>
</filter>
</svg>
<div id="div-with-content"> WOohooo</div>
If there is only text you would like to blur there is this little trick
p{
color: transparent;
text-shadow: 0 0 4px #222;
}
You can see it here how it works jsFiddle
edit
You can load from an external document, as long as "that document comes from the same origin as the HTML document to which it's applied".
Make sure the html page that has the svg effect is being passed in the URL argument along with the ID of the svg effect (for instance,
So, instead of
url('#filter-effect')
do
filter: url('index.html#filter-effect')
It wasn't obvious to me how this worked until I read #RobertLongon's comment, but it makes sense now. You can put all your SVGs in a single document and reference them from other html files.
-
Old Answer:
Mozilla Developer Network says:
You may specify SVG in styles either within the same document, or within an external style sheet.
...but they're full of it. Bug report?
use <style> instead of <link>
For reasons beyond my comprehension, if you declare the .blur class outside the html document, via <link>, your element will disappear while still occupying space. This is why the fiddles are working in other answers but implementation is not. JSFiddle appends your styles within the document using <style>. To avoid this behavior, you should instead declare the .blur class WITHIN the document, aka <style>...</style>
Also important:
NOTE: Namespacing is not valid in HTML5, leave off the "svg:" in tags for HTML-format documents.
Again, <style>, not <link>.
sources:
trial and error
mdn: Applying SVG effects to HTML content
I saw the same behavior with a filter I was trying to use. It turns out that I had also set the SVG where the filter was defined to display: none;. Once I removed that, the filters were available and the HTML elements they were applied to displayed properly.
This is probably 2 years too late, but Name calling the document didn't do it for me, but placing the style directly on the element like this worked perfectly:
<div class="imageblur" style="filter:url(#blur) ">