15

I want to use object-fit CSS rule.
This is not supported in MSIE and MS Edge Browser.
While there are some polyfills for IE, there is none to my knowledge that works in Edge.

E.g. the polyfill fitie by Jonathan Neal works with IE, but not in Edge (at least not on my machine). This is because fitie uses element.currentStyle and element.runtimeStyle which are MS only JS objects which do not any support in Edge browsers anymore. But if I use window.getComputedStyle(element).getPropertyValue('object-fit'), Edge returns nothing.

So how do I obtain the value of CSS rule object-fit rule with JavaScript in MS Edge browser?

img = document.getElementById('i');
s = self.getComputedStyle(img);
console.log('object-fit: ', s.getPropertyValue('object-fit'));
console.log('-ms-object-fit: ', s.getPropertyValue('-ms-object-fit'));
div {
  width: 400px;
  height: 320px;
  overflow: hidden;
}
#i {
  display: block;
  width: 100%;
  height: 100%;
  -ms-object-fit: cover;
  object-fit: cover;
}

div {
  box-sizing: border-box;
  border: 1px solid gold;
}
div,
p {
  font-family: sans-serif;
  font-size: 20px;
  width: 400px;
  margin: 0 auto;
}
<p>img: Has object-fit CSS rule, but does not appear in MS Edge JavaScript log</p>
<div>
<img src="https://dummyimage.com/640x240/333/444.png" id="i" />
</div>

Edit

It must be possible somehow, as it is not fully ignored.
The Developer Tools show the rule curly underlined
curly underlined


Bonus question:

Is there any polyfill for object-fit that works in Edge?

yunzen
  • 32,854
  • 11
  • 73
  • 106
  • Try this ? https://github.com/bfred-it/object-fit-images/ – l2aelba Jul 12 '17 at 07:58
  • @l2aelba This is rather strange, as it uses an arbitrary font-family rule. – yunzen Jul 12 '17 at 08:02
  • Hehe agree. I think his idea is "Who's changing font-family on images ?" – l2aelba Jul 12 '17 at 08:05
  • @l2aelba: I think it is more like: Where can I store arbitrary strings in CSS. – yunzen Jul 12 '17 at 08:10
  • hahaha, But does it work for you with this polyfill? – l2aelba Jul 12 '17 at 08:11
  • @l2aelba It does work, but that's only the bonus question :) – yunzen Jul 12 '17 at 08:11
  • Yeah its good ! – l2aelba Jul 12 '17 at 08:12
  • 1
    FYI, Edge in Win10 Creators Update (ver. 16.16237) supports `object-fit` – Asons Jul 25 '17 at 13:36
  • *"It must be possible somehow, as it is not fully ignored. The Developer Tools show the rule curly underlined"* If we as web-devs had the same power as our tools, I wouldn't use my web browser anymore. I guess you are in an X-Y problem, but while fortunately, browsers don't give us access to the rules they don't know (it's already a mess enough to deal with only supported ones...) you can try to parse it yourself from the ` – Kaiido Jul 25 '17 at 14:53

2 Answers2

6

You should be able reference it directly:

// 'Fill' in Chrome and undefined in Edge
console.log('object-fit',  
    window.getComputedStyle(document.querySelector('.test')).objectFit);

// 'rgb(255,0,0)' in both
console.log('color', 
    window.getComputedStyle(document.querySelector('.test')).color);
.test{ color: red; }
<div class="test">test</div>

That style property will be undefined in browsers that don't support it (like Edge) even with a polyfill.

The problem is that, as far as Edge is concerned: there is no object-fit rule. When Edge parses the CSS it fails to recognise the rule and just skips it. If you shim the behavior with other properties or JS that doesn't change the fact that Edge just doesn't know about it.

So, in answer specifically to "So how do I obtain the value of CSS rule object-fit rule with JavaScript in MS Edge browser?" you can do window.getComputedStyle(ele).objectFit to get the value, and it's always undefined (even if successfully shimmed).

For the bonus question: background-size: cover is supported by Edge, so you should be able to set the image as a CSS background to a display:inline-block element and get the behaviour that you want. You can swap out the <img> for a styled <div> fairly easily...

var img = document.querySelector('.i');

// If object-fit missing
if (!window.getComputedStyle(img).objectFit) {

  // Create a div
  var div = document.createElement('div');
  div.className = img.className;

  // Set the background image to be the source
  div.style.backgroundImage = 'url(' + img.src + ')';

  // Set background-size to the object-fit we want
  div.style.backgroundSize = 'cover';

  // Swap them
  img.parentNode.replaceChild(div, img);
}
.test {
  width: 400px;
  height: 320px;
  overflow: hidden;
  border: 1px solid red;
}

.i {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
<div class="test">
  <img src="https://dummyimage.com/640x240/333/444.png" class="i" /></div>

That's just the basic idea - a shim like object-fit-images takes this idea a lot further and supports additional properties like object-position.

Alternatively (and with a lot more HTML) you can keep the <img> tag and wrap it in a container that behaves like it's applying object-fit relative to it. This is what object-fit-polyfill has done.

Both shims should work in Edge.

Keith
  • 150,284
  • 78
  • 298
  • 434
  • Since we are testing the availability, you can do `prop in window.getComputedStyle(document.querySelector('.test'))` to return a boolean value – Rajesh Jul 25 '17 at 11:10
  • 2
    Isn't this exactly the problem the asker is trying to solve? You claim that one can reference the property directly, but then immediately debunk your own claim with the same observation that this won't work in browsers that don't support the property. – BoltClock Jul 25 '17 at 11:11
  • @BoltClock Yeah, it's a little confusing - one of the reasons JS's not one but two types of nothing is messy. I'm trying to narrow it down to _So how do I obtain the value of CSS rule object-fit rule with JavaScript in MS Edge browser?_ - and that value is (unhelpfully) `undefined`. – Keith Jul 25 '17 at 12:00
  • This does not help. I know, that MS Edge does not know about objectFit. But maybe there is some hidden place I can get, where it does – yunzen Jul 25 '17 at 14:29
  • @HerrSerker sorry, there isn't - to Edge `object-fit` is just an unknown CSS rule. It has no implementation you can access. You can either replace it with `background-size` or scale the entire `` to look similar (as the two shims I linked to both do in Edge) but those don't change the fact that it's just not supported. – Keith Jul 25 '17 at 14:32
  • 1
    @HerrSerker Edge will show that squiggly red underline to any unrecognised style rule that doesn't have a vendor prefix. It gets the CSS, sees the name of the rule `object-fit` and ignores it. – Keith Jul 25 '17 at 14:35
5

I want to use object-fit CSS rule.

You don't need to obtain the value of CSS rule object-fit rule with JavaScript in MS Edge browser to be able to make an img cover its parent.

Bonus: No need to use a polyfill and works across all browsers down to IE9

Side note, MS Edge ver. 16 supports object-fit

Here is a solution that works exactly as object-fit: cover, making use of transform: translate and min-width/height.

div {
  width: 400px;
  height: 320px;
  box-sizing: border-box;
  border: 1px solid gold;
  margin: 0 auto;
  overflow: hidden;
}

#i {
  position: relative;
  display: block;
  min-width: 100%;
  min-height: 100%;
  top: 50%;
  left: 50%;
  transform: translate(-50%,-50%);
}
<div>
  <img src="https://dummyimage.com/640x240/333/444.png" id="i" />
</div>

If you want you can use CSS @supports to also reset the above properties and add object-fit.

div {
  width: 400px;
  height: 320px;
  box-sizing: border-box;
  border: 1px solid gold;
  margin: 0 auto;
  overflow: hidden;
}

#i {
  position: relative;
  display: block;
  min-width: 100%;
  min-height: 100%;
  top: 50%;
  left: 50%;
  transform: translate(-50%,-50%);
}

@supports (object-fit: cover) {
  #i {
    min-width: auto;
    min-height: auto;
    top: auto;
    left: auto;
    transform: none;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
}
<div>
  <img src="https://dummyimage.com/640x240/333/444.png" id="i" />
</div>

Another overlooked option when one need to use an img because one want to set the image source in the markup, is to use a inline style for the background-image source.

Given the fact, in this case, where a div with fixed width/height sets the boundaries for the image, here is a simple sample of that.

div {
  width: 400px;
  height: 320px;
  box-sizing: border-box;
  border: 1px solid gold;
  margin: 0 auto;
  overflow: hidden;
  background-position: center;
  background-size: cover;
}
<div style="background-image: url(https://dummyimage.com/640x240/333/444.png)">
</div>

Updated

You can of course mimic object-fit: contain as well

div {
  width: 400px;
  height: 320px;
  box-sizing: border-box;
  border: 1px solid gold;
  margin: 0 auto;
  overflow: hidden;
}

#i {
  position: relative;
  display: block;
  max-width: 100%;                    /*  changed to max  */
  max-height: 100%;                   /*  changed to max  */
  top: 50%;
  left: 50%;
  transform: translate(-50%,-50%);
}
<div>
  <img src="https://dummyimage.com/640x240/333/444.png" id="i" />
</div>

Updated based on a comment

When it comes to mimic object-fit for video things gets much more complicated.

The video element doesn't respond in the same way an image does.

Here is 4 different samples showing that some video work when mimic cover and some when mimic contain

To achieve a consistent and the same good result as with the image, one need to run a small script to get the video aspect ratio, and then set its width or height to 100% based on its and its container aspect ratio.

Here is another post at SO, simulate background-size:cover on <video> or <img>, which show some more approaches how one can go about this.


One other option I found is to use media query and its max/min-aspect-ratio

Fiddle demo

Src: https://fvsch.com/code/video-background/

Asons
  • 84,923
  • 12
  • 110
  • 165