Related
I am trying to get exact pixel counts on an svg, but it seems off. I want it to be 300x56, but for some reason its rendering as 222x41
This is the code
But it seems like the pixels are inconsistent when I inspect:It says 222x41 here
but 300x56 here
How is 222x41 calculated, and why does chrome debugger show both 300x56 and 222x41?
Explaining what you are seeing would require seeing more of the page. We would need to see how the element containing the <svg> is styled.
But here's a quick explainer.
The area of your page that the SVG is displayed in is called the "viewport". The size of the viewport is determined by one of two things:
The width and height of the SVG if they use explicit units - such as px, or
The size of the SVGs parent container if the SVG specifies percentage units.
Your SVG has a viewBox this determines which area of the SVG canvas is displayed in the viewport. The browser will scale the area of the viewBox up of down so it fits in the viewport. Unless you turn it off, the contents will keep its aspect ratio
So since your SVG has a viewBox and its width and height are set to "100%", the SVG viewport will be scaled to fit into the parent container and the SVG contents will be scaled to fit into that viewport.
You said you were trying to make the SVG be 300x56, but it looks like all you did to try and achieve that is set the <rect> to that size. That is not enough because of the reasons stated above. The effect of the viewport and the viewBox will be affecting the size that the rectangle is drawn at.
The viewBox of your SVG is 1500x280. Your rectangle is occupying a small part of that - from (10,10) to (310,66). Since your rectangle is being scaled down to 222.93x41.61, the SVG's parent container must be smaller than the viewBox. We can work out how big it must be:
1500 * (222.93/300) ~= 1115 (if the width is constrained) or
280 * ( 41.61/ 56) ~= 208 (if the height is constrained).
If you want your SVG to be exactly 300x56 always, then what you probably want is to set the SVG's width and height, not the rectangle's.
<svg width="300" height="56">
<rect width="300" height="56" rx="4"/>
</svg>
Now the SVG will behave the same as if it was a 300x56 pixel PNG.
I am learning svg from its official documents, there is such line. I don't get it, if it already has a width and height attribute, what is the point to specify it again in viewBox="0 0 1500 1000" ?
It is says, "One px unit is defined to be equal to one user unit. Thus, a length of "5px" is the same as a length of "5"" in the official docs, thus this viewBox is a 1500px wide and 1000 height view, which exceeds 300px and 200px. So why does it define the width and height value in the first place?
<svg width="300px" height="200px" version="1.1"
viewBox="0 0 1500 1000" preserveAspectRatio="none"
xmlns="http://www.w3.org/2000/svg">
The width and height are how big the <svg> is. The viewBox controls how its contents are displayed so the viewBox="0 0 1500 1000" will scale down the contents of <svg> element by a factor of 5 (1500 / 300 = 5 and 1000 / 200 = 5) and the contents will be 1/5 the size they would be without the viewBox but the <svg>
Imagine you have an elastic surface and cut it into 4 equal pieces. If you throw 3 pieces away you've got a surface that's 1/4 the size of the original surface. If you now stretch the surface and make it the same size as the original surface then everything on the surface will be twice the size. That's how viewBox and width/height are related.
If you don't specify a viewbox, all unitless numbers in an element are assumed to be pixels. (and SVG assumes 90 dpi or pixels per inch for conversion from units like cm to pixels.)
A viewbox lets you make unitless numbers in elements mean "user units" and specifies how those units are mapped to the size. For simplicity, consider just the x coordinates, that is, a ruler. Your viewbox says that your ruler will have 1500 units to match the 200 pixel size width of the svg.
A line element from 0 to 1500 (unitless, i.e. user units) would stretch 200 pixels as drawn, that is, across the width of the svg drawing.
(And since SVG is scalable without loss of resolution, pixels really don't mean much in the real world, when a user zooms in or out.)
Its a coordinate transformation, of sorts.
I suggest you learn from a book like "SVG Essentials", about $10 used, from which I loosely quote this answer.
By default
<svg width="300" height="200">
the "ruler" of svg grid is in pixel (all shapes in that svg is measured in pixel)
But you want to use your own units you can use viewBox attr for that:
<svg width="300" height="200" viewBox="0 0 1500 1000">
That means:
horizontal axis: 1500 (your width unit) = 300px => 1 (your width unit) = 300/1500px = 1/5px
vertical axis: 1000 (your height unit) = 200px => 1 (your height unit) = 200/1000px = 1/5px
Now all shapes in the svg will scale:
their widths scale to 1/5px (1/5 < 1 => scale down) comparing to the origin.
their heights also scale to 1/5px (1/5 < 1 => scale down) comparing to the origin
MAIN:
The viewBox attribute is closely related to the term viewport in SVG
ABBREVIATION:
viewBox - VB
viewport - VP
viewport coordinate system - VCS
local coordinate system - LCS
SYNTAX:
<svg x = "VP_min_X" y = "VP_min_Y" width = "VP_width" height = "VP_height"
viewBox = "VB_min_X VB_min_Y VB_width VB_height">
DEFAULT VALUES:
units = px
viewport width = 300
viewport width = 150
viewBox = viewport
CODE WITH DEFAULT VALUES
<svg>
CODE WITH THE SAME RESULT:
<svg x = "0" y = "0" width = "300" height = "150" viewBox = "0 0 300 150">
VIEWPORT SETTINGS:
THE ORIGIN POINT of the viewport coordinate system (VCS):
VP_min_X
VP_min_Y
in the case of the outermost viewport, these values do not matter
and in any case will be equal to 0, they are usually omitted:
<svg width = "100" height = "150">
CODE WITH THE SAME RESULT: (for the most external viewport):
<svg x = "10" y = 20 "width ="100 "height ="150">
NESTED VIEWPORT:
In a nested viewport (VP_min_X, VP_min_Y) define the indent from the origin point of VCS:
<svg width="100%" height="100%"> <!-- external viewport = full browser size -->
<svg x="50" y="100" width="200" height="300" viewBox="0 0 100 100">
</svg>
</svg>
in this case indent of the nested viewport:
50px along the X axis and 100px along the Y axis from the origin point of the external VCS.
THE DIMENSIONS of the rectangular area (viewport) in which SVG grafics will be drawn are determined:
VP_width
VP_height
VIEWBOX SETTINGS:
THE ORIGIN POINT of the local coordinate system (LCS):
Vb_min_X
Vb_min_y
THE SIZE of the visible part of the SVG image:
Vb_width
Vb_height
RENDERING:
When constructing the final SVG image, the coordinate systems are transformed by COMBINING:
Points of origin of coordinate systems:
VCS (VP_min_X, VP_min_Y)
LCS (VB_min_X, VB_min_Y)
End points of the visible image area:
VCS (VP_width, VP_height)
LCS (VB_width, VB_height)
CAPABILITIES:
As a result, it becomes possible to control:
location of the viewport in the browser window [using the nested viewport and changing (VP_min_X, VP_min_Y)]
viewport sizes (VP_width, VP_height)
panning the visible part of the image [using viewBox and changing (VB_min_X, VB_min_Y)]
scaling the visible part of the image [using viewBox and changing (VB_width, VB_height)]
VISUALIZATION:
2 minutes on YouTube to understand the principles described above:
video viewBox in SVG
DOCUMENTATION:
W3C 2019 SVG 2 specification
Here is some practical information that I find useful to understand (and particularly to work with) SVG viewPort and viewBox.
SVG uses the terms viewPort and viewBox. The viewBox is inside the viewPort. Think of the viewBox as the image itself – because you can zoom it, slide it left/right/up/down – all within the viewPort. The viewPort (the SVG tag itself) is like a container that the SVG image is inside. You can size this also, and move it around left/right/up/down. And the SVG tag is within an HTML container (div, p, aside, h3, etc). So you can see why people find viewPort / viewBox to be a bit confusing. Just think of viewBox as the image itself.
The width/height attributes on the SVG tag provide the size of the viewPort. This is the width/height of the container in which the SVG image is displayed. (You can also have x="" and y="" attributes, just as you have in the viewBox attribute.)
So, on the SVG itself, you specify width /height and starting x offset / starting y offset – these are called the viewPort (aka ViewPort Coord System)
In the viewBox attribute, you specify "x y width height" – these are called the viewBox (aka Local Coord System LCS)
<svg x="0" y="0" width="500" height="300"
viewBox="start_x start_y width height" >
...path fill d etc...
</svg>
Important Concept #1: the width/height of the viewPort (the ones that are on the SVG tag itself, as width="" and height="") specify the size of the container in which the SVG image will be displayed. Usually, or if omitted, this is the exact size as (or a tiny bit larger than) the SVG image itself.
Super-Important Concept #2: the width/height of the viewBox is directly related to the width/height of the viewPort. If the viewPort is 300 x 500, then as the viewBox W / H numbers get LARGER than 300 x 500, the image itself grows smaller within the viewPort (zooms out). But as the viewBox w/h gets smaller than 300 x 500, the image itself grows LARGER within the viewPort. This growth is to the right and down, so if you need to slide the zoomed-in image around in the now-too-small viewPort, that is when you use the X / Y values of the viewBox.
viewBox x/y – slides the SVG right/down inside the viewPort
viewBox width/height – as increase larger than the SVG tag's width/height, it zooms the image OUT inside the viewPort. The SVG shrinks right/down within the viewport. Decrease number below the SVG width/height attribs: the image will GROW in the viewport until portions of the image to the right/bottom may be cut off by the rightSide/Bottom of the viewPort. *(i.e. when the width/height numbers in the viewBox attribute are less than the width/height attributes on the SVG, the image ZOOMS IN within the viewPort. When larger, the image zooms OUT (shrinks) with the viewPort.
viewPort x/y == slides the viewport itself right/down within its HTML container
viewPort width/height – resizes the entire viewPort larger, possibly overflowing the HTML container (div / p / etc). Basically, makes the viewPort larger by growing it right/down.
Notes:
a. If you do not include the ViewBox attribute on the SVG, then the size of the viewBox equals the size of the viewPort (takes 100% of the viewPort)
b. If the viewBox begins 0,0 and has same width/height as the SVG width/height (i.e. the viewPort), nothing will change. Equivalent to not having a viewbox attribute at all.
c. If you have a viewPort the size of a deck of cards, but the SVG image is the size of a cereal box, then increasing the viewBox "x y …" numbers will move the cereal box image up/left in the viewPort, showing a different part of the cereal box's image. This would be useful with sprites
d. (Usually (always!) the SVG element is also inside an HTML container - a div, p, section, li, whatever. We didn't discuss this, but remember it. If your image is being cut off, then either the viewBox is larger than the viewPort -OR- the HTML container element (div, etc) is smaller than the viewPort)
Here are two (excellent!) short videos, referred to us by the author of this answer within this same thread:
2min video demo
5min video demo (same guy, much better)
Here's a non-technical way of illustrating the relationship between width, height and the viewBox:
If you had any old image on your computer with the dimensions 1500 x 1000, and you pinched the corner of the image and resized it to 300 x 200, the image would shrink, or scale down (assuming scaling is enabled). The opposite is also true.
A good rule of thumb is to always look at the viewBox width and height first, and compare it to the SVG's width and height (or the parent's width and height if they are not declared in the SVG). That way you can tell whether the SVG image will scale up (grow), or down (shrink).
<svg width="300px" height="200px" viewBox="0 0 1500 1000">
The above is telling the browser that you have an SVG that's 1500 x 1000 but you want it to "pinch the corners" and shrink it down to 300 x 200.
viewbox is a ratio
In my humble experience, I've always considered <svg>’s viewbox values as a required image ratio to apply to the width and height values. While defining the laters just I do with any <img> in the DOM, either inline HTML properties or via CSS, viewbox property only applies to the SVG file.
I want to have an inline svg element's contents scale when size is non-native. Of course I could have it as a separate file and scale it like that.
index.html: <img src="foo.svg" style="width: 100%;" />
foo.svg: <svg width="123" height="456"></svg>
However, I want to add additional styles to the SVG thru CSS, so linking an external one is not an option. How do I make an inline SVG scale?
To specify the coordinates within the SVG image independently of the scaled size of the image, use the viewBox attribute on the SVG element to define what the bounding box of the image is in the coordinate system of the image, and use the width and height attributes to define what the width or height are with respect to the containing page.
For instance, if you have the following:
<svg>
<polygon fill=red stroke-width=0
points="0,10 20,10 10,0" />
</svg>
It will render as a 10px by 20px triangle:
Now, if you set only the width and height, that will change the size of the SVG element, but not scale the triangle:
<svg width=100 height=50>
<polygon fill=red stroke-width=0
points="0,10 20,10 10,0" />
</svg>
If you set the view box, that causes it to transform the image such that the given box (in the coordinate system of the image) is scaled up to fit within the given width and height (in the coordinate system of the page). For instance, to scale up the triangle to be 100px by 50px:
<svg width=100 height=50 viewBox="0 0 20 10">
<polygon fill=red stroke-width=0
points="0,10 20,10 10,0" />
</svg>
If you want to scale it up to the width of the HTML viewport:
<svg width="100%" viewBox="0 0 20 10">
<polygon fill=red stroke-width=0
points="0,10 20,10 10,0" />
</svg>
Note that by default, the aspect ratio is preserved. So if you specify that the element should have a width of 100%, but a height of 50px, it will actually only scale up to the height of 50px (unless you have a very narrow window):
<svg width="100%" height="50px" viewBox="0 0 20 10">
<polygon fill=red stroke-width=0
points="0,10 20,10 10,0" />
</svg>
If you actually want it to stretch horizontally, disable aspect ratio preservation with preserveAspectRatio=none:
<svg width="100%" height="50px" viewBox="0 0 20 10" preserveAspectRatio="none">
<polygon fill=red stroke-width=0
points="0,10 20,10 10,0" />
</svg>
(note that while in my examples I use syntax that works for HTML embedding, to include the examples as an image in StackOverflow I am instead embedding within another SVG, so I need to use valid XML syntax)
After like 48 hours of research, I ended up doing this to get proportional scaling:
NOTE: This sample is written with React. If you aren't using that, change the camel case stuff back to hyphens (ie: change backgroundColor to background-color and change the style Object back to a String).
<div
style={{
backgroundColor: 'lightpink',
resize: 'horizontal',
overflow: 'hidden',
width: '1000px',
height: 'auto',
}}
>
<svg
width="100%"
viewBox="113 128 972 600"
preserveAspectRatio="xMidYMid meet"
>
<g> ... </g>
</svg>
</div>
Here's what is happening in the above sample code:
VIEWBOX
MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox
min-x, min-y, width and height
ie: viewbox="0 0 1000 1000"
Viewbox is an important attribute because it basically tells the SVG what size to draw and where. If you used CSS to make the SVG 1000x1000 px but your viewbox was 2000x2000, you would see the top-left quarter of your SVG.
The first two numbers, min-x and min-y, determine if the SVG should be offset inside the viewbox.
My SVG needs to shift up/down or left/right
Examine this: viewbox="50 50 450 450"
The first two numbers will shift your SVG left 50px and up 50px, and the second two numbers are the viewbox size: 450x450 px. If your SVG is 500x500 but it has some extra padding on it, you can manipulate those numbers to move it around inside the "viewbox".
Your goal at this point is to change one of those numbers and see what happens.
You can also completely omit the viewbox, but then your milage will vary depending on every other setting you have at the time. In my experience, you will encounter issues with preserving aspect ratio because the viewbox helps define the aspect ratio.
PRESERVE ASPECT RATIO
MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/preserveAspectRatio
Based on my research, there are lots of different aspect ratio settings, but the default one is called xMidYMid meet. I put it on mine to explicitly remind myself. xMidYMid meet makes it scale proportionately based on the midpoint X and Y. This means it stays centered in the viewbox.
WIDTH
MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/width
Look at my example code above. Notice how I set only width, no height. I set it to 100% so it fills the container it is in. This is what is probably contributing the most to answering this Stack Overflow question.
You can change it to whatever pixel value you want, but I'd recommend using 100% like I did to blow it up to max size and then control it with CSS via the parent container. I recommend this because you will get "proper" control. You can use media queries and you can control the size without crazy JavaScript.
SCALING WITH CSS
Look at my example code above again. Notice how I have these properties:
resize: 'horizontal', // you can safely omit this
overflow: 'hidden', // if you use resize, use this to fix weird scrollbar appearance
width: '1000px',
height: 'auto',
This is additional, but it shows you how to allow the user to resize the SVG while maintaining the proper aspect ratio. Because the SVG maintains its own aspect ratio, you only need to make width resizable on the parent container, and it will resize as desired.
We leave height alone and/or set it to auto, and we control the resizing with width. I picked width because it is often more meaningful due to responsive designs.
Here is an image of these settings being used:
If you read every solution in this question and are still confused or don't quite see what you need, check out this link here. I found it very helpful:
https://css-tricks.com/scale-svg/
It's a massive article, but it breaks down pretty much every possible way to manipulate an SVG, with or without CSS. I recommend reading it while casually drinking a coffee or your choice of select liquids.
You'll want to do a transform as such:
with JavaScript:
document.getElementById(yourtarget).setAttribute("transform", "scale(2.0)");
With CSS:
#yourtarget {
transform:scale(2.0);
-webkit-transform:scale(2.0);
}
Wrap your SVG Page in a Group tag as such and target it to manipulate the whole page:
<svg>
<g id="yourtarget">
your svg page
</g>
</svg>
Note: Scale 1.0 is 100%
Messing around & found this CSS seems to contain the SVG in Chrome browser up to the point where the container is larger than the image:
div.inserted-svg-logo svg { max-width:100%; }
Also seems to be working in FF + IE 11.
Here's an easy way:
Type 1: Most SVGs have a viewbox, like so:
<svg viewBox="0 0 24 30" ...>
And you can easily control their size in css:
svg {
height: 20px;
}
Type 2: If the svg has width and height, but doesn't have a viewport, like so:
<svg width="810" height="540">
Then you can just manually add a viewbox that's exactly the same as its width and hegith, like so:
<svg width="810" height="540" viewBox="0 0 810 540">
Then you can do the same as type 1.
Another simple way is
transform: scale(1.5);
changing the SVG file was not a fair solution for me so instead, I used relative CSS units.
vh, vw, % are very handy. I used a CSS like height: 2.4vh; to set a dynamic size to my SVG images.
If you want to scale SVG without preserveAspectRatio attribute.
This way SVG will always stretch to fill both width and height, and to do so, it will resize just width or height, if necessary, was looking for this for days, so thought to share it here in case someone else is looking for this
You have to remove width and height from <svg> and add viewBox attribute and add preserveAspectRatio="none"
example
<?xml version="1.0" encoding="utf-8"?>
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 5.8208332 15.9"
preserveAspectRatio="none">
<polygon points="480.4,200 0,200 0,0 480.4,0 599.9,100 " fill="#E1E1E1"/>
</svg>
Adjusting the currentScale attribute works in IE ( I tested with IE 11), but not in Chrome.
What is the role of View-box in SVG and what if we don't provide it?
Is it important?
viewBox is the difference between your SVG being responsive and not.
With a viewBox if you rescale your canvas, the contents will rescale too, without it the contents will stay the same size and you'll either be able to see more or less of it kind of like putting a picture frame over a picture.
The viewBox attribute defines the position and dimension, in user
space, of an SVG viewport. The value of the viewBox attribute is a list of four numbers:
min-x, min-y, width, and height. The numbers separated by whitespace
and/or a comma, which specifies a rectangle in user space which is
mapped to the bounds of the viewport established for the associated
SVG element
This is referenced from MDN docs. Basically, you are setting the coordinates and width and height of your SVG. The syntax is - viewBox = "min-x min-y width height". The purpose of viewBox is to select that part of the your SVG plane, that should actually be rendered onto the page.
Without the viewBox tag and without any width or height specified, the svg won't scale. Here's an example -
<!--This one is without a viewbox which wont scale-->
<svg>
<path d="M 15,5 25,27.5 5,27.5 z"/>
</svg>
<!--This one is with a viewbox which will scale. Check by opening in full page-->
<svg viewBox="0 0 200 200">
<path d="M 15,5 25,27.5 5,27.5 z"/>
</svg>
I am learning svg from its official documents, there is such line. I don't get it, if it already has a width and height attribute, what is the point to specify it again in viewBox="0 0 1500 1000" ?
It is says, "One px unit is defined to be equal to one user unit. Thus, a length of "5px" is the same as a length of "5"" in the official docs, thus this viewBox is a 1500px wide and 1000 height view, which exceeds 300px and 200px. So why does it define the width and height value in the first place?
<svg width="300px" height="200px" version="1.1"
viewBox="0 0 1500 1000" preserveAspectRatio="none"
xmlns="http://www.w3.org/2000/svg">
The width and height are how big the <svg> is. The viewBox controls how its contents are displayed so the viewBox="0 0 1500 1000" will scale down the contents of <svg> element by a factor of 5 (1500 / 300 = 5 and 1000 / 200 = 5) and the contents will be 1/5 the size they would be without the viewBox but the <svg>
Imagine you have an elastic surface and cut it into 4 equal pieces. If you throw 3 pieces away you've got a surface that's 1/4 the size of the original surface. If you now stretch the surface and make it the same size as the original surface then everything on the surface will be twice the size. That's how viewBox and width/height are related.
By default
<svg width="300" height="200">
the "ruler" of svg grid is in pixel (all shapes in that svg is measured in pixel)
But you want to use your own units you can use viewBox attr for that:
<svg width="300" height="200" viewBox="0 0 1500 1000">
That means:
horizontal axis: 1500 (your width unit) = 300px => 1 (your width unit) = 300/1500px = 1/5px
vertical axis: 1000 (your height unit) = 200px => 1 (your height unit) = 200/1000px = 1/5px
Now all shapes in the svg will scale:
their widths scale to 1/5px (1/5 < 1 => scale down) comparing to the origin.
their heights also scale to 1/5px (1/5 < 1 => scale down) comparing to the origin
If you don't specify a viewbox, all unitless numbers in an element are assumed to be pixels. (and SVG assumes 90 dpi or pixels per inch for conversion from units like cm to pixels.)
A viewbox lets you make unitless numbers in elements mean "user units" and specifies how those units are mapped to the size. For simplicity, consider just the x coordinates, that is, a ruler. Your viewbox says that your ruler will have 1500 units to match the 200 pixel size width of the svg.
A line element from 0 to 1500 (unitless, i.e. user units) would stretch 200 pixels as drawn, that is, across the width of the svg drawing.
(And since SVG is scalable without loss of resolution, pixels really don't mean much in the real world, when a user zooms in or out.)
Its a coordinate transformation, of sorts.
I suggest you learn from a book like "SVG Essentials", about $10 used, from which I loosely quote this answer.
MAIN:
The viewBox attribute is closely related to the term viewport in SVG
ABBREVIATION:
viewBox - VB
viewport - VP
viewport coordinate system - VCS
local coordinate system - LCS
SYNTAX:
<svg x = "VP_min_X" y = "VP_min_Y" width = "VP_width" height = "VP_height"
viewBox = "VB_min_X VB_min_Y VB_width VB_height">
DEFAULT VALUES:
units = px
viewport width = 300
viewport width = 150
viewBox = viewport
CODE WITH DEFAULT VALUES
<svg>
CODE WITH THE SAME RESULT:
<svg x = "0" y = "0" width = "300" height = "150" viewBox = "0 0 300 150">
VIEWPORT SETTINGS:
THE ORIGIN POINT of the viewport coordinate system (VCS):
VP_min_X
VP_min_Y
in the case of the outermost viewport, these values do not matter
and in any case will be equal to 0, they are usually omitted:
<svg width = "100" height = "150">
CODE WITH THE SAME RESULT: (for the most external viewport):
<svg x = "10" y = 20 "width ="100 "height ="150">
NESTED VIEWPORT:
In a nested viewport (VP_min_X, VP_min_Y) define the indent from the origin point of VCS:
<svg width="100%" height="100%"> <!-- external viewport = full browser size -->
<svg x="50" y="100" width="200" height="300" viewBox="0 0 100 100">
</svg>
</svg>
in this case indent of the nested viewport:
50px along the X axis and 100px along the Y axis from the origin point of the external VCS.
THE DIMENSIONS of the rectangular area (viewport) in which SVG grafics will be drawn are determined:
VP_width
VP_height
VIEWBOX SETTINGS:
THE ORIGIN POINT of the local coordinate system (LCS):
Vb_min_X
Vb_min_y
THE SIZE of the visible part of the SVG image:
Vb_width
Vb_height
RENDERING:
When constructing the final SVG image, the coordinate systems are transformed by COMBINING:
Points of origin of coordinate systems:
VCS (VP_min_X, VP_min_Y)
LCS (VB_min_X, VB_min_Y)
End points of the visible image area:
VCS (VP_width, VP_height)
LCS (VB_width, VB_height)
CAPABILITIES:
As a result, it becomes possible to control:
location of the viewport in the browser window [using the nested viewport and changing (VP_min_X, VP_min_Y)]
viewport sizes (VP_width, VP_height)
panning the visible part of the image [using viewBox and changing (VB_min_X, VB_min_Y)]
scaling the visible part of the image [using viewBox and changing (VB_width, VB_height)]
VISUALIZATION:
2 minutes on YouTube to understand the principles described above:
video viewBox in SVG
DOCUMENTATION:
W3C 2019 SVG 2 specification
Here is some practical information that I find useful to understand (and particularly to work with) SVG viewPort and viewBox.
SVG uses the terms viewPort and viewBox. The viewBox is inside the viewPort. Think of the viewBox as the image itself – because you can zoom it, slide it left/right/up/down – all within the viewPort. The viewPort (the SVG tag itself) is like a container that the SVG image is inside. You can size this also, and move it around left/right/up/down. And the SVG tag is within an HTML container (div, p, aside, h3, etc). So you can see why people find viewPort / viewBox to be a bit confusing. Just think of viewBox as the image itself.
The width/height attributes on the SVG tag provide the size of the viewPort. This is the width/height of the container in which the SVG image is displayed. (You can also have x="" and y="" attributes, just as you have in the viewBox attribute.)
So, on the SVG itself, you specify width /height and starting x offset / starting y offset – these are called the viewPort (aka ViewPort Coord System)
In the viewBox attribute, you specify "x y width height" – these are called the viewBox (aka Local Coord System LCS)
<svg x="0" y="0" width="500" height="300"
viewBox="start_x start_y width height" >
...path fill d etc...
</svg>
Important Concept #1: the width/height of the viewPort (the ones that are on the SVG tag itself, as width="" and height="") specify the size of the container in which the SVG image will be displayed. Usually, or if omitted, this is the exact size as (or a tiny bit larger than) the SVG image itself.
Super-Important Concept #2: the width/height of the viewBox is directly related to the width/height of the viewPort. If the viewPort is 300 x 500, then as the viewBox W / H numbers get LARGER than 300 x 500, the image itself grows smaller within the viewPort (zooms out). But as the viewBox w/h gets smaller than 300 x 500, the image itself grows LARGER within the viewPort. This growth is to the right and down, so if you need to slide the zoomed-in image around in the now-too-small viewPort, that is when you use the X / Y values of the viewBox.
viewBox x/y – slides the SVG right/down inside the viewPort
viewBox width/height – as increase larger than the SVG tag's width/height, it zooms the image OUT inside the viewPort. The SVG shrinks right/down within the viewport. Decrease number below the SVG width/height attribs: the image will GROW in the viewport until portions of the image to the right/bottom may be cut off by the rightSide/Bottom of the viewPort. *(i.e. when the width/height numbers in the viewBox attribute are less than the width/height attributes on the SVG, the image ZOOMS IN within the viewPort. When larger, the image zooms OUT (shrinks) with the viewPort.
viewPort x/y == slides the viewport itself right/down within its HTML container
viewPort width/height – resizes the entire viewPort larger, possibly overflowing the HTML container (div / p / etc). Basically, makes the viewPort larger by growing it right/down.
Notes:
a. If you do not include the ViewBox attribute on the SVG, then the size of the viewBox equals the size of the viewPort (takes 100% of the viewPort)
b. If the viewBox begins 0,0 and has same width/height as the SVG width/height (i.e. the viewPort), nothing will change. Equivalent to not having a viewbox attribute at all.
c. If you have a viewPort the size of a deck of cards, but the SVG image is the size of a cereal box, then increasing the viewBox "x y …" numbers will move the cereal box image up/left in the viewPort, showing a different part of the cereal box's image. This would be useful with sprites
d. (Usually (always!) the SVG element is also inside an HTML container - a div, p, section, li, whatever. We didn't discuss this, but remember it. If your image is being cut off, then either the viewBox is larger than the viewPort -OR- the HTML container element (div, etc) is smaller than the viewPort)
Here are two (excellent!) short videos, referred to us by the author of this answer within this same thread:
2min video demo
5min video demo (same guy, much better)
Here's a non-technical way of illustrating the relationship between width, height and the viewBox:
If you had any old image on your computer with the dimensions 1500 x 1000, and you pinched the corner of the image and resized it to 300 x 200, the image would shrink, or scale down (assuming scaling is enabled). The opposite is also true.
A good rule of thumb is to always look at the viewBox width and height first, and compare it to the SVG's width and height (or the parent's width and height if they are not declared in the SVG). That way you can tell whether the SVG image will scale up (grow), or down (shrink).
<svg width="300px" height="200px" viewBox="0 0 1500 1000">
The above is telling the browser that you have an SVG that's 1500 x 1000 but you want it to "pinch the corners" and shrink it down to 300 x 200.
viewbox is a ratio
In my humble experience, I've always considered <svg>’s viewbox values as a required image ratio to apply to the width and height values. While defining the laters just I do with any <img> in the DOM, either inline HTML properties or via CSS, viewbox property only applies to the SVG file.