Search code examples
svgscale

How avoid SVG from scaling as its container shrinks?


I want an SVG to not scale as its container shrinks. On scroll, my container shrinks its height (its width stays the same). That container contains an SVG that I want to not become scaled, but instead have its lower part become invisible/cut off.

I can do it if I (by CSS) use my SVG as a background, but I'd prefer to have the SVG inline in the HTML.

I have tried with various values for the SVG attribute preserveAspectRatio. I thought that the value xMidYMin slice would slice off the bottom part of my SVG (like I want), but it squashes its height instead.

My container is 245x80 px and on scroll is shrinked to 245x40 px.

My svg element has attribute viewBox set to 0 0 245 80 , and has no width or height explicitly defined.


Solution

  • You can use preserveAspectRatio="xMidYMin slice" for the svg element.

    Please observe that the svg element has a viewBox and also a width and a height. While the aspect ratio of the viewBox is 1:1 the aspect ratio from width and height is 2:1

    xMidYMin - Force uniform scaling.
    Align the midpoint X value of the element's viewBox with the midpoint X value of the viewport.
    Align the of the element's viewBox with the smallest Y value of the viewport.

    slice - Scale the graphic such that: the aspect ratio is preserved and the entire viewport is covered by the viewBox

    Please read more about preserveAspectRatio

    In the next demo use the slider to change the height of the svg element

    itr.addEventListener("input",()=>{svg.setAttribute("height",itr.value)})
    svg{border:solid}
    <p><input id="itr" type="range" min="10" max="200" value="100"/></p>
    <svg preserveAspectRatio="xMidYMin slice" viewBox="0 0 100 100" width="200" height="100" id="svg">
      <defs>
        <path style="fill:gold; stroke:black; stroke-width: 8px;
        stroke-linecap: round; stroke-linejoin: round;" id="smiley" d="M50,10 A40,40,1,1,1,50,90 A40,40,1,1,1,50,10 M30,40 Q36,35,42,40 M58,40 Q64,35,70,40 M30,60 Q50,75,70,60 Q50,75,30,60" />
      </defs>
    
      <use href="#smiley" />
    </svg>