CSS SVG ClipPath - Fit path to height - html

The task
I'm trying to have an image which is the full height of the screen, and clipped with an SVG mask, which is also full height.
The problem
Although the image is full height, the SVG clipping is always the same size and will not resize to the full height of the image.
I've read about using: clipPathUnits="objectBoundingBox"
on the clipPath, but this seems to break it further.
CSS:
img {
position: absolute;
clip-path: url(#path);
-webkit-clip-path: url(#path);
width: 100%;
height: 100%;
}
HTML:
<div>
<svg width="0" height="0" xmlns="http://www.w3.org/2000/svg" version="1.1" preserveAspectRatio="xMidYMid meet" viewBox="0 0 200 440">
<defs>
<clipPath id="path">
<path d="m54.3,1c64,1 89.3,85 89.8,85.6c1,0.4 7,37 19,53.7c11.8,16.6 30.7,28.5 35,33.8c4.3,6 9,8 4.8,17s-18.8,7 -24.8,20c-6,13.7 7.5,11 8.6,22c1,11 -31.2,14 -29.6,27c1.4,13 22.4,12 24,23c1.5,11.6 -9,10 -13,18c-3.8,8 15.6,20 5,38c-11,18.5 -57.7,7 -84,32.5c-26.4,25.3 -35.5,70 -34.4,70.4c1,0.4 -64,3 -61.8,-1c2.1,-4 -4.9,-440 2.1,-440s-4.6,-1 59.4,0l-0.1,0z"/>
</clipPath>
</defs>
<img src="https://upload.wikimedia.org/wikipedia/commons/0/05/20100726_Kalamitsi_Beach_Ionian_Sea_Lefkada_island_Greece.jpg">
</svg>
</div>
jsFiddle showing problem - https://jsfiddle.net/kjnovege/1/
Is there any way to achieve this?

Related

SVG Path is crawling / climbing up the page when screen size is small

I have an SVG on my page. This SVG is a white wave that creates a nice wave effect on the hero image for the page. But the SVG's Path (drawing) crawls up the page when the screen width decreases, creating a gap between itself and the hero image.
How do I align this SVG Path so it stays on the bottom?
.wave {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
border-radius: none;
}
<svg
height="100%"
width="100%"
id="svg"
viewBox="0 0 1440 1"
xmlns="http://www.w3.org/2000/svg"
className="wave"
>
<path
d="M 0,400 C 0,400 0,200 0,200 C 153.19999999999993,213.06666666666666 306.39999999999986,226.13333333333335 449,220 C 591.6000000000001,213.86666666666665 723.6000000000001,188.53333333333333 887,182 C 1050.3999999999999,175.46666666666667 1245.1999999999998,187.73333333333335 1440,200 C 1440,200 1440,400 1440,400 Z"
stroke="none"
stroke-width="0"
fill="#ffffff"
></path>
</svg>
Here is an image of what is happening.
The size and scale of the viewbox (& graphics inside) is controlled by the preserveAspectRatio attribute on the svg.
By default, the viewbox is scaled uniformly to fit the size of the svg and centered horizontally and vertically. (Similar to how a background image would display with the following properties applied: background-position: center center; background-size: contain;)
This is why your path 'crawls up', the svg is positioned at the bottom of the hero but its contents is centered.
The preserveAspectRatio accepts two values, first is alignment, second (optional) is how it 'fits' inside the svg.
preserveAspectRatio="<align> [<meetOrSlice>]"
The mdn page about preserveAspectRatio is really helpful and gives a full list of examples. https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/preserveAspectRatio
tldr:
To fix your issue, add preserveAspectRatio="xMidYMax meet" as an attribute of the SVG, EG:
<svg
height="100%"
width="100%"
id="svg"
viewBox="0 0 1440 234"
xmlns="http://www.w3.org/2000/svg"
className="wave"
preserveAspectRatio="xMidYMax meet"
>
...
</svg>
NB: The viewBox’s height needs to be big enough to contain the graphics, so has been increased. Kudos: Sphinxxx & enxaneta.

How to scale SVG coordinates in the range 0 and 1?

I've been having issues scaling the inline SVG, in order to clip-path it in CSS, in the example to the container of the image that I'm trying to show.
I've seen the other similar questions with solutions but they still don't work as intended:
<style>
.cutR{
clip-path: url(#cutR)
}
.blogMainArticleMedia{
float:left;
width:100%
}
.image{
float:left;
display:block;
width:100%
}
</style>
<div class="blogMainArticleMedia cutR">
<img src="https://images.pexels.com/photos/459225/pexels-photo-459225.jpeg" alt="image" class="image">
</div>
<svg width="0" height="0" preserveAspectRatio="none">
<defs>
<clipPath id="cutR" clipPathUnits="objectBoundingBox">
<path d="M0,0c1.45,81.4 320,80 320,80l320,0l320,0c0,0 320,0.62 320,80c0,105.84 0,400 0,400c-1.45,81.4 -320,80 -320,80l-640,0c-171.919,0.239 -319.7,-0.491 -320,80l0,-720Z"
style="fill:none;" />
</clipPath>
</defs>
</svg>
https://codepen.io/thepra/pen/wNdpXW
They suggest to scale the coordinates of the path to a range between 0 and 1, but I can't find any software option(Affinity Designer) or online tool to do such thing.
Did anyone solved this scaling issue?
ps: here's the shape of the path
You don't need to do anything to the coordinates of the path. Instead, just transform the scale of the <clipPath>.
The path you want to use as your clipPath is 1280 x 670, so just apply the equivalent scale (1/1280, 1/670). This gives:
transform="scale(0.00078125, 0.001492537313433)"
This along with clipPathUnits="objectBoundingBox" means that you can use this shape to clip at any size or aspect ratio.
.cutR {
clip-path: url(#cutR)
}
.blogMainArticleMedia {
float: left;
width: 100%
}
.image {
float: left;
display: block;
width: 100%
}
<div class="blogMainArticleMedia cutR">
<img src="https://images.pexels.com/photos/459225/pexels-photo-459225.jpeg" alt="image" class="image">
</div>
<!-- Viewbox has no effect -->
<svg viewBox="0 0 1280 670">
<defs>
<clipPath transform="scale(0.00078125, 0.001492537313433)" id="cutR" clipPathUnits="objectBoundingBox">
<path d="M0 0C1.45 75.8834 320 74.5783 320 74.5783H960C960 74.5783 1280 75.1563 1280 149.157V522.048C1278.55 597.932 960 596.627 960 596.627H320C148.081 596.849 0.3 596.169 0 671.205V0Z"/>
</clipPath>
</defs>
</svg>
Codepen

Scaling svg to set width (px) & auto height

I seem to not understand svg. I would like someone to explain to me where I am going wrong. So I have an inline svg:
<div style="width:1000px; height:auto; background-color:blue;">
<svg class="_image"><use xlink:href="#myId" />
<symbol id="myId" viewBox="0 0 1000 700">
<ellipse cx="200" cy="80" rx="100" ry="50"
style="fill:yellow;stroke:purple;stroke-width:2" />
</symbol>
</svg>
</div>
The width of the div is set to 1000px. The svg is set to a 100% width. It has a viewBox. I would now expect the svg to scale 100% in width, which means 1000px in width, and then adjust the height accordingly since it is set to auto both for the div and for the svg itself. I expect this, since I provided a viewbox. Where am I going wrong?
Here is the css:
._image {
width: 100%;
height: auto;
}
...and everything put together as a fiddle: https://jsfiddle.net/hv6ejn98/2/
The svg is set to a 100% width. It has a viewBox.
No it doesn't. Only your <symbol> does. Without a viewBox your SVG won't scale. If you add a viewBox to the SVG, everything works as you expect.
<div style="width:1000px; height:auto; background-color:blue;">
<svg class="_image" viewBox="0 0 1000 700"><use xlink:href="#myId" />
<symbol id="myId" viewBox="0 0 1000 700">
<ellipse cx="200" cy="80" rx="100" ry="50"
style="fill:yellow;stroke:purple;stroke-width:2" />
</symbol>
</svg>
</div>

scaling an SVG over an image that resizes without jquery

lets suppose I have an image of dimensions 1280x720
I have some polygons that are computed by a server on top of the original sized images that need to be drawn on top of this image. They are
<polygon points="531,243,687,316,663,593,360,717,191,520" />
<polygon points="275,17,422,45,412,312,271,235" />
<polygon points="929,180,1108,248,985,707,847,676" />
<polygon points="598,70,700,101,658,531,516,436" />
Now I need to display the image and overlay these polygons on top of it. The problem however is that the image is scaled by the browser depending on the window size, which is dynamic. The image is displayed using object-fit-contain CSS so the size changes as I resize.
How do I ensure the SVG co-ordinates above auto scale?
I've read about viewBox but I'm not really looking to specify my own co-ordinates here. The issue is I don't really know how the image will be displayed/sized by the browser as it will depend on the window.
thanks
The default scaling behaviour of SVGs is the same as object-fit: contain. So all you should need to do is set the SVG's viewBox width and height to the same dimensions as the image.
So, for instance, if your image is 640x480, set your viewBox to "0 0 640 480".
div {
position: relative;
}
div > img,
div > svg {
width: 100%;
height: 200px;
}
img {
object-fit: contain;
}
svg {
position: absolute;
top: 0;
}
<div>
<img src="http://lorempixel.com/output/people-q-c-640-480-1.jpg"/>
<svg viewBox="0 0 640 480">
<circle cx="450" cy="215" r="40" fill="none" stroke="red" stroke-width="10"/>
</svg>
</div>
Could you avoid doing this with html in any way? A simple image editor seems like a better way of doing this, but I can't say because I don't know your circumstances. Otherwise you could probably use margin for the placement.
You can use <image> element inside the <svg> tag, then they will become one, you can do any scale with it.
Here is an SVG image example:
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<rect x="10" y="10" height="130" width="500" style="fill: #000000"/>
<image x="20" y="20" width="300" height="80"
xlink:href="http://jenkov.com/images/layout/top-bar-logo.png" />
<line x1="25" y1="80" x2="350" y2="80"
style="stroke: #ffffff; stroke-width: 3;"/>
</svg>
Reference: SVG image element

SVG full Width, while keeping img proportions

I've got an svg image which I want to autoresize to 100% width.
The problem is, that I've placed an Image (100px x 100px) on the left side of that svg and that picture has to keep its proportions.
I tried it with viewBox, but with this method the whole svg, and not only the path, gets resized.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 600 100" preserveAspectRatio="none" style="-webkit-user-select: auto;">
<g>
<title>title</title>
<image x="0" y="1.00001" width="100" height="100" id="svg_1" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3goUDAEUe/ATzgAAAkNJREFUeNrtnetugkAQRr8hJH3/tzWt7PRHxQuyN4qw6DlJo7GK7Jy9zdBQkxS0DJPkl0e44ZPYVMVo/AA0QkcIEAIIQQggBCGAEIQAQhAypvtk7A0wVzqhPtWYENiRnhBU4QWdu/SREVIQ7Np4eIGU1Pe4bpc/XJL39O6H33kigKnjWOYYc8d0SYOks6Sfy0/oF/aCIwW89HWfPO9merMSvT62IYq9dv/8W9JJ0qkvbKQ1OLXkgloiJLXLnLbdIlNTbrqyzDIRJH2N0o+2hnjlSPbKxVcrvL+2PePUNUgajiLEC4OlfwZsrxzsOuW1LGTt3khiCPVQXEQIIAQhgJA3oala1t2Wb0mhb6tTbG7b65mEzUoacF9XeHpT12kIYdgwwLaXgP8IydV8Hhpgk8bEsrtoRMw0uJ8nyWG4TLNBZdcdUh3FWhCwVEhp0c5iMnKtjUXHzRTcBy274FMS9FaqAP7XDZfP075WDyupj/h660nT5RhKJ2x7ASEIAYQgBBDyASytZXks+atJ/GqTHIRUxCn2dzmGhKdsXIniRd/KWb5RwEsmClt7yio+C4+MljcdDVYzGmIHoHTCLgsQghBACEIAIQgBhCAEEAIIQQggBCGAEIQAQhACCAGEIAQQghBACEIAIQgBhABCEAIIQQggBCGAEIQAQgAhCAGEHBT+bd4LuNyNwTPvud7ZwZ8/CxvxcCvYuVuNvFRI6sYf0MAagowd1hBbWYR9mOBNpixGRiNCgDwEIYAQhABCEAIIAYS0zy9dWbdrK07bIAAAAABJRU5ErkJggg=="/>
<path style="-webkit-user-select: auto;" stroke="#000000" fill="#FF0000" stroke-width="0" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="null" d="m98.66982,67.61566c0,0 136.5026,-1.32306 303.78312,-30.42615c167.28064,-29.10306 238.87799,-14.55161 238.20886,-14.55161c-0.66913,0 1.33826,79.37253 1.33826,79.37253c0,0 -543.33026,1.32291 -543.99939,1.32291c-0.66912,0 0.66915,-35.71768 0.66915,-35.71768z" id="svg_10"/>
</g>
</svg>
For using the svg I've got
<div class="svg">
<p>tesygst</p>
</div>
and
.svg {
background: url(pathToSvg.svg) no-repeat bottom left;
position : fixed;
bottom : 0;
left : 0;
height : 100px;
width : 100%;
}
The img has to be placed at the left bottom corner, while the path has to extend itself to 100% width starting at the end of that pic.
Hope somebody can help me :/
You can't put an image inside an SVG, stretch the SVG and have the image not stretch also. That's just how things work. You have to think of the contents of the SVG just the same as if you were talking about an <img> rather than an SVG. You stretch the img, the whole thing stretches.
I take it you are trying to keep the image at 100x100px?
You will need to move the image out of the SVG and into the HTML. Then position it in the right place with CSS. For example:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 600 100" preserveAspectRatio="none" style="-webkit-user-select: auto;">
<g>
<title>title</title>
<path style="-webkit-user-select: auto;" stroke="#000000" fill="#FF0000" stroke-width="0" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="null" d="m98.66982,67.61566c0,0 136.5026,-1.32306 303.78312,-30.42615c167.28064,-29.10306 238.87799,-14.55161 238.20886,-14.55161c-0.66913,0 1.33826,79.37253 1.33826,79.37253c0,0 -543.33026,1.32291 -543.99939,1.32291c-0.66912,0 0.66915,-35.71768 0.66915,-35.71768z" id="svg_10"/>
</g>
</svg>
<img width="100" height="100" src="data:image/png;base64,..."/>
CSS:
IMG {
position: relative;
top: -100px;
}
Demo here