1

I'm working on placing image in the exact middle of the object, to make it look like background-size: cover;. To do it, I've set the width or the height (the smaller among them) to 100% and the other one to auto. Then I've set the top and the right to 50%. At the end, I tried to set the margins (the right and the top) to minus half of the height and the width.

Here is my code:

$.fn.extend({
    middleify: function(){
        var i = $(this);
        var f = i.parent();
        var wh = i.height() == i.width() ? f.width() < f.height() : i.width() > i.height();
        var hw = i.height() == i.width() ? f.height() < f.width() : i.height() > i.width();
        return i.css({position: "relative", "z-index": 2, width: hw ? "100%" : "auto", height: wh ? "100%" : "auto", top: "50%", right: "50%", "margin-right": 0 - (i.width()) / 2, "margin-top": 0 - (i.width() / 2)});
    }
});

http://jsfiddle.net/beb8o2g6/2/

Thanks!

Robin Carlo Catacutan
  • 13,249
  • 11
  • 52
  • 85
  • I'm having trouble understanding what your end goal here is. – Jack May 15 '15 at 21:39
  • @Jack I want the image to be in the middle of the rectangle, exactly like `background-size: cover;` –  May 15 '15 at 21:41
  • @Jack I've added the goal: http://jsfiddle.net/beb8o2g6/2/ –  May 15 '15 at 21:49
  • Why do you need to do this with javascript? Knowing why you can't just use background-size might help to come up with a different solution. – Jack May 15 '15 at 21:59
  • Those images are important part of the website, and I've read somewhere that Googlebot can see only the images in the `img` object, not in the background image. –  May 15 '15 at 22:03

2 Answers2

0

You can do this with just CSS...

figure {
    position: relative;
    overflow: hidden;
    height: 100px;
    width: 200px;
    border: 1px solid black;
}

figure img {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%,-50%);
    width: 100%;
}
<div class="left">
    <h1>The attempt</h1>
    <figure>
        <img src="https://fbcdn-sphotos-b-a.akamaihd.net/hphotos-ak-xpf1/t31.0-8/1601993_484655221639466_890925492_o.jpg" />
    </figure>
    
    <figure>
        <img src="https://scontent-fra.xx.fbcdn.net/hphotos-ash2/v/t1.0-9/580303_450139941757661_1330443402_n.jpg?oh=9ae59fa1b0e51a356b2ca50b0c160354&oe=55DDE28F" />
    </figure>
    
    <figure>
        <img src="https://fbcdn-sphotos-g-a.akamaihd.net/hphotos-ak-xap1/v/t1.0-9/1618538_487714631333525_1011288966_n.jpg?oh=2e48acfd68c08d2ea27fa3e7ba8e9462&oe=55B2A1C5&__gda__=1441110764_e04ce223b16035ae8c496e00f8845212" />
    </figure>
</div>
sbeliv01
  • 11,550
  • 2
  • 23
  • 24
  • I cannot set the width to 100%, because if the height is smaller then the width it won't fill the whole `figure`. Also, correct me if I'm wrong, but not all the browsers support `translate`. –  May 15 '15 at 22:14
  • `transform/translate` has the same browser support as `figure` so if you want to use `figure` you should be fine. http://caniuse.com/#search=transform – sbeliv01 May 15 '15 at 22:25
  • If so, then great! Thanks! –  May 15 '15 at 22:34
0

There are too many things you missed checking.

First

Your $(this); contains an array of elements because your selector is img

$("img").middleify();

Yet you are storing values like this :

    var i = $(this);
    var f = i.parent();

Second

var wh = i.height() == i.width() ? f.width() < f.height() : i.width() > i.height();
var hw = i.height() == i.width() ? f.height() < f.width() : i.height() > i.width();

You don't need to have this kind of conditions, it really does confuse me. How about just setting the width:100% then height: auto since your container has bigger width than it's height.

Third

return i.css({position: "relative", "z-index": 2, width: hw ? "100%" : "auto", height: wh ? "100%" : "auto", top: "50%", right: "50%", "margin-right": 0 - (i.width()) / 2, "margin-top": 0 - (i.width() / 2)});

You are computing the width and height of the element which you haven't set those values yet. It's more likely it will get the default values.

To fix that you have to set the width and height first and separately to the computation

"margin-right": 0 - (i.width()) / 2, "margin-top": 0 - (i.width() / 2)});

Putting them together

$.fn.extend({
  middleify: function(){
    var i = $(this);
    $.each(i, function(index, value) {
       var elm = $(value);
       var f = elm.parent();  
       elm.css({position: "relative", "z-index": 2, width: "100%", height:"auto", top: "50%", left: "50%"});

       elm.css({"margin-left": 0 - (elm.width()) / 2, "margin-top": 0 - (elm.height() / 2)}); 
    });
  }
});
$("img").middleify();

Fiddle

Update

Since setting a wider image width 100% will cause a problem, let's make use of this logic on background:cover

$.fn.extend({
  middleify: function(){
    var i = $(this);
    $.each(i, function(index, value) {
       var elm = $(value);
       var f = elm.parent();  

        var imgWidth = elm.width();
        var imgHeight = elm.height();

        var containerWidth = f.width();
        var containerHeight = f.height();

        var imgRatio = (imgHeight / imgWidth);
        var containerRatio = (containerHeight / containerWidth);

        if (containerRatio > imgRatio) {
          var finalHeight = containerHeight;
          var finalWidth = (containerHeight / imgRatio);
        } 
        else {
          var finalWidth = containerWidth;
          var finalHeight = (containerWidth * imgRatio);
        }

       elm.css({position: "relative", "z-index": 2, width: finalWidth, height: finalHeight, top: "50%", left: "50%"});

       elm.css({"margin-left": 0 - (elm.width()) / 2, "margin-top": 0 - (elm.height() / 2)}); 
    });
  }
});
$("img").middleify();

Fiddle

Community
  • 1
  • 1
Robin Carlo Catacutan
  • 13,249
  • 11
  • 52
  • 85
  • There is a problem with setting width to 100%. Some of the images I'm working with looks like this one: https://scontent-fra.xx.fbcdn.net/hphotos-xfp1/t31.0-8/1502690_477245699047085_1960157551_o.jpg –  May 15 '15 at 22:52