SVG image is not stretching to the size specified - html

I am using an SVG image in my application. I want to stretch the image to fit the viewport by specifying the width and height to it. But, it is not stretching. Please look at the SVG code below.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="none" width="1009" height="577" viewBox="0 0 1009 577">
<defs>
<path id="login-background-b" d="M30,55.176624 L608,55.176624 C624.568542,55.176624 638,68.6080815 638,85.176624 L638,498.176624 C638,514.745167 624.568542,528.176624 608,528.176624 L30,528.176624 C13.4314575,528.176624 0,514.745167 0,498.176624 L0,85.176624 C0,68.6080815 13.4314575,55.176624 30,55.176624 Z"/>
<filter id="login-background-a" width="104.2%" height="105.7%" x="-2.1%" y="-2.9%" filterUnits="objectBoundingBox">
<feMorphology in="SourceAlpha" operator="dilate" radius="1" result="shadowSpreadOuter1"/>
<feOffset in="shadowSpreadOuter1" result="shadowOffsetOuter1"/>
<feGaussianBlur in="shadowOffsetOuter1" result="shadowBlurOuter1" stdDeviation="3.5"/>
<feColorMatrix in="shadowBlurOuter1" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.178895323 0"/>
</filter>
</defs>
<g fill="none" fill-rule="evenodd" transform="translate(9 .823)">
<path fill="#F0EEEF" d="M155.84305,574.219674 C154.077319,574.494565 152.304536,574.722075 150.526612,574.901961 C95.5786682,580.461447 46.5277046,540.42419 40.9682188,485.476246 L-3.41060513e-13,80.5612139 L511.937215,0.86245338 C513.208541,0.664532341 514.484945,0.50072478 515.76505,0.371207178 C555.327569,-3.63162264 590.644263,25.1952017 594.647093,64.7577215 L638.589181,499.065403 L155.84305,574.219674 Z"/>
<use fill="#000" filter="url(#login-background-a)" xlink:href="#login-background-b"/>
<use fill="#FFF" xlink:href="#login-background-b"/>
</g>
</svg>
I have tried so many ways to solve this issue by adding preserveAspectRatio to none and removing view box etc.. Still no luck.
Please help me solve this.
Thank you...

You can achieve what you want from viewBox (reference).
The viewBox specifies which part of your SVG should be shown in the view, it scales the SVG accordingly so that the viewBox specified is the only part visible in the box determined by SVG element (specified by width and height)
In your case when you say
width=1009 height=577 viewBox="0 0 1009 577" whats happening is the view inside rectangle with vertices 0,0, 0,577, 1009,577, 1009,0 is scaled to fit the width 1009 and height 577. Which doesn't change anything as you are giving exact dimensions.
So the part of the SVG you actually want to scale is (from observation)
0,0 to 638.59, 575.42. So if you want that part to scale and fit the view port you should mention the viewBox as viewBox="0 0 638.59 575.42"
PS: The dimensions 638.59 and 575.42 are just based on the outline observation, I didnt go deeper into path, you will know which dimensions to use as you have better understanding of the path

Remove the width inside the SVG file and try
<filter id="login-background-a" width="104.2%" height="105.7%" x="-2.1%" y=

Here is how I would create the desired outcome.
<filter id="grey_blur">
<feColorMatrix type="matrix"
values=".5 0 0 0 0
0 .5 0 0 0
0 0 .5 0 0
0 0 0 1 0 "/>
<feGaussianBlur stdDeviation="12" result="coloredBlur"/>
<feMerge>
<feMergeNode in="coloredBlur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<path id="login-background-a" d="M620.792,2096.222c-6.07,0.979-12.163,1.787-18.273,2.426c-188.864,19.772-357.46-122.613-376.569-318.026L85.136,340.612L1844.741,57.177c4.37-0.704,8.756-1.286,13.157-1.747c135.983-14.235,257.372,88.283,271.129,228.979l151.035,1544.54L620.792,2096.222z"/>
<path id="login-background-b" d="M188.251,250.336h1986.673c56.947,0,103.113,47.766,103.113,106.689v1468.763c0,58.924-46.166,106.689-103.113,106.689H188.251c-56.949,0-103.115-47.766-103.115-106.689V357.026C85.136,298.102,131.302,250.336,188.251,250.336z"/>
<use fill="#eeeeee" href="#login-background-a"/>
<use fill="#ffffff" filter="url(#grey_blur)" href="#login-background-b"/>
The original viewBox has no relationship to anything! When you create an element it should be in reference to the resolution of the document. I only work in 8K as that is currently the highest resolution available and I want all my work to be of the highest quality.
Since very few have access to that kind of digital display device my solution is designed for 4K. The 2381 2160 viewBox values represent 62% width and 100% height of a 4K display. Take the time to learn SVG before you start a project, it will keep you from getting half-way through and pulling your hair out trying to figure out how to finish the project.
If you want it to stretch to fill the viewport add the preserveAspectRatio="none' to the SVG file, although I can't see why you would want to do so.

Related

What are the best practices for images/svgs being used for multple img elements?

I have an asset, asset.svg, that I want to use for several img elements.
Is there anything wrong with only have one svg file that the other img elements reference as the src?
Or should I have a separate svg file to accompany each img element.
Here is a link to a code sandbox with one svg being used as the src for three separate img elements.
code sandbox
a svg file can be used as many times as you need in the src attribute. There's nothing wrong using the same file multiple times.
e.g.
<img class="image-1" src="src/chance.svg" />
<img class="image-2" src="src/chance.svg" />
.image-1 {
// styles here
}
.image-2 {
// styles here
}
Ok here is thing and I have been faced with dilemma my self. I was using one image and wanted different colours to it. Obviously I would have to make two JPGs or PNGs to achieve this but cut throat was load time. I wanted reuse-ability.
if you are using raw SVG in html then you will get cache with rest of page but it wont be reusable other than place it was in placed in code.
<div>
<svg width="33" height="33" viewBox="0 0 33 33" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="chance" filter="url(#filter0_d)">
<rect x="4" width="25" height="25" rx="5" fill="#52A5FF"/>
<rect x="4.5" y="0.5" width="24" height="24" rx="4.5" stroke="#1F8BFF"/>
</g>
<defs>
<filter id="filter0_d" x="0" y="0" width="33" height="33" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
</defs>
</svg>
</div>
But if you use it as image source like you have then it will fetched with http request and cached separate to the html code that fetched it.
Added advantage of this technique is since it would cached separately you can use the power of cache in rest of the pages on site not just parent page it self
<div>
<img src="https://j199m.csb.app/src/chance.svg" />
<img src="https://j199m.csb.app/src/chance.svg" />
<img src="https://j199m.csb.app/src/chance.svg" />
</div>
heck you can even use it as background image - see it repeat it self magic at works
div {
background: url(https://j199m.csb.app/src/chance.svg);
}
<div>hehe haha</div>
Bottom line theory
HTTP caching works based on URLs, and it is “all or nothing” - you can instruct the client to either take the whole resource from cache, or to reload it completely aka hard refresh.
Now, by “inlining” your SVGs, you are making them part of the HTML document - they are not external resources any more, that could individually be checked for whether they can be taken from cache or need to be reloaded, subject to page cache.
So, if you have three HTML documents that all have the same SVG image inlined, the code of the image will be loaded three times - because it is part of the three HTML documents.
So, if you have three HTML documents that all have the same SVG image as external source, the image will be loaded once and then from cache on each request - because it is part of individual cache resource not coupled with rest of html.
if the image was embedded as an external resource (as img, background-image, object, …), it would be loaded only once, on the first of those three HTML pages the browser loads. On the other pages, it will recognize, “hey, that external resource with this particular URL is in my cache already - no need to load it again.
wonderfully stated by this answer https://stackoverflow.com/a/37832616/10588650

SVG: applying a filter on a path doesn't work in Chrome [duplicate]

I have the following SVG document:
<svg preserveAspectRatio="xMinYMin meet" viewBox="0 0 21 484" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="dropShadow">
<feDropShadow dx="4" dy="0" stdDeviation="4"></feDropShadow>
</filter>
</defs>
<g id="Artboard" stroke-width="5" stroke="#FF0000" fill="#000000" stroke-linecap="round">
<path style="filter: url(#dropShadow)" d="M7.5,8.5 L7.5,471.5" id="path-1"></path>
</g>
</svg>
In Firefox, when I open the SVG document, it simply shows a very thin (not 5 wide) vertical line. In Chrome, it doesn't show anything (nor does it in codepen, here: https://codepen.io/jwir3/pen/BJBqEK ).
I'm not quite sure what I'm doing incorrectly here, but it has something to do with the filter, because, if I remove the filter: url(#dropShadow) from the path definition, the line shows up as expected.
You can't use objectBoundingBox units if your shape has no height or width.
Keyword objectBoundingBox should not be used when the geometry of the applicable element has no width or no height, such as the case of a horizontal or vertical line, even when the line has actual thickness when viewed due to having a non-zero stroke width since stroke width is ignored for bounding box calculations. When the geometry of the applicable element has no width or height and objectBoundingBox is specified, then the given effect (e.g., a gradient or a filter) will be ignored.
The default for filterUnits is objectBoundingBox units so you need to change that to userSpaceOnUse i.e.
<svg preserveAspectRatio="xMinYMin meet" viewBox="0 0 21 484" xmlns="http://www.w3.org/2000/svg">
<title>Line Drop Shadow</title>
<description>A red line with 5px width thickness and round caps, having a drop-shadow. This highlights the regression documented in PURP-1017.</description>
<defs>
<filter id="dropShadow" filterUnits="userSpaceOnUse">
<feDropShadow dx="4" dy="0" stdDeviation="4"></feDropShadow>
</filter>
</defs>
<g id="Artboard" stroke-width="5" stroke="#FF0000" fill="#000000" stroke-linecap="round">
<path style="filter: url(#dropShadow)" d="M7.5,8.5 L7.5,471.5" id="path-1"></path>
</g>
</svg>
When processing filters, different browsers process in different stroke.
Chrome considers stroke as a value with a zero pixel, so it does not include it in the filter region.
Therefore, to make the result look the same in different browsers, it is better to replace path with stroke-width ="5", a rectangle with a width of 5px withoutstroke (stroke="none")
In addition, the default values for the filter area are: x =" - 10% "" y = "- 10%" `` width = "120%" `` height = "120%"- large blur sizes are usually truncated .
By default, filterUnits = "objectBoundingBox" and therefore the values are specified in percentages.
To make it easier to calculate the size of the filter region action, specify the value offilterUnits = "userSpaceOnUse" and then you can specify all dimensions for thefilter region` in pixels.
<svg preserveAspectRatio="xMinYMin meet" width="100%" height="100%" viewBox="0 0 21 484" xmlns="http://www.w3.org/2000/svg" >
<defs>
<filter id="dropShadow" filterUnits = "userSpaceOnUse" x="4" y="0" width="12" height="472">
<feDropShadow dx="6" dy="4" stdDeviation="3"></feDropShadow>
</filter>
</defs>
<g id="Artboard" fill="#FF0000" filter="url(#dropShadow)" >
<!-- <path style="filter: url(#dropShadow)" d="M7.5,8.5 L7.5,471.5" id="path-1" stroke-width="5" ></path>-->
<rect x="5" y="5" width="5" stroke="none" height="463" />
</g>
</svg>
Swapping to userSpaceOnUse is the correct answer in most circumstances but has the following limitations:
The filter effects region will apply from -10% to 120% of the canvas, rather than the bounding box of the element (using more memory and processing time)
For large dynamic SVGs (such as created by d3) it can be hard to calculate the required filter x/y/width/height to ensure the filter applies to all elements.
An alternate (less elegant) solution is to apply the filter to a <g> and use a hidden node within this to give the group the correct width or height:
<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="dropShadow" width="20">
<feDropShadow dx="4" dy="0" stdDeviation="4"></feDropShadow>
</filter>
</defs>
<g id="Artboard" style="filter: url(#dropShadow)">
<circle r="5" cx="0" cy="0" visibility="hidden"></circle>
<path d="M10,10 L10,100" stroke-width="5" stroke="#FF0000" fill="#000000" stroke-linecap="round"></path>
</g>
</svg>

The shape change when the window decrease with svg

I'm currently working on a website and I need help on a svg trapezoid shape.
I decided to use SVG because, before that, my trapezoid was realized with css and the main problem with that is that is wasn't responsive as I expected.
This is the shape I would like : Trapezoid.
I've already realized this shape but the problem is when the window size decrease the shape look like that.
So my question is, does there any ways to "lock" the points to keep the shape of the 1st image ?
HTML :
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="84%" height="200" preserveAspectRatio="none">
<polygon fill="blue" points="1.5 0, 100 0, 85 100, 1.5 100"/>
...
</svg>
Edit:
Thanks to Paulie_D, i've patched my problem with :
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100%" height="200" preserveAspectRatio="xMaxYMin slice" class="spaceBetweenButton" >
<polygon fill="#00a8f3" points="1.5 0, 100 0, 0 100, 1.5 100"/>
...
</svg>
But now I would like to add another trapezoid at the right of the 1st like that but as before, my problem isn't on how to realize the shape but on how it render with this code :
<div class="col-md-2 col-xs-12">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100%" height="200" preserveAspectRatio="xMaxYMin slice" transform="rotate(180)" class="spaceBetweenButton">
<polygon fill="#00a8f3" points="0 0, 130 0, 0 130, 0 130" />
</svg>
</div>
And how it appear. At first sight I thought that the problem was in the preserveAspectRatio so I've tried to replace it by xMaxYMin slice off but I didn't found a way to have a decent result with it.
So I have 2 problem, how to extend the right trapezoid (I think it's with the width of the svg) and how to move it on the left. I've tried to add margin but the space between the 2 trapezoid changes when we resize the window.
Thanks for your help.
Valentin.
Just add another polygon to your SVG.
Move the right hand end of the first polygon left a bit
Add a second polygon of the right shape, to the right of that, leaving an appropriate gap.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100%" height="200" preserveAspectRatio="xMaxYMin slice" class="spaceBetweenButton" >
<polygon fill="#00a8f3" points="0 0, 83 0, 0 83"/>
<polygon fill="#00a8f3" points="85 0, 100 0, 100 100, 0 100, 0 85"/>
</svg>

SVG Rounding Bug

Chrome's way of rounding sub-pixel values in SVGs creates a problem for me.
Is there any way to fix this problem? Because I use opacity I'm not able to simply add a dark background to remove the white glimps.
Here's the example:
http://dabblet.com/gist/766f6a238d00bcbb41d4
You can create a filter to add "grout" into the gap :) But it's a hack that works by increasing the opacity of those pixels. It will also roughen up the anti-aliasing of our other edges. Also if you're using opacity in these gradients then you will need to adjust those tableValues below to the range that you want (aka if your fill is 0.4 opacity, then your tableValues would look like "0 .1 .4 .4 .4"). If you have variable opacity in your gradients, then you can play around with other types of component transfers that will preserve the opacity gradients better.
<svg id="background-svg" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 150 75" >
<defs>
<linearGradient y2="1" x2="1" y1="0" x1="0" id="triangleGradient">
<stop stop-color="black" offset="0"/>
<stop stop-color="blue" offset="1"/>
</linearGradient>
<filter id="mynameisgrout">
<feComponentTransfer>
<feFuncA type="table" tableValues="0 .25 1 1 1"/>
</feComponentTransfer>
</filter>
</defs>
<g filter="url(#mynameisgrout)">
<polygon points="0,75 100,75 50,0" fill="url(#triangleGradient)"></polygon>
<polygon points="50,0 150,0 100,75" fill="url(#triangleGradient)"></polygon>
</g>
</svg>
The SVG shape rendering option allows to configure what's important for rendering.
In this case shape-rendering="crispEdges" solves the problem.
See https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering

SVG path not observing aspect ratio

I'm having trouble getting the SVG path to scale to its container:
<svg xmlns="http://www.w3.org/2000/svg"
preserveAspectRatio="xMidYMid"
viewBox="0 0 16 16"
width="16"
height="16">
<path stroke="#000" fill="none" d="M209,15a195,195 0 1,0 2,0zm1,0v390m195-195H15M59,90a260,260 0 0,0 302,0 m0,240 a260,260 0 0,0-302,0M195,20a250,250 0 0,0 0,382 m30,0 a250,250 0 0,0 0-382"></path>
</svg>
Demo: http://jsfiddle.net/FeTv2/1/ - As you can see the path is way too big, and seems to have a top and left offset.
Looks the same in Chrome and Firefox.
The viewBox of you SVG is way too small to fit the path you're using. The viewBox represents the part of your SVG, that should be shown. The width and height the represent the dimension of the box, in which the content is shown.
Try a viewBox size, that really fits your path like this (may need further adjustments):
<svg height="16" width="16"
viewBox="0 0 450 450"
preserveAspectRatio="xMidYMid"
xmlns="http://www.w3.org/2000/svg">
<path d="M209,15a195,195 0 1,0 2,0zm1,0v390m195-195H15M59,90a260,260 0 0,0 302,0 m0,240 a260,260 0 0,0-302,0M195,20a250,250 0 0,0 0,382 m30,0 a250,250 0 0,0 0-382" fill="none" stroke="#000"/>
</svg>
Additionally, you may (or may not) want to adjust the size of the <svg> element.
Example Fiddle (big <svg>)
Example Fiddle (16x16 <svg>)