Understand SVG viewport - svg

I'm trying to understand the SVG viewport. Why are these three examples so different?
svg {
border: 2px solid red;
}
<div>
<svg>
<rect x="0" y="0" width="100" height="100" fill="blue" />
</svg>
<svg width="200" height="200">
<rect x="0" y="0" width="100" height="100" fill="blue" />
</svg>
<svg viewBox="0 0 200 200">
<rect x="0" y="0" width="100" height="100" fill="blue" />
</svg>
</div>

The first example is missing a width and height. The CSS specification says that replaced elements missing width and height values fallback to 300px x 150px so you'd see the top left 300 x 150 px of whatever you're drawing onto the canvas.
The second example has width and height so you'd see that part of the canvas.
The third example also has no width/height but oddly we're now going to use the 100% x 100% lacuna values for the width/height because we have a usable aspect ratio from the viewBox. The viewBox also scales the 200 x 200 internal co-ordinate system to fix into that canvas so everything looks bigger.

Related

Viewbox changing width of element

Would somebody be able to explain to me why adding viewBox="0 0 612 100" in the snippet below changes the width of the embedded rectangle? Based on everything I know about viewbox if the numbers match the user units of the SVG, no zooming or panning should be done, and thus the size of the two rectangles should be the same.
<div>
<svg width='612pt' height='100pt' xmlns="http://www.w3.org/2000/svg">
<rect width="100pt" height="100pt" />
</svg>
</div>
<div>
<svg width='612pt' height='100pt' viewBox="0 0 612 100" xmlns="http://www.w3.org/2000/svg">
<rect width="100pt" height="100pt"/>
</svg>
</div>
Your viewbox is measured in pixels (px - also the default unit in SVG), while you have measured the other widths/heights in points (pt).
Point vs Pixel: What is the difference?
Use pixels all over, and things will work the way you expect:
<svg width="200" height="150" viewBox="0 0 200 150" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" fill="pink"/>
<rect width="100pt" height="100pt" fill="red"/>
<rect width="100" height="100" fill="green"/>
</svg>

How to reduce svg size to clipped area?

Is it possible to reduce the actual size (i.e. width and height) to the clipping? Let's see the svg below for an example:
The underlying "base" image has a size of 272x136 pixels. The clipping result has a size of 17x17 pixels. Now I would like that the resulting svg is resized to 17x17 pixels. Is that even possible?
<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<clipPath id="cut-off-bottom">
<rect x="102" y="102" width="17" height="17"/>
</clipPath>
</defs>
<image xlink:href="https://openmaptiles.github.io/osm-bright-gl-style/sprite.png" clip-path="url(#cut-off-bottom)" />
</svg>
Select the area you want to see with a viewBox and then set the size of the SVG to whatever you want using the outer <svg> element's width and height
I've also added width and height attributes to the image element so it works on browsers other than Chrome/Opera.
<svg width="17px" height="17px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="102 102 17 17">
<defs>
<clipPath id="cut-off-bottom">
<rect x="102" y="102" width="17" height="17"/>
</clipPath>
</defs>
<image xlink:href="https://openmaptiles.github.io/osm-bright-gl-style/sprite.png" clip-path="url(#cut-off-bottom)" width="272px" height="136px" />
</svg>

Why does this SVG image have a height of 150px

Why is this SVG image displayed at 150px height inside this 500px container? Why this specific value?
I found this weird behavior in both js bin and Codepen, so I think it is something to do with my code and not with the online editors.
Note: a 700px div container results in the same thing. So the height of the parent doesn't matter.
<div style="padding: 30px; background-color: yellow; height: 500px; width: 500px; ">
<svg>
<pattern id="basicPattern" x="10" y="10" width="40" height="40" patternUnits="userSpaceOnUse" >
<rect x= "0" y="0" width="4" height="4"
stroke = "red"
stroke-width = "1"
fill = "black"/>
</pattern>
<!-- <rect x="0" y="0" width="300" height="151" // why this deletes the bottom line? -->
<!-- <rect x="0" y="0" width="300" height="150" // why this deletes 1 px from the bottom line? -->
<!-- but this height="149" is the bottom limmit for this picture..
what prevent's it bor beeing extended further - we have unthil 500 px as you can see on the div.-->
<rect x="0" y="0" width="300" height="149"
stroke= "red"
stroke-width="2"
fill="url(#basicPattern)" />
</svg>
This is Jsbin and this is CodePen.
You didn't set the SVG width and height, so it goes to the default size of 300px width x 150px height (for some user-agents).
Here is your JSBin with the SVG width and height both set to 500px. Now the rectangle can go beyond 150px of height: https://jsbin.com/yafenemawe/1/edit?html,output

How to make SVG scale only on X axis?

I have the following SVG graphic that is currently scaling when the window is resized, but the aspect ratio is maintained. How could I get this to only scale on the X axis, and keep the Y at 80px?
<svg width="100%" viewBox="0 0 300 80">
<rect x="0" y="0" fill="yellow" height="80" width="100"/>
<rect x="100" y="0" fill="blue" height="80" width="100"/>
<rect x="200" y="0" fill="red" height="80" width="100"/>
</svg>
Thank you,
You have a couple of options. First, you could simply specify the height of the graphic, e.g. using CSS.
svg {
height: 80px;
width: 100%;
}
If that's not the effect you want, you can get more sophisticated with the preserveAspectRatio attribute. It's hard to say what value would work for you since it's not completely clear what you want (assuming the CSS approach above doesn't do it), but maybe something like:
<svg viewBox="0 0 300 80" preserveAspectRatio="none">
Check out the reference link for more details.

How I can get text with desired height and width?

I need to get text with desired height and width.
I tried to find something in documentation of svg but found only font-size and also I tried to use scale in such manner:
<text xmlns="http://www.w3.org/2000/svg" id="10996080909940" name="-1"
x="1782.9351809218" y="-751.796133712862" width="1" height="1" style="font:Arial;text-
anchor:start;stroke:#000000" transform="rotate(0) scale(2 2)"> SOME TEXT </text>
But I get too big size of text and in place not where I need.
If you mean you want the text to exactly fill an arbitrary width and height, then there isn't really an easy way to do it in SVG. You can't specifiy a width and height on the <text> element. At least not in the current SVG spec (1.1).
However there are several ways to achieve this effect with a bit of trickery.
One way is by using a transform, as you suggested:
<svg>
<text font-size="10px" font-family="Verdana" transform="translate(99,400) scale(3.5,13.7)">SQUASHED TEXT</text>
<rect x="100" y="300" width="300" height="100" fill="none" stroke="red" />
</svg>
A second way is by using an inner <svg> element and setting the viewBox to match the bounds of the text. You then set preserveAspectRatio="none".
<svg>
<svg x="100" y="100" width="300" height="100" viewBox="0.2 -7.3 86 7.3" preserveAspectRatio="none" overflow="visible">
<text font-size="10px" font-family="Verdana">SQUASHED TEXT</text>
</svg>
<rect x="100" y="100" width="300" height="100" fill="none" stroke="red" />
</svg>
This way is more verbose, but it has the advantage that once you have found the correct viewBox for a piece of text, you can make it fit any sized rectangle very easily. Just set the x,y,width and height of the inner <svg> to the size of the rectangle.
Demo here: http://jsfiddle.net/ZRgEF/3/

Resources