SVG: Mask not working as expected - svg

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

Related

SVG getting distorted in IE

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.

Redundant <path> element inside an svg file

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.

Where can I find (or make) Material Design Icon set for dense layouts (20dp, desktop)

Google Material Design guidance says:
On desktop, when the mouse and keyboard are the primary input methods, measurements may be scaled down to 20dp.
Moreover, I see that new Gmail uses 20dp-sized icons(screenshot was taken on non-high DPI display):
At the same time, I cannot find MD icons of this size anywhere. Google MD icons only offers 18dp, 24dp and bigger. Same thing in the repository. But I need exactly the size of 20dp.
I tried to use icomoon.io to change grid to 20px and tried to use icon font with the size of 20px. Both methods produce blurry icons, of course.
Where can I find them?Or, how can I up/downscale existing MD icons?
UPDATE:
This is the original icon from Gmail (20px):
https://www.gstatic.com/images/icons/material/system/1x/archive_black_20dp.png
And this is SVG, with the 24px and the desired 20px size.
On my non-high DPI screen this 20px SVG is blurry.
<svg width='24' height='24' viewBox='0 0 24 24'><title>account balance</title>
<g id="g">
<path d='M0 0h24v24H0z' fill='none'></path>
<path d='M20.54 5.23l-1.39-1.68C18.88 3.21 18.47 3 18 3H6c-.47 0-.88.21-1.16.55L3.46 5.23C3.17 5.57 3 6.02 3 6.5V19c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V6.5c0-.48-.17-.93-.46-1.27zM12 17.5L6.5 12H10v-2h4v2h3.5L12 17.5zM5.12 5l.81-1h12l.94 1H5.12z'></path>
</g>
</svg>
<svg width='20' height='20' viewBox='0 0 24 24'><title>account balance</title>
<use xlink:href="#g" />
</svg>
You can use the SVG attribute - shape-rendering =" crispEdges " to disable browser anti-aliasing.
https://developer.mozilla.org/ru/docs/Web/SVG/Attribute/shape-rendering
crispEdges
Indicates that the user agent shall attempt to emphasize the contrast
between clean edges of artwork over rendering speed and geometric
precision. To achieve crisp edges, the user agent might turn off
anti-aliasing for all lines and curves or possibly just for straight
lines which are close to vertical or horizontal. Also, the user agent
might adjust line positions and line widths to align edges with device
pixels.
<svg width='24' height='24' viewBox='0 0 24 24'><title>account balance</title>
<g id="g" shape-rendering="crispEdges">
<path d='M0 0h24v24H0z' fill='none'></path>
<path d='M20.54 5.23l-1.39-1.68C18.88 3.21 18.47 3 18 3H6c-.47 0-.88.21-1.16.55L3.46 5.23C3.17 5.57 3 6.02 3 6.5V19c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V6.5c0-.48-.17-.93-.46-1.27zM12 17.5L6.5 12H10v-2h4v2h3.5L12 17.5zM5.12 5l.81-1h12l.94 1H5.12z'></path>
</g>
</svg>
<svg width='20' height='20' viewBox='0 0 24 24'><title>account balance</title>
<use xlink:href="#g" />
</svg>
An .svg element can take whatever size you want.
svg{border:1px solid;}
<svg width='15' height='15' viewBox='0 0 24 24'><title>account balance</title>
<use xlink:href="#g" />
</svg>
<svg width='24' height='24' viewBox='0 0 24 24'><title>account balance</title>
<g id="g">
<path d='M0 0h24v24h-24z' fill='none'></path>
<path d='M4 10v7h3v-7h-3zm6 0v7h3v-7h-3zm-8 12h19v-3h-19v3zm14-12v7h3v-7h-3zm-4.5-9l-9.5 5v2h19v-2l-9.5-5z'></path>
</g>
</svg>
<svg width='48' height='48' viewBox='0 0 24 24'><title>account balance</title>
<use xlink:href="#g" />
</svg>
<svg width='60' height='60' viewBox='0 0 24 24'><title>account balance</title>
<use xlink:href="#g" />
</svg>
UPDATE
This is an answer for the OP updated question:
I've made some changes in your code and now you have a 20/20 px svg:
Your icon has a lot of white space around the image. I've removed that space.
<svg width='20' height='20' viewBox='3 3 18 18'><title>account balance</title>
<g id="g">
<path d='M0 0h24v24H0z' fill='none'></path>
<path id="B" d='M20.54 5.23l-1.39-1.68C18.88 3.21 18.47 3 18 3H6c-.47 0-.88.21-1.16.55L3.46 5.23C3.17 5.57 3 6.02 3 6.5V19c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V6.5c0-.48-.17-.93-.46-1.27zM12 17.5L6.5 12H10v-2h4v2h3.5L12 17.5zM5.12 5l.81-1h12l.94 1H5.12z'></path>
</g>
</svg>

How can I make my embedded svg image stetch to fill a container?

I have an embedded svg that is will only stretch to about 2/3 of it's container size. I would like to get it to fill the entire container.
Here's how it currently looks:
I have a plunker here showing the embedded svg: http://plnkr.co/edit/5PbBmhV6aBiAtanXTVgM
The simplified svg structure is like this:
<svg id="approach_shot" viewBox="0 0 360 360" preserveAspectRatio="xMinYMin meet" class="content">
<rect fill="#FFFFFF" stroke="#000000" stroke-width="0.5" width="360" height="360"></rect>
<g id="green">
<defs>
<circle id="ball" r="6" stroke="#000000" fill="#FFFFFF" stroke-width="0.5"></circle>
</defs>
<g>
<path fill="#005C1F" stroke="#005C1F" stroke-width="0.75" stroke-miterlimit="10" d="M42.09 171.26c-10.48-25.3-9.77-52.43-0.17-75.92l-18.48-7.65c-11.56 28.22-12.42 60.83 0.17 91.23 0.08 0.2 0.17 0.4 0.25 0.6l18.48-7.65C42.26 171.65 42.17 171.46 42.09 171.26z"/>
more paths...
</g>
<g id="shots">
<use xlink:href="#ball" transform="translate(150,150) scale(1.0)" />
</g>
</g>
</svg>
I've been hacking on this for a few hours, and nothing I do impacts that green image. The outer rectangle fills the container just fine.
Thanks for your help!
The simplest way is to fix your viewBox attribute. You currently have it set to a width and height of 360, when your circle is only about 247 in diameter.
The top-left of the circle is at roughly (11, 9.5), so changing your viewBox to:
viewBox="11 9.5 247 247"
will cause it to fill your viewport.
How did I determine the dimensions of the circle? I used a little bit of javascript and called the getBBox() function on the element with id="green".
var b = document.getElementById("green").getBBox();
alert(b.x+" "+b.y+" "+b.width+" "+b.height);
Demo here

Fill polygon with pattern doesn't work with leaflet

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)');

Resources