0

What is the best way to simulate upcoming CSS3 object-fit property using CSS2 & JS? I'm interested in contain & cover methods for fitting.

EDIT: In CSS3 there is the new object-fit mechanism described here: http://dev.opera.com/articles/view/css3-object-fit-object-position/ but object-fit is not yet supported outside the Opera browsers. To create a portable solution I need to make an img grow or shrink to the size of its parent div without loosing the original aspect ratio of the image. This can be achieved by either containing the whole image (technique also called letterboxing) or by enlarging & overflowing the image until the smallest dimension matches the div's dimension (technique also called as cover). There are a few jquery imagefit libraries out there by they are very buggy (perhaps they work only in a specific situation on a specific browser).

EDIT 2: This question has been understood by those taking the time to read it, a good answer has been suggested and an answer has been given. It is difficult to understand the decision of closing it.

sqreept
  • 5,236
  • 3
  • 21
  • 26

5 Answers5

5

Why use JavaScript or CSS3 stuff? just use this and you are good to go

Demo

img {
   max-width: 100%;
   max-height: 100%;
}
/* This will resize you image according to the container size and 
   will retain the aspect ratio too */
NullPoiиteя
  • 56,591
  • 22
  • 125
  • 143
Mr. Alien
  • 153,751
  • 34
  • 298
  • 278
  • Not sure why the down vote.. it's a decent solution imo. Only thing is that it will not go beyond the original size of the image – dakdad Dec 25 '12 at 13:54
  • @dakdad ya but it's `Fit img in div container` else he can simply use `background-size: cover;` – Mr. Alien Dec 25 '12 at 13:56
  • Downvoting this because it doesn't answer the question. – sqreept Dec 25 '12 at 13:58
  • @sqreept so what's your question? – Mr. Alien Dec 25 '12 at 13:58
  • What is the best way to simulate upcoming CSS3 object-fit property using CSS2 & JS? I'm interested in contain & cover methods for fitting. – sqreept Dec 25 '12 at 13:59
  • 2
    but your question says this `Fit img in div container`, if you still need a full page background check this out, http://css-tricks.com/perfect-full-page-background-image/, still it's not what you are looking for than sorry no1 understood your question probably... – Mr. Alien Dec 25 '12 at 13:59
  • If you have an answer to the question please write it down. If you're here to participate in a semantic dispute, I'm sorry, seats are sold out. – sqreept Dec 25 '12 at 14:03
  • 1
    Am not here to dispute, if you think so am going mum...you can wait for your answer – Mr. Alien Dec 25 '12 at 14:05
3

For anyone interested, here's the actual working solution:

JSFiddle Demo

and the actual code:

(function($) {
  $.fn.imagefit = function(contain) {
    this.each( function() {
      var $this           = $(this),
          $wrapper        = $this.parent(),
          wrapper_width   = $wrapper.width(),
          wrapper_height  = $wrapper.height(),
          wrapper_ratio,
          image_ratio;


        // ratios
      image_ratio   = $this.width() / $this.height();
      wrapper_ratio = wrapper_width / wrapper_height;

      var ratio_cond = wrapper_ratio > image_ratio;
        if(contain) {
            ratio_cond = !ratio_cond;
        }

      if ( ratio_cond ) {
          $wrapper.css({
            'background'  : 'url('+$this.get(0).src+')',
            'background-size'  : '100% auto',
            'background-position'  : '0px 50%',
            'background-repeat'  : 'no-repeat'
          });
      } else {
          $wrapper.css({
            'background'  : 'url('+$this.get(0).src+')',
            'background-size'  : 'auto 100%',
            'background-position'  : '50% 0px',
            'background-repeat'  : 'no-repeat'
          });
      }

      $this.remove();

    });
    return this;
  };

  $('div.bgthumb#cover > img').imagefit(false);               
  $('div.bgthumb#contain > img').imagefit(true);               

}(jQuery));​

@Hippocrates: Thanks a lot for pointing me in the right direction.

sqreept
  • 5,236
  • 3
  • 21
  • 26
  • You could also use `ratio_cond` to set a class on the wrapper element and then apply styles accordingly: `width: 100%; height: auto;` or the other way around and center it with something like `top: 50%; left: 50%; transform: translate(-50%, -50%);`. – daniels May 14 '15 at 15:01
  • I used your solution and improved it a bit to answer a [similar question](http://stackoverflow.com/a/30242945/2270233). – daniels May 14 '15 at 17:02
2

If you set the image as the background of the container you get a handy CSS property: background-size. Values can be seen here: http://www.w3schools.com/cssref/css3_pr_background-size.asp

Hippocrates
  • 2,510
  • 1
  • 19
  • 35
0

if you need a cross-browser solution for stretchable background- maybe use some plugin like: http://srobbin.com/jquery-plugins/backstretch/

user1276919
  • 550
  • 5
  • 25
0

Here is another way - without using background images. (note, I have not worried about positioning at this stage)

http://jsfiddle.net/Z5Hb8/2/

$('.resize').each(function(){
var el = $(this).find('img'),
    pael = el.parent(),
    ph = pael.height(),
    pw = pael.width(),
    pr = pw/ph,
    img = new Image();

img.src = el.attr('src');
img.onload = function() {
    var w = this.width,
        h = this.height,
        sr = w/h;

    if (pael.hasClass('cover')) {
        if (pr > sr) {
            el.width(pw);   
        } else {
            el.height(ph);
        }
    } else if (pael.hasClass('contain')) {
        if (sr > pr) {
           el.width(pw);
        } else {
           el.height(ph);
        }
    }        
}
});
dakdad
  • 2,947
  • 2
  • 22
  • 21