48

I'm using object-fit: cover; in my CSS for images on a specific page, because they need to stick on the same height. It works great in most browsers.

But when scaling my browser in IE or Edge, the image is resizing in width (not height) instead of zooming. The image gets out of shape.

What CSS rule can I use to fix this?

Here is the page

dippas
  • 58,591
  • 15
  • 114
  • 126
Peter van Remmen
  • 645
  • 1
  • 6
  • 13
  • 17
    It's just depressing that it doesn't work in Edge.. – Rotareti Sep 29 '16 at 12:31
  • A nice solution over here that preserves the SEO benefits of using an img and some JS to handle the background ver for IE/edge browsers. https://medium.com/@primozcigler/neat-trick-for-css-object-fit-fallback-on-edge-and-other-browsers-afbc53bbb2c3#.6smxr75ca – Nickfmc Feb 07 '17 at 18:50
  • 3
    Faced the same problem recently. This lightweight polyfill had done the job like a charm :) https://github.com/bfred-it/object-fit-images – Sergiy Zaharchenko Apr 27 '19 at 18:33

7 Answers7

40

I had similar issue. I resolved it with just CSS.

Basically Object-fit: cover was not working in IE and it was taking 100% width and 100% height and aspect ratio was distorted. In other words image zooming effect wasn't there which I was seeing in chrome.

The approach I took was to position the image inside the container with absolute and then place it right at the centre using the combination:

position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);

Once it is in the centre, I give to the image,

// For vertical blocks (i.e., where height is greater than width)
height: 100%;
width: auto;

// For Horizontal blocks (i.e., where width is greater than height)
height: auto;
width: 100%;

This makes the image get the effect of Object-fit:cover.


Here is a demonstration of the above logic.

https://jsfiddle.net/furqan_694/s3xLe1gp/

This logic works in all browsers.

Furqan Rahamath
  • 2,034
  • 1
  • 19
  • 29
20

There is no rule to achieve that using CSS only, besides the object-fit (that you are currently using), which has partial support in EDGE1 so if you want to use this in IE, you have to use a object-fit polyfill in case you want to use just the element img, otherwise you have to do some workarounds.

You can see the the object-fit support here

UPDATE(2019)

You can use a simple JS snippet to detect if the object-fit is supported and then replace the img for a svg

//ES6 version
if ('objectFit' in document.documentElement.style === false) {
    document.addEventListener('DOMContentLoaded', () => {
        document.querySelectorAll('img[data-object-fit]').forEach(image => {
            (image.runtimeStyle || image.style).background = `url("${image.src}") no-repeat 50%/${image.currentStyle ? image.currentStyle['object-fit'] : image.getAttribute('data-object-fit')}`
            image.src = `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='${image.width}' height='${image.height}'%3E%3C/svg%3E`
        })
    })
}

//ES5 version transpiled from code above with BabelJS
if ('objectFit' in document.documentElement.style === false) {
    document.addEventListener('DOMContentLoaded', function() {
        document.querySelectorAll('img[data-object-fit]').forEach(function(image) {
            (image.runtimeStyle || image.style).background = "url(\"".concat(image.src, "\") no-repeat 50%/").concat(image.currentStyle ? image.currentStyle['object-fit'] : image.getAttribute('data-object-fit'));
            image.src = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='".concat(image.width, "' height='").concat(image.height, "'%3E%3C/svg%3E");
        });
    });
}
img {
  display: inline-flex;
  width: 175px;
  height: 175px;
  margin-right: 10px;
  border: 1px solid red
}

[data-object-fit='cover'] {
  object-fit: cover
}

[data-object-fit='contain'] {
  object-fit: contain
}
<img data-object-fit='cover' src='//picsum.photos/1200/600' />
<img data-object-fit='contain' src='//picsum.photos/1200/600' />
<img src='//picsum.photos/1200/600' />

UPDATE(2018)

1 - EDGE has now partial support for object-fit since version 16, and by partial, it means only works in img element (future version 18 still has only partial support)

SS

dippas
  • 58,591
  • 15
  • 114
  • 126
  • 3
    `background-size: cover` is the usual workaround for IE/Edge that solves most cases of this. – TylerH Jun 13 '16 at 14:58
  • 1
    @TylerH yes, but then you have to change from `img` to `background img` – dippas Jun 13 '16 at 15:00
  • Maybe a silly question, but is background-img less good for SEO then an actual image? – Peter van Remmen Jun 17 '16 at 13:04
  • 4
    img is better for SEO – dippas Jun 17 '16 at 13:14
  • Update for 2019 is the best answer right here. Minor note... you could make it a bit clearer that it needs to be transpiled. And I think ES5 might be too new, common might be better for compatibility. A link to an online transpiler that I used: https://babeljs.io/repl – Davey Jan 09 '20 at 11:11
  • @Davey I have this note on top of the JS code `//for browsers which doesn't support object-fit (you can use babel to transpile to ES5)` I don't know if you saw that. Although I will update the answer to have the transpiled version as well – dippas Jan 09 '20 at 11:14
  • 1
    @dippas In addition, `background-image` is also not accessibility friendly. – hazelnut Mar 30 '20 at 03:13
  • @dippas On IE11 I get error for `forEach` method, it seems not supported. Could you provide a version of your solution compatible with IE11? – Fred K Nov 16 '20 at 10:51
  • @dippas I tried with this polyfill https://developer.mozilla.org/it/docs/Web/API/NodeList/forEach. Now I don't get error anymore, but it just doesn't add `style="..."` on the ``, it just inject the code into `src="..."`, so I get no image as background. EDIT: maybe I'm wrong, it was IE11 console that doesn't show the style="" attribute but it shows in compiled tab! – Fred K Nov 16 '20 at 11:28
12

I just used the @misir-jafarov and is working now with :

  • IE 8,9,10,11 and EDGE detection
  • used in Bootrap 4
  • take the height of its parent div
  • cliped vertically at 20% of top and horizontally 50% (better for portraits)

here is my code :

if (document.documentMode || /Edge/.test(navigator.userAgent)) {
    jQuery('.art-img img').each(function(){
        var t = jQuery(this),
            s = 'url(' + t.attr('src') + ')',
            p = t.parent(),
            d = jQuery('<div></div>');

        p.append(d);
        d.css({
            'height'                : t.parent().css('height'),
            'background-size'       : 'cover',
            'background-repeat'     : 'no-repeat',
            'background-position'   : '50% 20%',
            'background-image'      : s
        });
        t.hide();
    });
}

Hope it helps.

Meloman
  • 3,558
  • 3
  • 41
  • 51
10

You can use this js code. Just change .post-thumb img with your img.

$('.post-thumb img').each(function(){           // Note: {.post-thumb img} is css selector of the image tag
    var t = $(this),
        s = 'url(' + t.attr('src') + ')',
        p = t.parent(),
        d = $('<div></div>');
    t.hide();
    p.append(d);
    d.css({
        'height'                : 260,          // Note: You can change it for your needs
        'background-size'       : 'cover',
        'background-repeat'     : 'no-repeat',
        'background-position'   : 'center',
        'background-image'      : s
    });
});
TheMisir
  • 4,083
  • 1
  • 27
  • 37
8

Here's a CSS solution to fix this. Use the below css.

.row-fluid {
  display: table;
}

.row-fluid .span6 {
  display: table-cell;
  vertical-align: top;
}

.vc_single_image-wrapper {
  position: relative;
}

.vc_single_image-wrapper .image-wrapper {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  background-size: cover;
  background-repeat: no-repeat;
  background-position: 50% 50%;
}

HTML from the OP:

<div class="vc_single_image-wrapper   vc_box_border_grey">
  <div class="image-wrapper" style="background-image: url(http://i0.wp.com/www.homedecor.nl/wp-content/uploads/2016/03/Gordijnen-Home-Decor-2.jpg?fit=952%2C480;"></div>
</div>

try this, it should work. also remove float from .row-fluid .span6

dippas
  • 58,591
  • 15
  • 114
  • 126
Lucian
  • 1,715
  • 3
  • 17
  • 26
3

I achieved satisfying results with:

min-height: 100%;
min-width: 100%;

this way you always maintain the aspect ratio.

The complete css for an image that will replace "object-fit: cover;":

width: auto;
height: auto;
min-width: 100%;
min-height: 100%;
position: absolute;
right: 50%;
transform: translate(50%, 0);
Ini Kim
  • 47
  • 1
2

parent div:

height: 584px;
display: block;
background-position: center center;
background-size: cover;
width: 100%;
position: absolute;
overflow: hidden;
background-color: #fff;

child img

object-position: center center;
min-height: 100%;
display: block;
position: absolute;
top: -9999px;
bottom: -9999px;
left: -9999px;
right: -9999px;
margin: auto;
width: auto;
min-width: 100%;
max-width: none;
-o-object-fit: cover; // you can keep them for modern browsers
object-fit: cover; // you can keep them for modern browsers
height: 100%;

fiddle: http://jsfiddle.net/j6hLaxz8/

funky-nd
  • 637
  • 1
  • 9
  • 25