122

I've been trying to use object-fit on a few images placed inside article elements, but it doesn't seem to affect them at all.

The desired value for the object-fit property would be cover, but as of right now, none of the other values seem to work either.

When I change it's value, they don't shrink, don't grow, don't ... nothing.

If you see the CodePen, there are white spaces between the two rows, and the images don't take all the same space/height (as it would be expected with object-fit: cover).

Here's a CodePen

body{
 margin: 0 auto; padding: 0;
}
main{
 min-height: 70vh;
 padding: 0;
}
main > section.posts{
 box-sizing: border-box;
 margin: 0; padding: 0;
 display: flex;
 flex-flow: row wrap;
}
main > section.posts > article{
  outline: 1px solid red;
 width: 22vw;
 min-height: 100vh;
 margin: 0; padding: 0;
 flex-grow: 1;
 overflow: hidden;
 box-sizing: border-box;
}
main > section.posts > article > img{  /* Our suspect */
  object-fit: cover;
}
<!--
Basic structure of this file is

<main>
  <section.posts>
      <article> (six of them)
          <image>
-->

<main>
  <section class="posts">
    <article>
      <img src="http://41.media.tumblr.com/tumblr_m6s6d65lE11qdnz8wo1_400.jpg">
    </article>

    <article>
      <img src="http://41.media.tumblr.com/71c1fe7c899cd048fb961d3c1953411b/tumblr_nj24pvINyW1qzq8p3o1_400.jpg">
    </article>

    <article>
      <img src="http://36.media.tumblr.com/3358cb6ac8eaa0e61dffd53bc1bab93d/tumblr_n92l475hol1qlmppmo1_400.png">
    </article>

    <article>
      <img src="http://36.media.tumblr.com/9ad997ca0385a23a8d82ec919da2392c/tumblr_nwcewbFVAL1s71gzco1_400.jpg">
    </article>

    <article>
      <img src="http://41.media.tumblr.com/tumblr_mbl45xDSwj1qfn79co1_400.jpg">
    </article>

    <article>
      <img src="http://41.media.tumblr.com/1c3718e71a2aa5acaaaf4af654991c91/tumblr_nx6psaH67d1tvh80lo1_400.jpg">
    </article>
  </section>
</main>
P3t3r6
  • 1,398
  • 2
  • 9
  • 12
  • Hi, first, thank you for your time :) My problem is that object-fit doesn't seem to be doing anything at all on the images. When I change it's value, they don't shrink, don't grow, don't ... nothing .... If you see the CodePen, there are white spaces between the two rows, and the images don't take all the same space/height (as it would be expected with `object-fit: cover` ). – P3t3r6 Dec 13 '15 at 02:36
  • 1
    I've never used object fit, and I don't think it works on my current mobile chrome browser, but from what I've read, this seems to apply to the image itself and not the image container. So if you specify the width and height of the image, you may get what you want. So in your case, perhaps making the flex work with the image instead of the article – teynon Dec 13 '15 at 02:38
  • http://jsfiddle.net/o2fx87ws/ on my phone so this is a bit hard to write – teynon Dec 13 '15 at 02:44
  • 1
    Possible duplicate of [Fit background image to div](http://stackoverflow.com/questions/8200204/fit-background-image-to-div) – Alvaro Silvino Dec 13 '15 at 02:45
  • @alvarojoao this isn't really the same concept as fitting an image to a div. Object-fit has to do with how the image is rendered in its given space – teynon Dec 13 '15 at 02:47
  • @Tom It should work in every browser (Except Edge and IE), native Android browser from 4.4.3 and up, and in Opera mini with `-o-` prefix. Yes, I am applying it to the image, and not the container. Using the flex on the images instead, would mess with their aspect ratio, making them disproportional. – P3t3r6 Dec 13 '15 at 02:48
  • @Tom wait, imma check the fiddle – P3t3r6 Dec 13 '15 at 02:48
  • 1
    The whole point of object-fit: cover is that it preserves the aspect ratio. – teynon Dec 13 '15 at 02:51
  • @Tom Yea ... but I thought that it needed a parent, in order to adjust its height and width to the parent's ... ? I can't really explain my it, but yea, I get it now ... That seems to work, thanks :) (Add your solution the the answers so I can 1+ it) – P3t3r6 Dec 13 '15 at 02:59

7 Answers7

188

For object-fit to work, the image itself needs a width and height. In the OP's CSS, the images do not have width and/or height set, thus object-fit cannot work.

The clue: width and height need NOT be the dimensions of the image itself! Think of it as if it were a div: If you want a div to fill its container, you will set

width:100%; height:100%;

...and the browser will know that this div should completely fill its container's space.

In case of an img, the browser performs two steps:

  1. The browser creates a bounding box: By default, the box dimensions will be the exact dimensions of the image itself. But we're free to tell the browser to size the image to 100% of its container's width and 100% of its container's height. Then it will create a box that completely fills the container's space.
  2. The browser fits the image pixels into this box: By default, the image will be squeezed/stretched so the image width matches the box width, and the image height matches the box height. But using object-fit, you can select how to match image and box dimensions. For example, using object-fit:cover commands to enlarge/downsize the image to completely fill the box while maintaining its aspect ratio.

Regarding the OP, I would simply set:

main > section.posts > article > img {
  width: 100%; /* image box size as % of container, see step 1 */
  height: 100%; /* image box size as % of container, see step 1 */
  object-fit: cover; /* matching of image pixels to image box, see step 2 */
}

One final caveat: When using % values for sizing, the container must have a defined width and height for object-fit to work. OP would need to define height in main > section.posts > article.

The Conspiracy
  • 3,495
  • 1
  • 17
  • 18
113

object-fit only affects the way the picture displays inside of the img boundaries.

Object-Fit

The object-fit CSS property sets how the content of a replaced element, such as an <img> or <video>, should be resized to fit its container.

Replaced Element

elements whose contents are not affected by the current document's styles. The position of the replaced element can be affected using CSS, but not the contents of the replaced element itself.

This means that the object-fit is independent of your article elements as object-fit only cares about the dimensions of the img element.

The point of this is that you need to get the img elements to stretch to those dimensions first. The object-fit only affects the way the picture displays inside of the img boundaries.

Sample Code / Demonstration

$(function() { $("img").resizable(); });
img {
  width: 300px;
  height: 300px;
  border: 1px solid #FF0000;
  background-color: #00FF00;
}

.fill {
  object-fit: fill;
}

.contain {
  object-fit: contain;
}
.cover {
  object-fit: cover;
}
.none {
  object-fit: none;
}
.scaledown {
  object-fit: scale-down;
}

.variant1 {
  max-width: 100px;
}

.variant2 {
  max-height: 100px;
}
<link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<p>Resize images to see properties with different dimensions.</p>

<h1>fill (default)</h1>
<img src="https://i.stack.imgur.com/EtYb2.jpg" class="fill" />

<h1>contain</h1>
<img src="https://i.stack.imgur.com/EtYb2.jpg" class="contain" />

<h1>cover</h1>
<img src="https://i.stack.imgur.com/EtYb2.jpg" class="cover" />

<h1>none</h1>
<img src="https://i.stack.imgur.com/EtYb2.jpg" class="none" />

<h1>scale-down</h1>
<img src="https://i.stack.imgur.com/EtYb2.jpg" class="scaledown" />
<!-- Spacer for scale down scroll annoyance -->
<br /><br /><br /><br /><br /><br /><br />

Solutions to Question

Solution 1: More flex

Using your current HTML structure you can use the snippet below to apply an additional flex inside of each article.

//
//   Image styles are near the end of file
//   (Line 28)
//

body{
    margin: 0 auto; padding: 0;
}
main{
    min-height: 70vh;
    padding: 0;
}
main > section.posts{
    box-sizing: border-box;
    margin: 0; padding: 0;
    display: flex;
  align-content: stretch;
    flex-flow: row wrap;
}
main > section.posts > article{
  outline: 1px solid red;
    width: 22vw;
    min-height: 100vh;
    margin: 0; padding: 0;
    flex-grow: 1;
    overflow: hidden;
    box-sizing: border-box;
  display: flex;
  align-content: stretch;
  align-items: stretch;
}
main > section.posts > article > img{
  object-fit: cover;
  flex: 1;
}
<!--
Basic structure of this file is

<main>
  <section.posts>
      <article> (six of them)
          <image>
-->

<main>
  <section class="posts">
    <article>
      <img src="https://41.media.tumblr.com/tumblr_m6s6d65lE11qdnz8wo1_400.jpg">
    </article>

    <article>
      <img src="https://41.media.tumblr.com/71c1fe7c899cd048fb961d3c1953411b/tumblr_nj24pvINyW1qzq8p3o1_400.jpg">
    </article>

    <article>
      <img src="https://36.media.tumblr.com/3358cb6ac8eaa0e61dffd53bc1bab93d/tumblr_n92l475hol1qlmppmo1_400.png">
    </article>

    <article>
      <img src="https://36.media.tumblr.com/9ad997ca0385a23a8d82ec919da2392c/tumblr_nwcewbFVAL1s71gzco1_400.jpg">
    </article>

    <article>
      <img src="https://41.media.tumblr.com/tumblr_mbl45xDSwj1qfn79co1_400.jpg">
    </article>

    <article>
      <img src="https://41.media.tumblr.com/1c3718e71a2aa5acaaaf4af654991c91/tumblr_nx6psaH67d1tvh80lo1_400.jpg">
    </article>
  </section>
</main>

Solution 2: Remove article elements

Or you could restructure your html to remove the article elements and flex the img elements.

    body{
        margin: 0 auto; padding: 0;
    }
    main{
        min-height: 70vh;
        padding: 0;
    }
    main > section.posts{
        box-sizing: border-box;
        margin: 0; padding: 0;
        display: flex;
        flex-flow: row wrap;
    }
    main > section.posts > img{
      outline: 1px solid red;
        width: 22vw;
        min-height: 100vh;
        margin: 0; padding: 0;
        flex-grow: 1;
        overflow: hidden;
        box-sizing: border-box;
    }
    main > section.posts  > img{  /* Our suspect */
      object-fit: cover;
    }
    <main>
      <section class="posts">
    
          <img src="http://41.media.tumblr.com/tumblr_m6s6d65lE11qdnz8wo1_400.jpg">

          <img src="http://41.media.tumblr.com/71c1fe7c899cd048fb961d3c1953411b/tumblr_nj24pvINyW1qzq8p3o1_400.jpg">
        

        
          <img src="http://36.media.tumblr.com/3358cb6ac8eaa0e61dffd53bc1bab93d/tumblr_n92l475hol1qlmppmo1_400.png">
        

        
          <img src="http://36.media.tumblr.com/9ad997ca0385a23a8d82ec919da2392c/tumblr_nwcewbFVAL1s71gzco1_400.jpg">
        

        
          <img src="http://41.media.tumblr.com/tumblr_mbl45xDSwj1qfn79co1_400.jpg">
        

        
          <img src="http://41.media.tumblr.com/1c3718e71a2aa5acaaaf4af654991c91/tumblr_nx6psaH67d1tvh80lo1_400.jpg">
        
      </section>
    </main>
teynon
  • 7,540
  • 10
  • 63
  • 106
21

Here's what is says in the spec:

5.5. Sizing Objects: the object-fit property

The object-fit property specifies how the contents of a replaced element should be fitted to the box established by its used height and width.

I focused on... fitted to the box established by its used height and width.

So I added height and width attributes to your img elements, and it seems to work now.

Revised Codepen

To remove the tiny line of whitespace under each image, add vertical-align: bottom to the img. For an explanation see here: Mystery white space underneath image tag

As a side note, you may want to consider browser support for:

  1. object-fit (no IE support)
  2. main (no IE support)
  3. flexbox (consider prefixes)
notapatch
  • 6,569
  • 6
  • 41
  • 45
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • Still not working for me :/ And that wouldn't be too maintainable, because I won't know the images dimensions in the future. Thank you anyways :) – P3t3r6 Dec 13 '15 at 03:07
  • 1
    The demo works fine on this end. Also, in all examples I've seen (MDN, Opera, etc), the images have a defined height and width. I understand that doesn't work for you, but it *may* be a requirement for `object-fit` to work. – Michael Benjamin Dec 13 '15 at 03:15
  • 1
    "I focused on... _fitted to the box established by its used height and width_." This was key. Thanks! – Perry Holden Sep 28 '22 at 14:20
6

I had a similar problem where object fit was not working. I added max-width to the image and it worked.

.myImg {
    object-fit: cover;
    max-width: 100%;
    object-position: center;
}

Alfrex92
  • 6,278
  • 9
  • 31
  • 51
4

I found a very easy trick which worked best for me, but first thanks to tenyon for inspiration from his answer.

you can simply put the img element in your desired div element of any size, then give your image width and height of inherit then give it whatever object-fit value you want, it will work perfect.

1

I changed the container, image and the parent of the container to box-sizing: content-box since img is replaced and switched the object-fit: cover on the container instead of the img. Since img is expected to be cropped, a height of 100vh and a width of 100% and +22hw offset worked good on the top four, there seems to be a little distortion both the bottom two img, not much. object-position still doesn't work for me (never does) :-\

http://codepen.io/01/pen/zrvdaz?editors=110

body{
    margin: 0 auto; padding: 0;
}
main{
    min-height: 70vh;
    padding: 0;
}
main > section.posts{
    box-sizing: content-box;
    margin: 0; padding: 0;
    display: flex;
    flex-flow: row wrap;
}
main > section.posts > article{
  outline: 1px solid red;
    width: 22vw;
    min-height: 100vh;
    margin: 0; padding: 0;
    flex-grow: 1;
    overflow: hidden;
    box-sizing:content-box;
  object-fit: cover;

}
main > section.posts > article > img{
 display: block;
  box-sizing:content-box;
  max-height: 100vh;
  width: calc(100% + 22vh);
  object-position: 100% 100%;
}
zer00ne
  • 41,936
  • 6
  • 41
  • 68
0

instead of using object-fit in img tag, you can use background-size in div tag, it's work well for me. my css code just look like this

{
  background-size: cover;
  background-repeat: no-repeat;
  background-position: center;
  display: inline-block;
  padding: 0px;
  margin: 0px;
}