I am trying to embed an svg into a web page. It works fine in Chrome and Firefox but gets completely distorted in IE. Please use the below svg block of code as reference:
<svg width="33" height="33" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<path d="M21 17.625h-3.375c-.619 0-1.125.506-1.125 1.125v3.375c0 .619.506 1.125 1.125 1.125H21c.619 0 1.125-.506 1.125-1.125V18.75c0-.619-.506-1.125-1.125-1.125zm0-11.25V7.5h-9V6.375c0-.619-.506-1.125-1.125-1.125S9.75 5.756 9.75 6.375V7.5H8.625a2.24 2.24 0 00-2.239 2.25L6.375 25.5a2.25 2.25 0 002.25 2.25h15.75a2.257 2.257 0 002.25-2.25V9.75a2.257 2.257 0 00-2.25-2.25H23.25V6.375c0-.619-.506-1.125-1.125-1.125S21 5.756 21 6.375zM23.25 25.5H9.75a1.128 1.128 0 01-1.125-1.125v-11.25h15.75v11.25c0 .619-.506 1.125-1.125 1.125z" id="a"/>
</defs>
<g fill="none" fill-rule="evenodd">
<path fill="#FFF" d="M-134-821h1400V297H-134z"/>
<path fill="#FFF" d="M-134-821h1400V204H-134z"/>
<path fill="#FFF" d="M-134-821h1400V204H-134z"/>
<circle fill="#269F96" cx="16.5" cy="16.5" r="16.5"/>
<use fill="#FFF" fill-rule="nonzero" xlink:href="#a"/>
</g>
</svg>
So some browsers have a hard time with the <use>, <mask> and <def> tags.
To fix this you can sometimes "flatten" your image in the graphics editor. Remove any folders containing layers, etc etc.
You can also fix this manually. It is not hard and doing it once helps you learn SVG syntax:
Start by looking at the id referenced in the href attribute <use ... xlink:href="#a">. As you can see it is a
Now we look for the tag with id="a" In this case it is the path inside the <def> tag. This is kind of expected as the def means "define for later use".
Remove the <def> tags but keep that <path id="a" ...> and all its guts.
Move the all the attributes (except the xlink:href="#a") in the <use> tag (fill and fill-rule ) to the path#id="a" element.
Remove the <use> tag.
place all <path> tags inside the one <g> tag
In this case the other fill tags are pointless (artifacts maybe from the editor). They are just white squares so you can ditch those.
I put the circle first since this renders in order top renders on bottom. So visually the bottom layer should be a circle top layer is some drawing in white.
End result should be something like this:
No def or use tags.
All shapes inside a root g tag
Removed pointless shapes.
.
<svg width="33" height="33" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g fill="none" fill-rule="evenodd">
<circle fill="#269F96" cx="16.5" cy="16.5" r="16.5"/>
<path fill="#FFF" fill-rule="nonzero" d="M21 17.625h-3.375c-.619 0-1.125.506-1.125 1.125v3.375c0 .619.506 1.125 1.125 1.125H21c.619 0 1.125-.506 1.125-1.125V18.75c0-.619-.506-1.125-1.125-1.125zm0-11.25V7.5h-9V6.375c0-.619-.506-1.125-1.125-1.125S9.75 5.756 9.75 6.375V7.5H8.625a2.24 2.24 0 00-2.239 2.25L6.375 25.5a2.25 2.25 0 002.25 2.25h15.75a2.257 2.257 0 002.25-2.25V9.75a2.257 2.257 0 00-2.25-2.25H23.25V6.375c0-.619-.506-1.125-1.125-1.125S21 5.756 21 6.375zM23.25 25.5H9.75a1.128 1.128 0 01-1.125-1.125v-11.25h15.75v11.25c0 .619-.506 1.125-1.125 1.125z"/>
</g>
</svg>
I don't have enough reputation points to answer #cloned question in the comments. One annoying thing I have found out about IE11 is that not all versions of IE11 will break the same. The versions among Win7, Win8, Win8.1, and Win10 actually intemperate code differently.
Related
I want to manually create an svg of a directory tree, and thought it would be nice to do it in a way that makes it easy to add, move or delete elements from that tree (without having to repeat myself too much).
While skimming through the svg specification i noticed the <use> element, which allows to "include" other elements with the option to override some of the attributes. So what i would like to do is define the symbol for a folder (or file), including the corresponding label, and then set the actual text of the label via <use>.
Essentially something like this (which doesn't work of course):
<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<symbol id="folder">
<g width="24" height="24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z" />
</g>
<text x="28" y="12" dominant-baseline="middle">my_text</text>
</symbol>
</defs>
<g>
<use href="#folder" my_text="root"/>
<g transform="translate(24)">
<use y="24" href="#folder" my_text="foo"/>
<g transform="translate(24)">
<use y="48" href="#folder" my_text="bar"/>
</g>
<use y="72" href="#folder" my_text="hello"/>
<use y="96" href="#folder" my_text="world"/>
</g>
</g>
</svg>
So, is there any way to use the value of an attribute as the actual text of a <text> element?
PS: Please note that this svg file is not supposed to be part of a web page, but should be rendered correctly when i open it in another application (like inkscape, or any other svg editor/viewer) or generate a pdf from an Asciidoc document.
Thw following two SVG markups render identically:
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path style={inputAdornmentIcon} d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/>
<path d="M0 0h24v24H0z" fill="none"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path style={inputAdornmentIcon} d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/>
</svg>
Any idea what the second path element (<path d="M0 0h24v24H0z" fill="none"/>) in the first version actually does?
The extra path in your code is a a rectangle that covers all the svg canvas. As I've commented Google's icons are always using an extra rectangle like this for a background, but the rectangle is coming first. It's always a good idea to remove redundant elements and to simplify the markup.
I have this rather basic SVG with a vertical line going through 4 circles. The mask that I have for the vertical line has the same definition as the line itself, the only difference being the stroke color (#fff in this case) because I want to be able to see through the mask. But, for unknown reasons, the mask still acts as if the color is black, thus hiding the element. If anyone knows why it's behaving like this, please let me know.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400">
<defs>
<mask id="education">
<path class="through" fill="none" stroke="#fff" stroke-width="2" stroke-miterlimit="10" d="M200 325.6v42.5M200 325.6V44.2"/>
</mask>
</defs>
<path class="arrow" fill="#C57773" d="M191.9 41.5l8.1-14 8.1 14"/>
<path style="mask: url(#education);" class="through" fill="none" stroke="#58595B" stroke-width="2" stroke-miterlimit="10" d="M200 325.6v42.5M200 325.6V44.2"/>
<path class="circle2" fill="#C95147" d="M200 234.7c-4.6 0-8.3 3.7-8.3 8.3s3.7 8.3 8.3 8.3c4.6 0 8.3-3.7 8.3-8.3s-3.7-8.3-8.3-8.3z"/>
<path class="circle1" fill="#C95147" d="M200 317.2c-4.6 0-8.3 3.7-8.3 8.3s3.7 8.3 8.3 8.3c4.6 0 8.3-3.7 8.3-8.3s-3.7-8.3-8.3-8.3z"/>
<path class="circle3" fill="#C95147" d="M200 152c-4.6 0-8.3 3.7-8.3 8.3 0 4.6 3.7 8.3 8.3 8.3 4.6 0 8.3-3.7 8.3-8.3 0-4.5-3.7-8.3-8.3-8.3z"/>
<path class="circle4" fill="#C95147" d="M200 67.1c-4.6 0-8.3 3.7-8.3 8.3s3.7 8.3 8.3 8.3c4.6 0 8.3-3.7 8.3-8.3s-3.7-8.3-8.3-8.3z"/>
</svg>
P.S. Just started tinkering around with SVG, but this (the element dissapearing) happens no matter what shape I define in the mask or what color I give that shape.
SVG is not like CSS, it doesn't use the stroke-width when calculating dimensions for masks and filters, so you can't mask a shape like a horizontal or vertical line (zero-height/zero-width bounding box) using default mask parameters. Just add "maskUnits="userSpaceOnUse" to your mask element to fix.
<mask id="education" maskUnits="userSpaceOnUse">
(live example at http://codepen.io/RwwL/pen/xbNLJp)
I'm including SVGs in an app using the <symbol> element (see https://css-tricks.com/svg-symbol-good-choice-icons/ for full details as to why), and certain icons — ones that include clip-path — are not rendering when I include their icons in pages with the <use> element.
<svg style="display: none">
<symbol id="icon-pin" viewBox="0 0 24 24" enable-background="new 0 0 24 24">
<path fill="none" stroke="#2F3137" stroke-width="2" stroke-miterlimit="10" d="M12 2C8.3 2 5.3 5 5.3 8.7c0 1.2.3 2.3.9 3.3l5.4 9.9c.1.1.2.2.4.2.1 0 .3-.1.4-.2l5.4-9.9c.5-.9.9-2.1.9-3.3C18.7 5 15.7 2 12 2zm0 0" />
<clipPath id="pin-clip">
<path d="M12 11.2c-1.4 0-2.5-1.1-2.5-2.5s1.1-2.5 2.5-2.5 2.5 1.1 2.5 2.5-1.1 2.5-2.5 2.5zm0 0" />
</clipPath>
<path clip-path="url(#pin-clip)" fill="#2F3137" d="M4.5 1.2h15v15h-15z" />
</symbol>
</svg>
</div>
<h2>Normal inline SVG</h2>
<svg id="inlinePin" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24" enable-background="new 0 0 24 24">
<path fill="none" stroke="#2F3137" stroke-width="2" stroke-miterlimit="10" d="M12 2C8.3 2 5.3 5 5.3 8.7c0 1.2.3 2.3.9 3.3l5.4 9.9c.1.1.2.2.4.2.1 0 .3-.1.4-.2l5.4-9.9c.5-.9.9-2.1.9-3.3C18.7 5 15.7 2 12 2zm0 0" />
<clipPath id="inline-pin-clip">
<path d="M12 11.2c-1.4 0-2.5-1.1-2.5-2.5s1.1-2.5 2.5-2.5 2.5 1.1 2.5 2.5-1.1 2.5-2.5 2.5zm0 0" />
</clipPath>
<path clip-path="url(#inline-pin-clip)" fill="#2F3137" d="M4.5 1.2h15v15h-15z" />
</svg>
<h2>Inline SVG using sprite</h2>
<svg>
<use xlink:href="#icon-pin">
</svg>
Here's how it's rendering:
It's broken in the same way across Chrome/Firefox/Safari, so it seems to most likely just be something I'm not understanding about the way other elements need to be referenced in SVG, especially when a symbol is being pulled in via a use. IE11 is also not rendering correctly, but in a slightly different way (no dot in the middle of the pin, but no solid square box like the others).
The problem is caused by the very first line
<svg style="display: none">
Removing display: none will render your svg referencing the inline sprite just fine.
This does at first seem a bit odd since the spec tells us
The ‘display’ property does not apply to the ‘symbol’ element; thus,
‘symbol’ elements are not directly rendered even if the ‘display’
property is set to a value other than none, and ‘symbol’ elements are
available for referencing even when the ‘display’ property on the
‘symbol’ element or any of its ancestors is set to none.
But reading further down the spec it becomes apparent why setting display: none causes this unexpected rendering:
The ‘display’ property affects direct rendering into offscreen
canvases also [...] Setting display: none on a child of a
‘clipPath’ element will prevent the given child element from
contributing to the clipping path.
Thus, setting display: none globally on the svg inhibits rendering of these offscreen canvases leaving you with the incomplete clip path, although it can still be referenced. Removing the display-attribute from the root svg and setting it directly to the clipPath will demonstrate the same behaviour.
To hide your sprite svg you could go for something like
<svg width="0" height="0">
Update:
IE and Firefox seem to be even a bit more stringent on rendering the offscreen canvases when putting a clipPath inside a symbol. Since symbols itself are never rendered, the contained clipPath will keep missing the offscreen rendering and can therefore not meaningfully be applied to any element. You should put the clipPath right outside the symbol which works well in IE, FF and Chrome.
<svg>
<clipPath id="pin-clip">
<path d="M12 11.2c-1.4 0-2.5-1.1-2.5-2.5s1.1-2.5 2.5-2.5 2.5 1.1 2.5 2.5-1.1 2.5-2.5 2.5zm0 0" />
</clipPath>
<symbol id="icon-pin" viewBox="0 0 24 24" enable-background="new 0 0 24 24">
<path fill="none" stroke="#2F3137" stroke-width="2" stroke-miterlimit="10" d="M12 2C8.3 2 5.3 5 5.3 8.7c0 1.2.3 2.3.9 3.3l5.4 9.9c.1.1.2.2.4.2.1 0 .3-.1.4-.2l5.4-9.9c.5-.9.9-2.1.9-3.3C18.7 5 15.7 2 12 2zm0 0" />
<path clip-path="url(#pin-clip)" fill="#2F3137" d="M4.5 1.2h15v15h-15z" />
</symbol>
</svg>
I try to render a SVG polygon filled with pattern. SVG.path filled with pattern doesn't work. As you can see in this jsfiddle, filled background shows up transparent in Firefox and black in Chrome.
The example is based on leaflet GeoJSON Example and uses the diagonalHatch pattern described by carto.net.
<defs>
<pattern id="diagonalHatch" patternUnits="userSpaceOnUse" x="0" y="0" width="105" height="105">
<g style="fill:none; stroke:black; stroke-width:1">
<path d="M0 90 l15,15"/><path d="M0 75 l30,30"/>
<path d="M0 60 l45,45"/><path d="M0 45 l60,60"/>
<path d="M0 30 l75,75"/><path d="M0 15 l90,90"/>
<path d="M0 0 l105,105"/><path d="M15 0 l90,90"/>
<path d="M30 0 l75,75"/><path d="M45 0 l60,60"/>
<path d="M60 0 l45,45"/><path d="M75 0 l30,30"/>
<path d="M90 0 l15,15"/>
</g>
</pattern>
</defs>
As this jsfiddle shows, copying the SVG polygons below the map, makes it work on Chrome but not on Firefox. Apply a fill pattern adding this style to SVG.path:
style="fill: url(#diagonalHatch)"
I'm really not sure if this is a bug in leaflet or some conflict with SVG implementation on Firefox and Chrome.
I've wrote a leaflet plugin for this, you may try it,
https://github.com/lnaweisu/leaflet-polygon-fillPattern
Maybe you can try setting the path via the shape's attribute as mentioned in this thread: Leaflet polygon with fuzzy outline
// Set filter attribute on the polygon
polygon._path.setAttribute('filter', 'url(#blur)');