ClipPath on SVG within 'use' link in IE - html

I've got a four slice scaling SVG image which works great in all browsers, except when I try and include it via a use tag. Then it works fine in Chrome, Firefox and Safari but not in <=IE11.
The problem seems to be with the clip-path, is there something I'm missing to get this working in IE or is it just not supported? If not, is there a way I can achieve the same effect in an IE friendly way?
Thanks!
#box,
#use {
width: 200px;
height: 50px;
}
#use {
fill: #f00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div style="display: none;">
<svg id="box" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<symbol id="topleft" viewBox="0 0 500 500">
<path d="M3.1,22.6c0,0.2,0,0.4,0,477.4H5C5,22.9,5,22.5,5,22.6c0-4.3,0-7.9,0.1-8.8C5.1,11.5,5,8.2,6.2,6.1
c0.4-0.6,40.8-0.8,80.2-0.9c0.5,0,413.6,0,413.6,0V3.4c0,0-413.3,0-413.6,0C47.5,3.4,8.2,3.6,6.7,4C6.5,3,6.6,2,6.5,1
C6.4,0.3,5.7-0.1,5,0c-0.7,0.1-1,0.8-1,1.4C4.2,2.2,4.2,3,4.2,3.7C3.4,3.9,2.7,4.2,1.9,4.4c-1.5,0.3-1,2.7,0.5,2.4
C2.9,6.6,3.5,6.4,4,6.3C3.5,7.8,3.5,9.7,3.4,11C3.3,12,3.1,19.8,3.1,22.6z"/>
</symbol>
<symbol id="topright" viewBox="0 0 500 500">
<use xlink:href="#topleft"/>
</symbol>
<symbol id="bottomleft" viewBox="0 0 500 500">
<path d="M5.3,494.5C5,493.1,5,484.3,5,477.4L5,0H3.1l0,477.4c-0.1,7.2,0,15.3,0.4,17.2c-0.8,0.1-1.7,0.1-2.5,0.3
c-0.6,0.2-1.1,0.7-1,1.4c0.1,0.6,0.8,1.1,1.4,1c0.6-0.2,1.3-0.2,1.9-0.2c0,0.2-0.2,1.5-0.3,1.7C3,499.4,3.7,500,4.3,500
c0.7,0,1.2-0.5,1.3-1.1c0-0.1,0.3-2.3,0.3-2.3c1.8,0.4,4.2,0.3,5.3,0.4c0.9,0.1,37.6,0.2,75.2,0.3c0.3,0,413.6,0,413.6,0v-2.1
c0,0-413.3,0-413.6,0C46.8,495.2,6,495,5.3,494.5z"/>
</symbol>
<symbol id="bottomright" viewBox="0 0 500 500">
<use xlink:href="#bottomleft"/>
</symbol>
<clipPath id="crop">
<rect class="mask" width="100%" height="100%" x="0"/>
</clipPath>
</defs>
<svg width="50%" height="50%">
<use xlink:href="#topleft" width="500" height="500" class="box_border__tl"/>
</svg>
<!-- top right: -->
<g transform="scale(-1, 1)">
<svg width="50%" height="50%" x="-100%" y="0">
<use xlink:href="#topright" width="500" height="500" class="box_border__tr"/>
</svg>
</g>
<!-- bottom left: -->
<g transform="scale(1, -1)">
<svg width="50%" height="50%" x="0" y="-100%" clip-path="url(#crop)">
<use xlink:href="#bottomleft" width="500" height="500" y="-500" transform="scale(1, -1)" class="box_border__bl"/>
</svg>
</g>
<!-- bottom right: clip-path="url(#crop)" -->
<g transform="scale(-1, -1)">
<svg width="50%" height="50%" x="-100%" y="-100%" clip-path="url(#crop)">
<use xlink:href="#bottomright" width="500" height="500" y="-500" transform="scale(1, -1)" class="box_border__br"/>
</svg>
</g>
</svg>
</div>
<svg id="use" class="box" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<use xlink:href="#box"/>
</svg>

The issue is happening because I'm hiding the main SVG in a container with display: none; The same also happens if I use visibility: hidden; or position: absolute; on the parent container.
It only works if the main SVG is rendered on the page. It also works if you start with the main item visible, then hide it using javascript.
It's a really obscure issue, and odd how the non-clipped elements render even when the SVG is hidden. Oh, also the main SVG must be placed above the use links otherwise Safari doesn't render it.

Related

SVG Mask not working when rotated in Chrome (but works in Firefox and Safari)

I'm building a painting tool with SVG that has various actions such as painting rectangles and rotating. One of the actions is to add a mask, effectively windowing the content to a specific area. To accomplish this, I'm using the svg mask element. However, when also adding a rotation, it seems that the mask is not working and the elements are rendering weirdly.
This is an example SVG:
`
<svg width="50%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-250 -300 500 600">
<defs>
<mask id="57656">
<rect fill="black" x="-250" y="-300" width="500" height="600"></rect>
<rect fill="white" x="-72" y="-141" width="235" height="287"></rect>
</mask>
</defs>
<g transform="rotate(20)">
<g mask="url(#57656)">
<rect x="0" y="202" width="271" height="118" fill="rgb(128,237,51)" opacity="0.21"></rect>
<rect x="3" y="167" width="313" height="318" fill="rgb(152,28,5)" opacity="0.58"></rect>
<rect x="-65" y="-40" width="317" height="222" fill="rgb(74,103,68)" opacity="0.29"></rect>
</g>
</g>
</svg>
`
how it should look (on firefox and safari)
how it looks on chrome
how it looks on chrome without rotation
What could be causing this? is it a bug? I've also tried style="transform: rotateZ(20)" but that has the same issue.
Apparently, this issue is also related to transparency rendering.
Replacing opacity with fill-opacity applid to masked elements fixed this bug for me.
svg {
width: 20em;
border: 1px solid #ccc
}
<svg width="50%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-250 -300 500 600">
<defs>
<mask id="m57656">
<rect fill="black" x="-250" y="-300" width="500" height="600"></rect>
<rect fill="white" x="-72" y="-141" width="235" height="287"></rect>
</mask>
</defs>
<g transform="rotate(20)">
<g mask="url(#m57656)">
<rect x="0" y="202" width="271" height="118" fill="rgb(128,237,51)" fill-opacity="0.21"></rect>
<rect x="3" y="167" width="313" height="318" fill="rgb(152,28,5)" fill-opacity="0.58"></rect>
<rect x="-65" y="-40" width="317" height="222" fill="rgb(74,103,68)" fill-opacity="0.29"></rect>
</g>
</g>
</svg>

How to draw svg on image?

I have a image, and i have cordinates (x1,y1),(x2,y2),(x3,y3),(x4,y4) to draw a svg/rectagle on image, how to draw?
I have tried using svg tag in img tag, but it does not work, the main thing is how to set width and height of svg(rect svg) using those cordinates.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%" viewBox="0 0 1055 717" preserveAspectRatio="xMinYMin meet" >
<rect x="540" y="134" width="150" height="100" fill="none" stroke="red" stroke-width="2" />
</svg>
If I understand correctly OP then so and look at the comments in the code.
<style>
.container {
width:100vw;
height:100vh;
}
</style>
<div class="container">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 1055 717" preserveAspectRatio="xMinYMin meet" >
<!-- Add image -->
<image xlink:href="https://i.stack.imgur.com/ORJ3b.jpg" width="100%" height="100%" />
<!-- Add a red rectangle over the image. -->
<rect x="540" y="134" width="150" height="100" fill="none" stroke="red" stroke-width="2" />
<!-- Add text -->
<text x="550" y="200" font-size="48px" font-family="sans-serif" font-weight="700" fill="white" >TEST </text>
</svg>
</div>
UPDATE
If a square over the image is needed to focus on one or more fragments of the image, then
you can use it repeatedly but add individual tooltips <tooltip>
A tooltip pops up when you hover and hold the cursor on the red square
.container {
width:100vw;
height:100vh;
}
.rect {
fill:transparent;
stroke:red;
stroke-width:2;
}
<div class="container">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 1024 768" preserveAspectRatio="xMinYMin meet" >
<!-- Add image -->
<image xlink:href="https://i.stack.imgur.com/uOg10.jpg" width="100%" height="100%" />
<!-- Add a red rectangles over the image. -->
<g>
<!-- Tooltip pops up on hover -->
<title> Young lioness </title>
<rect class="rect" x="160" y="220" width="170" height="170" rx="15" />
</g>
<g>
<title> Young lion </title>
<rect class="rect" x="475" y="200" width="200" height="220" rx="15"/>
</g>
</svg>
</div>
You can consider using calc() and some CSS variables to find the width/height:
:root {
--x1:200;
--x2:100;
--x3:150;
--x4:200;
}
rect {
x:calc(var(--x1)*1px);
y:calc(var(--x2)*1px);
width:calc((var(--x1) + var(--x2))*1px);
height:calc((var(--x3) + var(--x4))*1px);
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%" viewBox="0 0 1055 717" preserveAspectRatio="xMinYMin meet" >
<rect fill="none" stroke="red" stroke-width="2" />
</svg>

SVG <use> element not visible in Chrome

I have an SVG element that is embedded into my HTML page that works perfectly on Firefox but does not work on Chrome.
I'm using a mask to cover a video background while the SVG element has a transparent fill (using CSS class on use element) to show video background through it.
I believe I identified the problem to be with the <use> tag because when I inspect it in Chrome, the use element has some dimensions but is not matching the SVG viewbox's size: <svg viewBox="0 0 1000 300" class="svg-inverted-mask"> that it lives in. In Firefox, the size of use element matches the viewbox and renders correctly.
Code:
<div class="wrap heightwrap wow fadeInDown" data-wow-delay="0.4s">
<svg viewBox="0 0 1000 300" class="svg-defs">
<!-- Symbol with Logo -->
<symbol id="s-text2">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="30%" y="-25%" width="700" height="800" viewBox="0 0 1000 800">
<defs>
<rect id="a" x="50%" y="50%" width="612" height="792"/>
</defs>
<clipPath id="b">
<use href="#a" overflow="visible"/>
</clipPath>
<path clip-path="url(#b)" d="M468.896,118.65l-80.667,254.289H145.563l-24.334-62.667h188 c0,0,26.167,0.167,33.311-18.676l15.356-50.99c20.333-62.333,22.67-67.217-34-67.667c-15.121-0.12-30.689,0.122-39.254,0.072 c-17.878-0.105-22.246,0.139-20.368-10.094l10.712-34.979c0,0,1.285-9.287,17.66-9.287"/>
<path clip-path="url(#b)" d="M275.563,267.9c28.667,0,28.013-1.13,35.833-28.5c8-28,9.457-29.082-12-29.5 c-10.548-0.205-26.166,0-26.166,0c-51.959,0-64.834,1.5-58.222-24.03c2.682-10.354,6.587-25.693,12.221-45.637 c4.024-14.247,8.103-29.353,11.369-38.006C250.481,70.74,271.842,75.708,343.23,75.9c92.334,0.249,139.333,0,139.333,0l20.333-62 h-314l-41.553,149.031c0,0-2.537,10.65-6.408-0.212L87.896,13.9h-69l89.667,254H275.563"/>
</svg>
</symbol>
<!-- Mask with text -->
<mask id="m-text2" maskunits="userSpaceOnUse" maskcontentunits="userSpaceOnUse">
<rect width="100%" height="100%" class="mask__shape">
</rect>
<use href="#s-text2" class="mask__text"></use>
</mask>
</svg>
<div class="box-with-text">
<!-- Container for video -->
<div class="text-fill">
<video class="video" src="/css/fractal3.mp4" autoplay loop></video>
</div>
<!-- Visible SVG -->
<svg viewBox="0 0 1000 300" class="svg-inverted-mask">
<rect width="100%" height="100%" mask="url(#m-text2)" class="shape--fill" />
<use href="#s-text2" class="text--transparent"></use>
</svg>
</div>
</div>
Getting rid of the unnecessary clipPaths seems to help.
They look like the sort of clips that Illustrator adds to reproduce its way of rendering strokes. But since your symbol doesn't have an stroking, they are safe to remove.
<div class="wrap heightwrap wow fadeInDown" data-wow-delay="0.4s">
<svg viewBox="0 0 1000 300" class="svg-defs">
<!-- Symbol with Logo -->
<symbol id="s-text2">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="30%" y="-25%" width="700" height="800" viewBox="0 0 1000 800">
<path d="M468.896,118.65l-80.667,254.289H145.563l-24.334-62.667h188 c0,0,26.167,0.167,33.311-18.676l15.356-50.99c20.333-62.333,22.67-67.217-34-67.667c-15.121-0.12-30.689,0.122-39.254,0.072 c-17.878-0.105-22.246,0.139-20.368-10.094l10.712-34.979c0,0,1.285-9.287,17.66-9.287"/>
<path d="M275.563,267.9c28.667,0,28.013-1.13,35.833-28.5c8-28,9.457-29.082-12-29.5 c-10.548-0.205-26.166,0-26.166,0c-51.959,0-64.834,1.5-58.222-24.03c2.682-10.354,6.587-25.693,12.221-45.637 c4.024-14.247,8.103-29.353,11.369-38.006C250.481,70.74,271.842,75.708,343.23,75.9c92.334,0.249,139.333,0,139.333,0l20.333-62 h-314l-41.553,149.031c0,0-2.537,10.65-6.408-0.212L87.896,13.9h-69l89.667,254H275.563"/>
</svg>
</symbol>
<!-- Mask with text -->
<mask id="m-text2" maskUnits="userSpaceOnUse" maskContentUnits="userSpaceOnUse">
<rect width="100%" height="100%" class="mask__shape">
</rect>
<use href="#s-text2" class="mask__text"></use>
</mask>
</svg>
<div class="box-with-text">
<!-- Container for video -->
<div class="text-fill">
<video class="video" src="/css/fractal3.mp4" autoplay loop></video>
</div>
<!-- Visible SVG -->
<svg viewBox="0 0 1000 300" class="svg-inverted-mask">
<rect width="100%" height="100%" mask="url(#m-text2)" class="shape--fill" />
<use href="#s-text2" class="text--transparent"></use>
</svg>
</div>
</div>

Keep svg pattern scaling when resizing svg-shape

I have a svg-pattern applied to a polygon. It's working fine.
When I set another size on the svg-polygon, I don't want to scale the pattern.
I've tried all combinations I can think of with viewBox, patternUnits and patternContentUnits. The goal is to make the polygon work responsibly e.g. scale with it's parent element. Can anyone point me in the right direction?
<svg width="1000" fill="#ccc" viewBox="0 0 1440 60">
<defs>
<pattern id="pattern" x="0" y="0" width="900" height="600" patternUnits="userSpaceOnUse" patternContentUnits="userSpaceOnUse">
<svg x="0" y="0" width="900.4" height="600" viewBox="0 0 900.4 600">
<!-- pattern code -->
</svg>
</pattern>
</defs>
<polygon points="0,0 1440,0 1440,20 0,60" x="0" y="0" stroke="#bbb" fill="url(#pattern)" />
</svg>
<svg width="500" fill="#ccc" viewBox="0 0 1440 60">
<defs>
<pattern id="pattern" x="0" y="0" width="900" height="600" patternUnits="userSpaceOnUse" patternContentUnits="userSpaceOnUse">
<svg x="0" y="0" width="900.4" height="600" viewBox="0 0 900.4 600">
<!-- pattern code -->
</svg>
</pattern>
</defs>
<polygon points="0,0 1440,0 1440,20 0,60" x="0" y="0" stroke="#bbb" fill="url(#pattern)" />
</svg>
full example: https://codepen.io/anderssonola/pen/QqxKjJ
I solved temporarily by applying the pattern to a <rect>and then use css clip-pathto create the polygon and the pattern does not scale. I still would prefer to solve it with pure svg, since IE does not support the css clip-path.
.clip {
background: gray;
clip-path: polygon(0 0, 100% 0, 100% 30%, 0% 100%);
margin-bottom: 1em;
}
.clip.half {
width: 50%;
}
svg {
display: block;
height: 50px;
width: 100%
}
<div >
<svg>
<defs>
<pattern id="pattern" x="0" y="0" width="900" height="600" patternUnits="userSpaceOnUse" patternContentUnits="userSpaceOnUse">
<svg x="0" y="0" width="900.4" height="600" >
<!-- pattern code -->
</svg>
</pattern>
<rect width="100%" height="50" fill="url(#pattern)" id="pattern-md"/>
</defs>
</svg>
</div>
<div class="clip">
<svg>
<use href="#pattern-md"/>
</svg>
</div>
<div class="clip half" >
<svg>
<use href="#pattern-md" />
</svg>
</div>
Working example: https://codepen.io/anderssonola/pen/oGyBMj/
You could always scale the pattern and size the polygon appropriately e.g.
<polygon transform="scale(2)" points="0,0 720,0 720,10 0,30" stroke="#bbb" fill="url(#pattern)" />

How to hide clipPath in IE

I want to hide the clipPath element so it doesn't show empty white space in the browser, but I still want to be able to use it from other svgs, like the image.
If I put width 0 and height 0 on it then IE won't show the image either.
If I put display:none the image doesn't show up in any browser.
<svg height="0" width="0" viewBox="0 0 400 400">
<defs>
<clipPath id="svgPath">
<circle fill="#FFFFFF" cx="50%" cy="50%" r="200" />
</clipPath>
</defs>
</svg>
<svg width="400" height="400" viewBox="0 0 400 400">
<image xlink:href="https://farm2.staticflickr.com/1530/25831337243_d27d32ceb5_z_d.jpg" width="100%" height="100%" preserveAspectRatio="xMinYMin slice" clip-path="url(#svgPath)" />
</svg>
Any ideas?
Put it in the same SVG as the image and there's nothing to hide.
<svg width="400" height="400" viewBox="0 0 400 400">
<defs>
<clipPath id="svgPath">
<circle fill="#FFFFFF" cx="50%" cy="50%" r="200" />
</clipPath>
</defs>
<image xlink:href="https://farm2.staticflickr.com/1530/25831337243_d27d32ceb5_z_d.jpg" width="100%" height="100%" preserveAspectRatio="xMinYMin slice" clip-path="url(#svgPath)" />
</svg>