frumbert
frumbert

Reputation: 2427

scale image to fit its parent object proportionally

I realise this has been asked many times under many guises, but most solutions seem to not care about the resulting image height, or only scale in one direction. This:

min-width: 100%;
height: auto;

isn't a solution.

I'm trying to fit an image to the height and width so that it can be dynamically injected into a number of places in different systems and sites, so I don't necessarily know what the parent object is going to be - might be a div with or without overflow set, or a p, or the body - or its dimensions; The parent container mustn't change size just by injecting my image/script .. jQuery is NOT available.

I can't see how the css3 background technique would work.

Proportional scaling is as easy as using a ratio:

<img onload="scale(this)" src="screenshot.png">
<script type="text/javascript">
function scale(img){
var p = img.parentNode,
    x = p.offsetWidth,
    y = p.offsetHeight,
    w = img.naturalWidth,
    h = img.naturalHeight;
    ratio = h / w;
    if (h >= y) {
        h = y;
        w = h / ratio;
        img.style.width = w + "px";
        img.style.height = h + "px";
    } else if(w >= x) {  //} && ratio <= 1){
        w = x;
        h = w * ratio;
        img.style.width = w + "px";
        img.style.height = h + "px";
    }
}
</script>

but this only scales in one plane - I need it to continue to scale both width and height until it fits into the parent container space neatly in both dimensions. If the image is smaller than the parent container, it should scale UP to fill proportionally.

Upvotes: 0

Views: 1894

Answers (2)

Jacob
Jacob

Reputation: 595

I used this code to fit a video to its parent:

      var parent = vid.parentNode,
      vw = vid.videoWidth,
      vh = vid.videoHeight,
      vr = vh / vw, // video ratio
      pw = parent.offsetWidth,
      ph = parent.offsetHeight,
      pr = ph / pw; // parent ratio
      if(pr > vr) {
        vid.style.width = 'unset';
        vid.style.height = `${ph}px`;
      } else {
        vid.style.height = 'unset';
        vid.style.width = `${pw}px`;
      }

Upvotes: 0

Roko C. Buljan
Roko C. Buljan

Reputation: 206151

Adapt image to fit parent container (of unknown size) without stretching image


Instead of messing with JS, let CSS do the job!

  • Set your image to 100%; height and width;
  • Replace your image's src with a transparent pixel and set it's background to the actual src.
  • Use CSS's background-size on your (now) full-sized image:

contain (image will cover the parent completely)
cover (image will respect image proportions instead)

Example using contain

function scale( img ) {
  if(img.isScaled) return;
  img.style.background="no-repeat url("+ img.src +") 50%";
  img.style.backgroundSize="contain";  // Use "contain", "cover" or a % value
  img.style.width="100%";
  img.style.height="100%";
  img.isScaled=true; // Prevent triggering another onload on src change
  img.src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
}
<div style="width:300px; height:300px; background:#000; margin:10px;">
  <img onload="scale(this);" src="//placehold.it/1200x600/f0f">
</div>


<div style="width:300px; height:300px; background:#000; margin:10px;">
  <img onload="scale(this);" src="//placehold.it/400x600/cf5">
</div>

Tested in: FF, CH, E, IE(11), SA


NB: The transparent pixel data is used solely to prevent the browser's Missing Iimage Icon that would be otherwise caused by doing img.src = "";

http://caniuse.com/#search=background-size

Upvotes: 3

Related Questions