Is viewbox in SVG important? - html

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>

Related

How to remove padding from font library svg files

I am using Flaticon font library, which is really useful, since you can include svg images via the i tag and change their color and size via css.
Flaticon Font Documentation: https://www.flaticon.com/iconfonts
For some reason their svg icons are bigger than needed and have invisible space between them.
If I want to have a perfect design, I have to use margin with negative values, which is pretty annoying.
Is there something that I can do inline in order to make the size of the i element the same as the icon vector without the invisible space?
Update:
It seems like the spacing is intentional: https://gyazo.com/90f1b8f986bea7a00e8efeea52c24cdd
SVG icons normally have some whitespace around them. On of the reasons is because sometimes icons have to have different physical sizes in order to look optically similar in size.
Consider this square and a circle.
<svg viewBox="0 0 200 100" width="400">
<rect x="20" y="20" width="60" height="60" fill="grey"/>
<circle cx="150" cy="50" r="30" fill="grey"/>
</svg>
Note how they are the same phical size, but the circle does not have the same "physical presence" as the square.
But if we make the circle a little bigger, they now look better. They appear to match in size despite being physically different sizes.
<svg viewBox="0 0 200 100" width="400">
<rect x="20" y="20" width="60" height="60" fill="grey"/>
<circle cx="150" cy="50" r="35" fill="grey"/>
</svg>
How to adjust the padding
Most SVG icons have a viewBox attribute that tells the renderer what the important area of the SVG is. The renderer needs to know which area of the SVG canvas to scale up or down when you make an SVG bigger or smaller.
I don't know for sure that the Flaticon ones have a viewBox. But I'm going to assume that they do.
You can alter the padding in your icons by adjusting the viewBox dimensions. Contracting the viewBox in towards the icon shape will reduce the padding. But consequently it will make the icon appear bigger if you don't also reduce the display size of the SVG (ie the width and height of the SVG - or it's container).
Unfortunately you cannot alter the viewBox attribute via CSS. So you will have to edit the actual SVG file.
You can read more about the viewBox attribute in the SVG Specification. If that's hard to follow, you will be able to find other good viewBox tutorials. Here is a good one by Sara Soueidan.
Note: The reason I included the first section of this answer was to explain why the padding was there, and why it is useful. If you do alter your icons by reducing the viewBox, my recommendation would be to try and make the same change on all icons. Otherwise they may end up looking like they are all different sizes.

How do I scale an SVG to adjust with screen size? [duplicate]

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.

Why does the 'use' tag size not match the svg element it references?

Looking at the following code snippet, I would expect the svg element referenced by "use" to be constrained within a 100px wide and 100px tall box:
body {
background: blue;
}
.svgautohide {
display: none;
}
<body>
<div style="height:100px;background:red">
<svg><use xlink:href="#icontest"></use></svg>
</div>
<svg width="100px" height="100px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" style="svgautohide">
<defs>
<symbol id="icontest">
<rect x="0" y="0" width="100" height="100" />
</symbol>
</defs>
</svg>
</body>
However, this is not what I'm seeing, as the screenshot below illustrates:
This doesn't appear to be a browser bug, as the same behaviour was replicated across Firefox, Edge and Chrome. Can anyone help explain why the "use" box is a different size to the svg? Also, can anything be done to override this behaviour? Thanks.
You need to set a width and height for the referencing <svg>.
Both <svg> elements and <symbol>/<use>/ combinations provide a mechanism for fitting one area inside another:
For <svg>, the viewBox area is fitted inside the box defined by width and height.
For <use>, the viewBox area defined for the <symbol> is fitted inside the box defined by x, y, width and height of the <use>.
For both, if no viewBox is given, content remains at original size. A missing x or y defaults to 0. A missing width or height defaults to 100%. Percentages are defined in relation to the viewport, that is the size of the viewBox of the next outer <svg> (or the size of the svg itself, if it is missing).
In contrast, if the <svg> is the outermost in a HTML page, width and height are presentation attributes with a default value of auto. They are resolved within the CSS cascade and following its rules for inline-block elements. If finding a concrete size fails, the default object size comes out at 300px * 150px:
Otherwise, if height has a computed value of auto, but none of the conditions above are met, then the used value of height must be set to the height of the largest rectangle that has a 2:1 ratio, has a height not greater than 150px, and has a width not greater than the device width.

Why does the svg path change size when inside a clipPath element?

I have a svg path that I am trying to use as a clip mask. When I add the svg path to an svg element, its size lines up with the image I want to clip. However, If I copy and paste the same path into a clipPath element, it changes size. In the code below you can see that the same path is used to draw an svg and in a clipPath. The drawn path is the correct size, however the clipPath is larger.
<svg id="clip-svg" viewBox="0 0 374 518">
<path d="M374,0l-41.7,492.3c0,0-61.6,25.7-143.3,25.7S41.7,492.3,41.7,492.3L0,0C12,16.1,366.2,17.7,374,0z"/>
<defs>
<clipPath id="clip-path">
<path d="M374,0l-41.7,492.3c0,0-61.6,25.7-143.3,25.7S41.7,492.3,41.7,492.3L0,0C12,16.1,366.2,17.7,374,0z"/>
</clipPath>
</defs>
</svg>
Why is the path changing size when placed in the clipPath?
You don't say, but I assume you are clipping an HTML element?
When a clipPath is used outside of the SVG, it is not longer subject to the scaling that happens due to the viewBox. So it will be used, as defined, at 1:1 scale.

SVG viewbox always relative to it's size?

A pretty simple example if I have this square SVG:
<svg class="svg-correct-symbol" viewBox="0 0 442.533 442.533"
width="50px" height="50px">
And I change it to:
<svg class="svg-correct-symbol" viewBox="0 0 200 200"
width="50px" height="50px">
I will see about a quarter of the image right? Because the width and height is halved of the window(viewbox) you are 'looking through' to view the SVG.
So the viewbox's number: 442.533 will always mean 100% of the images width/height.
How it this default viewbox number set? Is this viewbox size determined by how large the file is when you export it? I would like to have a viewBox of something more rounded like viewBox="0 0 16 16".
With an already exported image I don't see a way to change it though.
There is no default viewBox number. It is defined at the time the svg image is created (manually or by using software, like illustrator). It has 4 co-ordinates x y width height. What makes it tricky is that these coordinates have nothing to do with the image dimension and, like you mentioned, it only defines the area you are "looking through".
You can set the viewbox to any values you want. But you will also need to scale the svg image accordingly to fit your new viewbox. Similarly, you might also need to translate / shift the images in the x , y axis to bring it to centre or to fit the frame / viewbox.
Check out svg transform from the documentation.
This tutorial might also be useful to understand svg transforms.
And in case you are using a software like illustrator, all you need to do is set the dimension of the artboard which defines the viewbox and then scale accordingly.