0

I want to make an arbitrary SVG scale up to its parent container while maintaining aspect ratio. Note that I can't modify the SVGs themselves, so solutions involving modification of the SVG, like editing its viewBox attribute, are not applicable here.

Here is a JSfiddle to demonstrate the issue: https://jsfiddle.net/mj9o0nea/

If you modify the size of the window, you will see that the image scales without maintaining aspect ratio.

CSS from that JSfiddle:

html {
  height: 100%;
  overflow-y: hidden !important;
  overflow-x: hidden !important;
}
body {
  height: 100%;
  margin: 0 0 0 0;
}
img {
  position: absolute;
  margin-left: auto;
  margin-right: auto;
  margin-top: auto;
  margin-bottom: auto;
  padding: 0;

  left: 5%;
  right: 5%;
  top: 3%;
  bottom: 3%;
  max-height: 94%;
  max-width: 90%;

}
.ph {
  width: 100%;
  max-width: 100%;
  max-height: 100%;
}

Normal images like JPGs will display correctly, scaled and centered (e.g. <img src=s.jpg ...) however SVGs will not display correctly (e.g. <img src="data:image/svg+xml...")

5
  • Wht can't you just change the img src attribute with javascript? You can modify the SVG that way or are your actual images not really data URLs? Commented Sep 11, 2019 at 20:52
  • Do you mean adding a preserveAspectRatio attribute inside the src attribute, or something else? As far as I know, it wouldn't have any effect on an SVG that doesn't have a viewBox attribute. Maybe you are thinking about something else? I'm not really familiar with SVGs.
    – bkoodaa
    Commented Sep 11, 2019 at 21:02
  • I mean editing in a viewBox attribute into the src and preserveAspectRatio too if you need/want it. Commented Sep 11, 2019 at 21:03
  • I would need to know the aspect ratio of the image in order to write the viewBox attribute, right? I suppose I could first parse the SVG contents for the height and width attributes in order to calculate aspect ratio, then write the viewBox and preserveAspectRatio attributes?
    – bkoodaa
    Commented Sep 11, 2019 at 21:07
  • that would be the way to go yes, although you might be able to get it directly as nativeHeight and nativeWidth. Commented Sep 11, 2019 at 21:09

1 Answer 1

1

You need to choose what happens when the aspect ratio of the parent element is different from the aspect ratio of the image. I have forked the fiddle to show one way to do it. For clarity, I left out the ph class and added the code to the img css.

The difference with the original code is that both width and height are auto to preserve the aspect ratio. Since max-height and max-width are provided, they will determine which dimension fills the container. The other dimension does not fill the container to preserve the aspect ratio.

You could also fill the container by cropping the larger dimension. The trick is to provide min-height and min-width instead.

EDIT after comments:

As suggested in the comment, I had not taken into account the possibility that the size of the parent (body) could be larger than the native size of the img. In that case, I cannot think of a pure css solution. I have forked the fiddle again here to show a solution using jQuery. Briefly, the script stores the image ratio immediately after loading and sets a handler for resizing. The procedure sets the minor dimension to that of the body and the other dimension accordingly.

EDIT for a pure javascript method:

See a pure javascript version here.

8
  • I'm looking for a solution to scale up to the parent container while maintaining aspect ratio without cropping.
    – bkoodaa
    Commented Sep 12, 2019 at 13:33
  • It doesn't scale up to the parent container.
    – bkoodaa
    Commented Sep 12, 2019 at 19:15
  • One of the dimensions scales to the parent container. If both dimensions scale to the parent container, the aspect ratio will be, by definition, the same as that of the parent container. If you want it to keep the aspect ratio, only one dimension can scale to the parent container. Perhaps I misunderstood your question.
    – vqf
    Commented Sep 13, 2019 at 7:09
  • Your explanation is on point, but the fiddle isn't. As you said, it's supposed to scale until one dimension is as large as the parent container. However, the fiddle jsfiddle.net/c3wyvr2q doesn't scale up. It sounds like you might be using a very small screen? (The fiddle does scale down from its "default" size, but it does not scale up from the default size).
    – bkoodaa
    Commented Sep 13, 2019 at 14:15
  • Here is a screenshot from running your fiddle. It shows the image as a small image in the middle of the container, when it's supposed to scale the image larger, since there is clearly much space in the container: imgur.com/a/Oh5Ol95
    – bkoodaa
    Commented Sep 13, 2019 at 14:17

Not the answer you're looking for? Browse other questions tagged or ask your own question.