I have a really simple loading animation that works perfectly on Firefox and Chrome, but in IE11 it's not showing the SVG figure.
Here is the full example:
JSFiddle sample
SVG:
<svg class="circular-loader" viewBox="25 25 50 50">
<circle class="loader-path" cx="50" cy="50" r="20" fill="none" stroke-width="2" stroke-miterlimit="10"/>
</svg>
The animation, which is a rotation, is working on IE11, but the SVG, which is a circle, is not being displayed.
Any idea?
I just can't figure out what is not being supported by IE11.
Only Microsoft Edge will support SVG CSS Transitions and Animation.. especially stroke-dasharray.
Please see the Microsoft Developer Docs:
https://dev.windows.com/en-us/microsoft-edge/platform/status/csstransitionsanimationsforsvgelements
Allows CSS Transitions and Animations to apply to SVG elements.
Unprefixed version: Microsoft Edge build 10240+
As you can see in my fork of your example. You were not seeing the loader spin due to not having the stroke attribute on your circle element.
https://jsfiddle.net/z8w4vuau/50/
You can see how it can spin now. But you will have to check if the browser is IE and adjust your stroke-dasharray so it is larger dash. Since IE11 and below do not support animating SVG stroke-dasharray and stroke-dashoffset with CSS animation or transitions, unless it is Microsoft Edge build 10240+.
But if you need a cross browser solution to animate SVG, especially stroke-dasharray and stroke-dashoffset, then look into using a JS animation library like the GreenSock Animation Platform (GSAP). Using the DrawSVGPlugin
https://greensock.com/drawSVG
IE does not support CSS animation of SVG elements. It also doesn't support the standard built-in SMIL animations that SVG has.
If you convert your animation to native SVG animations, you could perhaps get it working using the FakeSmile library. Otherwise you will need to use some alternative fallback for IE - such as an animated gif or something.
IE11 supports CSS3 animations but not on child nodes of an SVG element. You can animate the SVG node itself so my solution is to break up the parts into separate SVGs and animate those with CSS3.
https://codepen.io/getsetbro/full/Bxeyaw/
This will even work if IE11 is in compatibility mode if you add the meta tag
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
For anyone having trouble with this, I have a workaround.
I had a full SVG with IDs and CSS animations, all working perfect for all the other major browsers.
I have my SVG inserted into the HTML, so I can access every item with CSS animations.
For this to work, you have to have your SVG with position:
absolute; top: 0px; left: 0px,
... inside a container .svgcontent (or whatever you want to call it)
Script:
var IE = (navigator.userAgent.indexOf("Edge") > -1 || navigator.userAgent.indexOf("Trident/7.0") > -1) ? true : false;
objs = [ '#file1', '#file2','#file3','#file4','#file5','#file6','#file7','#file8','#file9','#file10','#file11', '#bottom' ];
if ( IE ){
objs.forEach(function (item) {
item = $(item);
id = item.attr('id');
svgcontent = item.closest('.svgcontent')
svg = item.closest('svg');
svgattrs = ' width='+svg.attr('width')+' height='+svg.attr('height')+' '
html = '<svg id="'+id+'" '+svgattrs+'>'+item.html()+'</svg>';
item.remove();
$(svgcontent).prepend(html);
});
}
This takes all the elements in the objs array, and insert them as a full SVG behind the first one (you can change prepend to append to change this behavior).
And the SVG is going to have the same id as the object, so the CSS animate is going to apply to a full SVG, not an SVG object.
And that's it!
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.
As part of a project of mine, I need to dynamically create a canvas and then draw an SVG file (also dynamically generated) in the canvas. For my project I need the canvas to cover the whole page and the SVG to fill the whole canvas. In the interest of browser comparability I set the SVG width and height to the canvas width and height respectively (to deal with this know Firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=700533 as per this answer https://stackoverflow.com/a/28692538) yet the canvas is still blank in Firefox (works fine in Chrome, Safari, and Opera). I was wondering anyone could shed some light on this problem.
I made a fiddle with a demo (not my real SVG file but the same method and the same problem). Just to show the problem is not the the SVG if you copy it out of the alert and paste into a new Firefox tab it renders just fine. My Firefox version is 47.0
This should be the part of the code that is the most important.
img.onload = function () {
ctx.scale(ratio, ratio);
ctx.drawImage(img, 0, 0);
}
svg = "data:image/svg+xml,"+ "<svg xmlns='http://www.w3.org/2000/svg' width='"+canvas.width+"px' height='"+canvas.height+"px' viewBox='0,0,"+canvas.width+","+canvas.height+"' >" +
"<style type='text/css'> * { margin: 0; padding: 0; } p{background-color:blue;}</style>"+
'<rect x="10" y="10" width="100" height="100"/>' +
"</svg>"
img.src = svg
Full fiddle demo of the problem: https://jsfiddle.net/9are9tzx/5/
Thank you!
Your demo is working fine for me in FF. I see a black rectangle.
Did you accidentally use an SVG in your example that works?
If some other of your SVGs don't work, it may be because of a common issue people strike when working with SVG DataURIs in Firefox: the hash/pound symbol (#).
Technically '#' is a reserved character in URLs. It marks a fragment identifier. It appears in SVGs both as a fragment identifier (eg. url(#mygradient) and in colours (#ffcc88).
Chrome and other browsers are more forgiving if there are '#'s in the DataURI, but Firefox isn't. This is not a bug in Firefox. It is behaving correctly.
The solution to this is to escape any '#'s in your SVG the way you would any reserved URL characters - by using percentage encoding. For '#' the encoding is %23.
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 manipulate an external .svg file via CSS.
HTML
<body>
<div class="mysvg">
<img src="decho.svg" alt="decho" width="200px"></img>
</div>
</body>
CSS
div.mysvg img {
opacity: .3;
transition: opacity 1s linear 0s;
}
div.mysvg img:hover {
opacity: 1;
}
This code works for opacity, but not for fill or other svg specific attributes like stroke. I am aware I can't do that with an img tag, but I've been looking for hours and I can't find the correct way to do it with svg or object.
So basically, my questions is, how do I achieve the same result as the code which I linked, but to be able to manipulate fill, stroke etc. properties and it must be an external file, not just an inline svg code pasted in the html.
If someone is able to show me the correct way to do it, I'd be most grateful. Thanks.
EDIT:
I managed to do it by adding a css inside the .svg file itself. It must be right after the svg opening tag.
<svg ...>
<style type="text/css" media="screen">
<![CDATA[
g {
fill: yellow;
stroke: black;
stroke-width: 1;
transition: fill 1s linear 0s;
}
g:hover {
fill: blue;
}
]]>
</style>
<g>
<path ...>
</g>
</svg>
You also need to insert it as an object in the html, otherwise it won't work.
<object data="decho.svg" type="image/svg+xml">
Hopefully this helps to someone looking for an answer like mine in future. This is what helped me http://www.hongkiat.com/blog/scalable-vector-graphic-css-styling/.
This is in my opinion the greatest flaw in svg: sandboxing.
Svg files are sandboxed: in their own document, which is why a typical 'fill:' style will not apply. Likewise, the css you write in your svg will not apply to the rest of your site.
Adding css directly to an svg: Not a good solution as you will end up rewriting the css in every svg you use.
The real solution: An "icon-system". Svg font-face or svg sprites. Read more about them here.
The reason opacity works: Opacity applies to the svg object/frame itself, not the contents of the svg (which are inaccessible).
I should also note that no matter how you load those svg's, inline, by reference, in an object, as a background, you will not be able to get inside the sandbox. This is why converting them to a font or using sprites is necessary for using hover, focus, and other effects/transitions.
This is possible providing the SVG is hosted on the same domain (thanks #FabienSnauwaert) and it does not have a fill colour defined on itself, and you do not contain a parent selector within the CSS. For example:
I have the following files:
icon-sprite.svg (my external sprite of SVGs)
buttons.scss
test.html
icon-sprite.svg
I have omitted the other SVGs for clarity.
<svg xmlns="http://www.w3.org/2000/svg" style="width:0;height:0;visibility:hidden;">
<symbol viewBox="0 0 1500 828" id="icon-arrow-3pt-down">
<title>arrow-3pt-down</title>
<path d="M1500 0H0l738.9 827.7z"/>
</symbol>
</svg>
test.html
<button class="button--large">
Large button
<svg class="svg" width="20px" height="20px">
<use xlink:href="icon-sprite.svg#icon-arrow-3pt-down"></use>
</svg>
</button>
buttons.scss
.svg {
fill: red;
}
This would not work if I was to use body .svg due to shadow DOM boundaries.
See this CSS Tricks article for more info
I recently ran into this. While SVGs are not part of the DOM for some arbitrary reason, you can move them to the DOM with a bit of javascript:
<object type="image/svg+xml" data="illustration.svg"
onload="this.parentNode.replaceChild(this.contentDocument.documentElement, this);">
</object>
This will replace the <object> with an inline after it has loaded. In case javascript is disabled, it falls back to an <object> tag, and the svg will not be themed. In my case, the styling was for a javascript-controlled dark theme, so having the correct fallback means no theming issue.
Other options considered (xlink is a good one for sprites):
Use an external library to load svgs inside the DOM (the above js is simple enough IMO)
use svg filters for chroma-keying. That makes svgs more complex to edit, might use more resources to perform the filtering, and is less flexible.
Note that I am not sure of the security implications, better save this for files you control.
Unfortunately, there's no built-in feature in Web Standards that makes it possible. SVG Symbols is an option but doesn't work with files hosted on CDNs. Additionally, you need to ensure that SVG files are defined properly to make use of <use> tag.
I have created a library, svg-loader, that makes it easier to achieve this. It uses Javascript but it's only 3kb and it's loaded asynchronously, so the impact on performance is negligible. It's plug 'n play, so you don't need to do anything except including the <script> tag.
Here's a Codepen example.
Usually the browser renders the svg images properly but in chrome the browser doesn't detects the css3 scale and return a poor image. This must be because css scale is a new technology... Is there any way to select the render quality?
Sorry for my english, I'm studying it!
There are a couple of workarounds for this, none as easy as setting a render quality directive, I'm afraid. The most straightforward workaround would be inserting the actual SVG instead of using it inside an img tag.
Your html would look like...
<svg>
...
</svg>
And your css would look like...
svg {
-webkit-transform: scale(2);
}
Here is a demo: http://jsfiddle.net/EgsGe/