Nesting SVGs causes unexpected resizing - html

I am trying to use nested inline SVGs in order to flexibly arrange smaller svg images within an svg container. However, I am struggling to understand the rules of how nested SVGs are sized.
svg {
display: block;
}
Why does this correctly display a 200px by 200px red square:
<svg width="200px" viewBox="0 0 100 100">
<rect width="100" height="100" fill="red" />
</svg>
But why does wrapping in another svg element cause the square to become 150px by 150px?
for example:
<svg>
<svg width="200px" viewBox="0 0 100 100">
<rect width="100" height="100" fill="red" />
</svg>
</svg>
or:
<svg width="200px">
<svg width="200px" viewBox="0 0 100 100">
<rect width="100" height="100" fill="red" />
</svg>
</svg>
or:
<svg width="200px">
<svg viewBox="0 0 100 100">
<rect width="100" height="100" fill="red" />
</svg>
</svg>

You can change the width and the height of each successive <rect> but be sure to maintain the same width and viewbox of each nested parent <svg> every time.
Working Example:
<svg width="200px" viewBox="0 0 200 200">
<rect width="200" height="200" fill="red" />
<svg width="200px" viewBox="0 0 200 200">
<rect width="100" height="100" fill="yellow" />
<svg width="200px" viewBox="0 0 200 200">
<rect width="50" height="50" fill="red" />
<svg width="200px" viewBox="0 0 200 200">
<rect width="25" height="25" fill="yellow" />
<svg width="200px" viewBox="0 0 200 200">
<rect width="12.5" height="12.5" fill="red" />
</svg>
</svg>
</svg>
</svg>
</svg>

Related

How do you scale an immutable SVG?

If I have a regular SVG element like this, but it is immutable as in you cannot clone, or change any parameters such as height and width. Is there any way to scale it?
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" height="42" width="350">
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" id="svg2" xml:space="preserve" x="30" y="0" width="80" height="65" viewBox="-200 400 1600 900">
<metadata>
...
</metadata>
<g>
...
</g>
</svg>
</svg>
If you have an SVG like this:
<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="50" fill="orange"/>
</svg>
You can wrap it in another SVG element where the viewBox matches the size of the original SVG. Now, you can specify a size (width and/or height) or leave it out to make it fill the available space.
<svg xmlns="http://www.w3.org/2000/svg" width="200" viewBox="0 0 50 50">
<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="50" fill="orange"/>
</svg>
</svg>
You can do the same with the SVG as an external resource (here a data URI for the example) where the width and the height attributes of the image element matches the viewBox of the parent SVG element.
<svg xmlns="http://www.w3.org/2000/svg" width="200" viewBox="0 0 100 100">
<image width="100" height="100" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1MCIgaGVpZ2h0PSI1MCIgdmlld0JveD0iMCAwIDEwMCAxMDAiPgogIDxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIHI9IjUwIiBmaWxsPSJvcmFuZ2UiLz4KPC9zdmc+" />
</svg>

How to scale/squish triangle symbol in SVG using `use`

I have the following system:
<html>
<head>
<style>
html, body {
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3000 3000">
<defs>
<symbol id="triangle" viewBox="0 0 100 100">
<polygon points="0,100 50,0 100,100" class="triangle" />
</symbol>
<symbol id="tree" viewBox="0 0 100 100">
<use href="#triangle" width="100" height="100" />
</symbol>
</defs>
<use href="#tree" width="200" height="400" x="1000" />
<use href="#tree" width="100" height="100" x="1100" />
</svg>
</body>
</html>
For the following:
<use href="#tree" width="200" height="400" x="1000" />
I would expect it to be a triangle that's twice the height as the width (200x400). But it just ends up being a random size that is proportional to the original 100x100 triangle.
Wondering how to get this to scale/squish the image so I can use use in multiple times and have it show different height trees all with the same width.
Same with making a #rect symbol that you can size with any width/height and it creates an appropriately shaped rectangle. If I try the following it just shows a square.
<symbol id="rect" viewBox="0 0 100 100">
<rect width='100' height='100' />
</symbol>
<use href="#rect" width="400" height="300" x="1300" y="1000" />
Add preserveAspectRatio="none" to your symbol elements.
<html>
<head>
<style>
html, body {
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3000 3000">
<defs>
<symbol id="triangle" viewBox="0 0 100 100" preserveAspectRatio="none">
<polygon points="0,100 50,0 100,100" class="triangle" />
</symbol>
<symbol id="tree" viewBox="0 0 100 100" preserveAspectRatio="none">
<use href="#triangle" width="100" height="100" />
</symbol>
<symbol id="rect" viewBox="0 0 100 100" preserveAspectRatio="none">
<rect width='100' height='100' />
</symbol>
</defs>
<use href="#tree" width="200" height="400" x="1000" />
<use href="#tree" width="100" height="100" x="1100" />
<use href="#rect" width="400" height="300" x="1300" y="1000" />
</svg>
</body>
</html>

SVG circle with image inside not working on mobile

I have code
<svg class="circle-chart in-view" version="1.1" viewBox="0 0 33.83098862 33.83098862" width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<circle class="circle-chart-background" stroke="#efefef" stroke-width="2" fill="none" cx="16.91549431" cy="16.91549431" r="15.91549431"></circle>
<defs>
<pattern id="image2" patternUnits="userSpaceOnUse" height="100" width="100">
<image xlink:href="/hoangnguyenwp/wp-content/themes/hoangnguyenwp/images/web-shop.png" x="50%" y="50%" height="32" width="32" transform="translate(-35.5,-31)"></image>
</pattern>
</defs>
<circle class="circle-chart-circle circle-shop" stroke="#E91E63" stroke-width="2" stroke-linecap="round" fill="url(#image2)" cx="16.91549431" cy="16.91549431" r="15.91549431"></circle>
</svg>
with image inside circle
<defs>
<pattern id="image2" patternUnits="userSpaceOnUse" height="100" width="100">
<image xlink:href="/hoangnguyenwp/wp-content/themes/hoangnguyenwp/images/web-shop.png" x="50%" y="50%" height="32" width="32" transform="translate(-35.5,-31)"></image>
</pattern>
</defs>
but on mobile it's not show image
What's wrong with my code ?

SVG percentage coordinate is off

I have three SVGs nested inside another SVG. The first one is supposed to be fluid and stretched out so preserveAspectRatio is none. The other two are set to 10% and 90% for the x value. But if you resize the page you'll see they have different distance from the left and right side. Why?
I'm expecting to see the left one having the same distance from left as the right one having the distance from right.
.box {
width: 60vw;
border: 1px dashed lightgray;
}
svg {
overflow: visible;
}
<div class="box">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="50">
<svg viewBox="0 0 2 2" preserveAspectRatio="none">
<rect x="0" width="2" height="1" fill="#DDDDDD" />
</svg>
<svg x="10%" viewBox="0 0 20 20" preserveAspectRatio="xMinYMid">
<rect x="0" y="0" width="10" height="10" fill="#7FDBFF" />
</svg>
<svg x="90%" viewBox="0 0 20 20" preserveAspectRatio="xMinYMid">
<rect x="0" y="0" width="10" height="10" fill="#7FDBFF" />
</svg>
</svg>
</div>
Because you're starting to draw the second blue box at 90%, when you really want to end the draw at 90%. Fix this by setting the viewBox of the second blue box to:
viewBox="20 0 20 20"
Here's another solution.
The two blue SVGs are identical apart from their preserveAspectRatio attributes.
.box {
width: 60vw;
border: 1px dashed lightgray;
}
svg {
overflow: visible;
}
<div class="box">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="50">
<svg viewBox="0 0 2 2" preserveAspectRatio="none">
<rect x="0" width="2" height="1" fill="#DDDDDD" />
</svg>
<svg x="10%" width="80%" height="100%" viewBox="0 0 10 20" preserveAspectRatio="xMinYMid">
<rect x="0" y="0" width="10" height="10" fill="#7FDBFF" />
</svg>
<svg x="10%" width="80%" height="100%" viewBox="0 0 10 20" preserveAspectRatio="xMaxYMid">
<rect x="0" y="0" width="10" height="10" fill="#7FDBFF" />
</svg>
</svg>
</div>
For anyone as confused as me, here is the problem:
If I set the viewBox x value to half of the width 10 / 2 = 5, then I technically panned the origin to the width's center.
.box {
width: 60vw;
border: 1px dashed lightgray;
}
svg {
overflow: visible;
}
<div class="box">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="50">
<svg viewBox="0 0 2 2" preserveAspectRatio="none">
<rect x="0" width="2" height="1" fill="#DDDDDD" />
</svg>
<svg x="10%" viewBox="5 0 20 20" preserveAspectRatio="xMinYMid">
<rect x="0" y="0" width="10" height="10" fill="#7FDBFF" />
</svg>
<svg x="90%" viewBox="5 0 20 20" preserveAspectRatio="xMinYMid">
<rect x="0" y="0" width="10" height="10" fill="#7FDBFF" />
</svg>
</svg>
</div>

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>