I'm trying to get an SVG image to be the equivalent of object-fit
inside an 100vh full screen container. From what I can gather I need to use the preserveAspectRatio="xMidYMid slice"
attribute and set width="100%" height="100%"
I can't seem to get it work though? When I play around with it, there is either a chunk of whitespace showing at the bottom of the container, or when the image does fill the viewport the viewport then becomes a lot bigger than 100vh?
Just to note I can't use the CSS background-image property because it is part of a wider SVG / Javascript animation I'm building.
Codepen: https://codepen.io/emilychews/pen/YJYrEa
Does anyone know what is going wrong here and what the solution would be?
Thanks in advance for any help / ideas.
body {
margin: 0;
padding: 0;
display: flex;
width: 100%;
height: 100vh;
justify-content: center;
align-items: center;
}
#section-1, .background-clipped {
width: 100%;
height: 100%;
}
<section id="section-1">
<div class="background-clipped background-clipped-1">
<svg id="home-image-1" viewbox="0 0 100 100" preserveAspectRatio="xMidYMid slice">
<image x="0" y="0" xlink:href="https://i.postimg.cc/9XdQKYF1/dimon-blr-309444-unsplash.jpg" width="100%" height="100%" />
</svg>
</div>
</section>
There are multiple sizing mechanisms at work; one for the <svg>
element, one for the <image>
element.
The one you set for the <svg>
element is not really helpfull. The viewBox
attribute fits a coordinate system of 100 by 100 user units inside the container. This coordinate system is then the viewport for sizing the <image>
with an implicit preserveAspectRatio="xMidYMid meet"
. If you find that confusing: yes, that is the problem.
Instead, just size the <svg>
element to fill the container. Remove the viewBox
, set width
and height
to 100%. Without a viewBox
, preserveAspectRatio
also has no effect on the <svg>
element.
Now, only the sizing mechanism for your image (fit the nimage into the 100% width and height of the viewport, as preserveAspectRatio
describes), takes effect and works as you want it to.
General note: a JPG, as used in your <image>
, has an inherent aspect ratio. Therefore preserveAspectRatio
will always have an effect. A <svg>
element has not. Only a viewBox
has one. and is what the attribute works on.
body {
margin: 0;
padding: 0;
display: flex;
width: 100%;
height: 100vh;
justify-content: center;
align-items: center;
}
#section-1, .background-clipped {
width: 100%;
height: 100%;
}
<section id="section-1">
<div class="background-clipped background-clipped-1">
<svg id="home-image-1" width="100%" height="100%">
<image xlink:href="https://i.postimg.cc/9XdQKYF1/dimon-blr-309444-unsplash.jpg"
x="0" y="0" width="100%" height="100%" preserveAspectRatio="xMidYMid slice"/>
</svg>
</div>
</section>