SVG scales down to fit small screen height, why? - svg

I have a simple SVG in a web page, and I'd like the SVG to be responsive to width only. The problem is, it scales down also when the screen height is less than the SVG height.
HTML:
<div class="container">
<svg version="1.1" width="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500" preserveAspectRatio="xMinYMin">
<circle stroke="#000" stroke-width="10" fill="transparent" cx="250" cy="250" r="200"/>
</svg>
</div>
CSS:
svg {
max-height: 100%;
}
.container {
width:50%;
border: 1px solid black;
}
Here is the jsfiddle, where you can see the circle radius decreases when the window height is reduced. How can this be avoided ?
Thanks !

Here is what I wanted to achieve, sorry if my question wasn't clear enough:
width of the SVG depending only on the width left available to the container,
(width / height) ratio of the SVG preserved at all time,
container's height depending only on the width of the SVG and its (width / height) ratio.
I got it working this way:
HTML & SVG:
<div class="container">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 500 400" preserveAspectRatio="xMinYMin">
<circle fill="#F7941E" stroke="#231F20" stroke-width="10" cx="250" cy="200" r="150"/>
</svg>
</div>
<hr>
CSS:
.container {
position: relative;
width:50%;
padding-bottom: 40%;
border: 1px solid black;
}
svg {
position: absolute;
top: 0;
left: 0;
max-height: 100%;
}
Fiddle here
The only drawback I see is that the padding-bottom of the container needs to be defined, and to a value matching the w/h ratio of the SVG, which is redundant.

If what you want is for the circle to remain the same size even when the window size changes, then just get rid of the viewBox. Try removing : viewBox="0 0 500 500" preserveAspectRatio="xMinYMin" from the opening svg tag.

The default for height (like width) is 100%. Which means 100% of it's container height.
One solution is to give the container a very large height.
.container {
width:50%;
height: 9999px;
border: 1px solid black;
}
Fiddle here
You don't really say what you want to happen to the lower parts of the circle when the height scales up. If you want it to be hidden off the bottom of the div container, then you could do something like this:
svg {
height: 9999px;
}
.container {
width:50%;
height: 300px;
overflow: hidden;
border: 1px solid black;
}
Fiddle here

Related

SVG - stroke-dasharray with percentage units doesn't work as expected

I think I don't quite understand something here.
Percentage units in stroke-dasharray are realtive to what? I was thinking relative to the SVG viewbox, but I was probably wrong.
My problem:
I have an SVG with the width of 320px and the height of 160px.
In this SVG I draw a line from x1 = "0%" to x2 = "100%", so it has a width of 320px just like the SVG.
Then I give the line: stroke-dasharray: 100% 100%;
For me it is surprising that the line is not drawn with the full width of the SVG, but only about 80%.
I think I don't quite understand something here.
Pronounced units in stroke-dasharray are realtive to what? I was thinking relative to the SVG viewbox, but I was probably wrong.
My problem:
I have an SVG with the width of 320px and the height of 160px.
In this SVG I draw a line from x1 = "0%" to x2 = "100%", so it has a width of 320px just like the SVG.
Then I give the line: stroke-dasharray: 100% 100%;
For me it is surprising that the line is not drawn with the full width of the SVG, but only about 80%.
If someone has an idea, I would be happy to hear from you
Here the link to an example: https://codepen.io/stefka1210/pen/xxVwBom
html, body {
width: 100%;
height: 100%;
}
body {
display: flex;
align-items: center;
justify-content: center;
}
.container {
width: 320px;
height: 160px;
background: lightgrey;
}
svg {
width: 100%;
height: 100%;
}
line {
stroke-width: 2px;
}
#one {
stroke-dasharray: 100% 100%;
stroke: red;
}
#two {
stroke-dasharray: 320px 320px;
stroke: green;
}
<html>
<body>
<div class="container">
<svg x="0px" y="0px" viewBox="0 0 320 160" xmlns="http://www.w3.org/2000/svg">
<g>
<line id="one" x1="0%" y1="40%" x2="100%" y2="40%"></line>
<line id="two" x1="0%" y1="60%" x2="100%" y2="60%"></line>
</g>
</svg>
</div>
</body>
</html>
Since a line can go in any direction, it would not make sense to link "percentage of the viewport" to either its width or height. Instead, 100% is set to the root mean square of width and height:
For width = 320 and height = 160, that gives a length of 252.98.

Rounded rectangle with stroke -- svg quality compared to div

I understand that there is a different render process, but why is the stroke so funky on rounded rectangles compared to a rounded div with a border?
body {
background: #1a1a1a;
display: flex;
justify-content: center;
padding-top: 50px;
}
.svg-square {
fill: #75604A;
stroke: white;
stroke-width: 1px;
}
.div-square {
background-color: #75604A;
margin-left: 10px;
width: 60px;
height: 60px;
border: 1px solid white;
border-radius: 10px;
}
span {
display: block;
margin: 20px;
color: white;
}
<span>svg</span>
<svg width="60" height="60">
<rect class="svg-square" width="60" height="60" rx="10" />
</svg>
<div class="div-square"></div>
<span>div</span>
FIDDLE: https://codepen.io/kirkbross/pen/gEGGvx
It seems like it's a half pixel stroke on the svg and even when I increase it to 2, the sides seem thinner than the top and bottom.
I want to understand the physics here. This example is an svg with a stroke of 1. These corners seem janky compared to a div with a border.
Well part of it is that you're cutting off half the stroke-width because your rect is exactly the size of your svg element. Look at:
<rect x="1" y="1" class="svg-square" width="58" height="58" rx="10" />
Still not as good at rounded corners as CSS drawing - but much more reasonable.

Clip-Path vs Border-Radius issue when window is resized

I want to use an SVG as a clip-path to round the edges of an image. Yes, I must do it in this way for various reasons .
PROBLEM:
When the browser window is resized, the points and handles that form the rounded corners adjust to the changing size of the image (bounding box) because I'm using clipPathUnits="ObjectBoundingBox". This causes the rounded edges to loose their "roundness" and look overall really bad. The CSS border-radius property doesn't have this issue. No matter how you resize the browser window, the edges of a div clipped with border-radius never loose their round shape. The problem is most apparent when you resize the browser window to it's most narrow or widest possible state. Try that with this codepen and you'll see what I mean. The top image uses border-radius and the bottom image uses clip-path. Is there any way to force the ONLY rounded edges of the SVG clip-path to stay equally rounded no matter how the image is resized without sacrificing the responsiveness of the clip-path dimensions? Is this even possible? I'm totally open to a JavaScript solution if there is one. Thanks!
You can trick the <svg> element to have just the same dimensions as the image and then size the clip-path with relative units. The downside is that you cannot reuse these paths but have to define one for every individual image.
.box {
left: 5%;
height: 40%;
position: absolute;
background-color: blue;
overflow: hidden;
}
#box1 {
top: 5%;
width: 50%;
clip-path: url(#clipPath1);
}
#box2 {
top: 55%;
width: 90%;
clip-path: url(#clipPath2);
}
.flower{
width: 100%;
height: 100%;
object-fit: cover;
object-position: center;
}
svg {
width: 100%;
height: 100%;
position: absolute;
}
<div class="box" id="box1">
<img class="flower" src="https://images.pexels.com/photos/67636/rose-blue-flower-rose-blooms-67636.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" alt="none">
<svg>
<clipPath id="clipPath1" clipPathUnits="userSpaceOnUse">
<rect width="100%" height="100%" rx="20" ry="20"/>
</clipPath>
</svg>
</div>
<div class="box" id="box2">
<img class="flower" src="https://images.pexels.com/photos/67636/rose-blue-flower-rose-blooms-67636.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" alt="none">
<svg>
<clipPath id="clipPath2" clipPathUnits="userSpaceOnUse">
<rect width="100%" height="100%" rx="20" ry="20"/>
</clipPath>
</svg>
</div>

Responsive inline svg?

This SVG icon is 640x640px. The toolbar is 48px high.
The icon should now automatically adjust to the height of the toolbar.
Accordingly, the blue area would have to be 48x48px.
However, the icon now occupies much more space than it needs.
I gave the svg a height of 48px. Better would be height: 100% but that does not work.
my codepen
Changing only the height to 48px leaves the width at 640px. Because you have width="640px" specified on your <SVG>.
So the fix is simply to remove the width and height attributes from <svg>.
body {
margin: 5%;
}
.toolbar {
position: realive;
color: #fff;
display: flex;
align-items:center;
justify-content: space-between;
background: red;
height: 48px;
}
.toolbar__section.flex-grow {
flex-grow: 1;
}
.toolbar__section.bg-green {
background: green;
}
svg {
display: flex;
height: 48px;
background: blue;
}
<p><strong>Responsive inline svg?</strong></p>
<p>
This SVG icon is 640x640px. The toolbar is 48px high.
The icon should now automatically adjust to the height of the toolbar.
Accordingly, the blue area would have to be 48x48px.
However, the icon now occupies much more space than it needs.
I gave the svg a height of 48px. Better would be "height: 100%" but that does not work.
</p>
<div class="toolbar">
<div class="toolbar__section bg-green flex-grow">
Logo
</div>
<div class="toolbar__section">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640" preserveAspectRatio="xMinYMin meet">
<title></title>
<g id="icomoon-ignore">
</g>
<path fill="#000" d="M603.794 613.188l-190.189-207.478c42.858-44.846 66.395-103.468 66.395-165.71 0-64.106-24.964-124.375-70.294-169.706s-105.6-70.294-169.706-70.294-124.375 24.964-169.706 70.294-70.294 105.6-70.294 169.706 24.964 124.376 70.294 169.706 105.6 70.294 169.706 70.294c55.226 0 107.595-18.542 150.027-52.655l190.178 207.467c3.156 3.442 7.471 5.188 11.799 5.188 3.862 0 7.736-1.391 10.808-4.205 6.513-5.972 6.954-16.093 0.982-22.607zM32 240c0-114.691 93.309-208 208-208s208 93.309 208 208-93.309 208-208 208-208-93.309-208-208z"></path>
</svg>
</div>
<div class="toolbar__section bg-green">
Login Icon
</div>
</div>
Delete the width attribute from the svg element. You may have to adjust the flex-grow attributes in your toolbar afterwards.
See it live on CodePen.
Tested on Chrome 63.0.3239.132

svg image not working in safari 5.1.7 (windows)

svg image not working in safari 5.1.7 (windows) . But when i open the svg image in safari and then visit the site, the image is displayed there.
Safari on Windows has known issues calculating the height of responsive inline SVGs.
You might try the intrinsic ratio technique, whereby you position the <svg> tag absolutely inside an <object> tag with bottom padding equal to the ratio of the viewBox (or height/width attributes) of the svg.
.my-responsive-svg {
width: 100%;
display: block;
height: auto;
position: relative;
/* for an svg with a 16:9 aspect ratio */
padding-top: 56.25%;
}
.my-responsive-svg svg {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
right: 0;
}
<object class="my-responsive-svg">
<svg width="160" height="90" viewBox="0 0 160 90">
<rect x="10" y="10" width="140" height="70" />
</svg>
</object>
Source: Hat tip to Sérgio Lopes who commented on this blog post.

Resources