[css-images] Overconstrained image sizing and preserving aspect ratio: the object-sizing property

Hi all,

At the F2F the other day Simon brought up an image fitting problem we've
been having. It's a very common problem in the EPUB space, but I think
it's a more general problem that we see on the Web, especially in the
context of articles inserted into a template authored by someone else.

Consider these three cases:

* Alice develops a slideshow widget and Bob makes use of this widget on
  his website to show people photos he took on his summer vacation.

* Bob writes an article about How He Spent His Summer Vacation and Alice
  publishes it on her website using CSS Regions & <iframe>.

* Bob creates an EPUB version of his article and readers buy lots of
  copies of it from the iBooks Store. Alice is an engineer on iBooks.

In all three cases, Alice would like to write some CSS to ensure that
images in Bob's document are constrained to their container and maintain
their aspect ratio, but Alice doesn't control Bob's document. Bob may
have explicitly provided width and height values which are much larger
than the container Alice is flowing Bob's content through.

If Bob didn't explicitly provide widths and heights for his images,
Alice could simply do the following in her stylesheet:

img {
  max-width: 100%;
  max-height: 100%;
}

If Bob *did* explicitly set width and height, Alice could do the
following to visually preserve the image's intrinsic aspect ratio:

img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

However, `object-fit' doesn't affect the size of the <img> element but
only where within the <img> the image will be painted. The result for
many images is letterboxing that neither Alice nor Bob want. This is due
to the design of the Default Sizing Algorithm, which favors
author-provided explicit widths & heights over all else.

In Alice's case, what she really wants is a new property that switches
to another sizing algorithm that does the aspect-ratio preserving effect
of `object-fit: contain' at layout time instead of at paint time.
Consider this <img> of Bob's:

<img src=5x3.jpg alt="Image with an intrinsic aspect ratio of 5 by 3"
     width=5000 height=3000>

The image has an aspect ratio of 5:3. Alice wants to have CSS that
favors the intrinsic aspect ratio of the image. Something like this
would do the trick:

img {
  max-width: 100%;
  max-height: 100%;
  object-sizing: prefer-intrinsic;
}

But there's a related case that suggests we need another value for this
new property. Consider this <img> of Bob's:

<img src=5x3.jpg alt="Image with an intrinsic aspect ratio of 5 by 3"
     width=2000 height=1000>

The image has an intrinsic aspect ratio of 5:3, but Bob has specified a
width and height that produce an aspect ratio of 2:1. Alice might want
to have CSS that favors the intrinsic aspect ratio of the image asset,
or she might want to have CSS that favors the aspect ratio implicitly
specified by the author. This case is different from the Default Sizing
Algorithm because the author-supplied width and height are not respected
*as widths and heights* but instead only as the source of an aspect
ratio.

img {
  max-width: 100%;
  max-height: 100%;
  object-sizing: prefer-specified;
}

So here's where we end up:

    Name:           object-sizing
    Value:          auto | prefer-specified | prefer-intrinsic
    Initial:        auto
    Applies to:     replaced elements
    Inherited:      no
    Media:          visual
    Computed value: specified value
    Percentages:    n/a
    Animatable:     no

* auto is the current Default Sizing Algorithm
* prefer-intrinsic prioritizes the image asset's intrinsic aspect ratio
  over the author-supplied one
* prefer-specified prioritizes the author-supplied aspect ratio
  over the intrinsic one

I couldn't come up with a property name or property value names that
a) make it sufficiently clear that this is really about aspect-ratio,
and b) aren't way too long. Bikeshedding is very welcome.


Thanks,
Ted

Received on Friday, 31 January 2014 22:42:52 UTC