Skip to content

[css-grid] Stretching image grid items in both dimensions #523

Closed

Description

@MatsPalmgren

I'm wondering about how we should stretch grid items that has
an intrinsic ratio, such as images. The Grid spec just refers to
css-align which says:
https://drafts.csswg.org/css-align-3/#justify-self-property
"the stretch keyword sets the box’s used size to the length necessary
to make its outer size as close to filling the alignment container
as possible while still respecting the constraints imposed by
min-height/min-width/max-height/max-width."

which I think means that having 'stretch' in both dimensions
will resize the image to fill the grid area without respecting
the image aspect ratio
. I think this is a rather unfortunate
default behavior for Grid.

Some background; this topic was discussed for flex items here:
https://lists.w3.org/Archives/Public/www-style/2012Oct/0781.html
where everyone seems to agree that respecting the ratio is desirable,
but for various flex layout specific reasons, this could not be
achieved and it was decided to ignore the ratio (IIUC).

As far as I can tell, those reasons do not apply to Grid, so I see
no reason why we can't respect the ratio when stretching grid items
in both dimensions.

I think web authors generally prefer to preserve aspect ratios,
so that's what I think we should do for grid items.

Activity

  1. mrego commented on Sep 22, 2016

    @mrego
    Member

    We were discussing that yesterday at TPAC (@fantasai, @jensimmons and me).
    The conclusion we got was that the image should stretch (grow or shrink) in both directions, so we don't respect the aspect ratio unless you manually set width (e.g. width: 100%) or use a different value for alignment (like "start").

  2. fantasai commented on Sep 22, 2016

    @fantasai
    Collaborator

    Well, actually manually setting the width won't cause the aspect ratio to be observed: it just sets the width in that dimension, and since the initial value of align-self is stretch, the other axis will continue to just stretch.

    Squishing images seems a little odd, but as a starting point it's useful: the object-fit options are then only one step away, and the alignment options can be used to release the stretch in either or both axes easily.

  3. fantasai commented on Sep 22, 2016

    @fantasai
    Collaborator

    (Plus it's consistent with how blocks behave so not surprising at all.)

  4. MatsPalmgren commented on Sep 22, 2016

    @MatsPalmgren
    Author

    @mrego I don't think that solution works, because setting width:100%
    might cause the image height to overflow the grid area. So the author
    needs to know upfront the relative ratio of each image vs its grid area
    to know which dimension to stretch. This is very inconvenient.

    My proposal doesn't have that problem.
    (and if by chance an author wants a ratio-destroying stretch to fill
    its area completely, they can simply use width:100%;height:100%)

  5. MatsPalmgren commented on Sep 22, 2016

    @MatsPalmgren
    Author

    @fantasai, I don't think object-fit:contain works either since
    it works on the content box, not the margin box as we want for
    grid items. So if you add padding/border/margin to the image it
    will cause overflow. Besides, the rule becomes somewhat elaborate
    and requiring that authors comes up with workarounds like that for
    something that ought to be the default behavior is inconvenient.

  6. fantasai commented on Sep 23, 2016

    @fantasai
    Collaborator

    Cover example, image proportionally sized and clipped to fit:

      img { object-fit: cover; }
    

    Contain example, margin/border/padding fitted to grid slot and image proportionally sized into it:

      img { object-fit: contain; }
    

    Contain example, margin/border/padding fitted to proportionally scaled-down image:

      img { justify-self: center; align-self: center; min-width: 100%; min-height: 100%; box-sizing: border-box }
    

    Contain example with future syntax, margin/border/padding fitted to proportionally scaled-down image:

      img { foo-self: center; max-size: fill; }
    
  7. MatsPalmgren commented on Sep 25, 2016

    @MatsPalmgren
    Author

    img { object-fit: cover; }

    As you say, this leads to the image being clipped and is thus
    not a solution to the problem at hand.

    img { justify-self: center; align-self: center; min-width: 100%; min-height: 100%; box-sizing: border-box }

    This leads to the image overflowing when the window is very wide
    or very narrow. Thus it is not a solution to the problem at hand.
    (also, having a margin doesn't seem to work?)
    I've made a demo here:
    https://people.mozilla.org/~mpalmgren/tests/grid/grid-align-center-min-width-demo.html
    (Chrome has some problems when resizing this demo)

    img { foo-self: center; max-size: fill; }

    Suggesting magic future tech to solve this problem isn't serious.
    Besides, it still requires that you write the above workaround rule to get
    what ought to be the default behavior.

    img { object-fit: contain; }

    I've made a demo of object-fit:contain here:
    https://people.mozilla.org/~mpalmgren/tests/grid/grid-object-fit-contain-demo.html
    (Firefox has some problems with this demo at the moment)

    I see the following problems:

    1. Like with most object-fit values, it makes the image scale down
      inside its content box. This leads to gaps between the image
      and the border. (Try resizing the window to be very wide or
      very narrow with the demo above.) This leads to ugly layout
      if you try to use a border, box-shadow, outline etc, since users
      expects such decorations to wrap the image.
    2. Since the image doesn't fill the content box, I suspect this
      also leads to other problems... like CSSOM reporting the "wrong"
      image size, the baseline not having any relation with the actual
      image position etc. Visual effects such as opacity, filter etc,
      also applies in the gaps, i.e. "outside" the image proper. I also
      suspect min/max/-width/-height will be awkward to use when
      the image doesn't fill its content box.
    3. It requires using object-fit which I suspect is a lesser known
      property.
    4. It requires adding a rule to get the behavior that really ought
      to be the default: it's preferable if layout preserves the intrinsic
      ratio by default (which some CSSWG members seem to agree
      with in the earlier discussion about flex items).

    My proposal doesn't have any of the above problems and it provides
    the desired behavior by default.

  8. MatsPalmgren commented on Sep 27, 2016

    @MatsPalmgren
    Author

    To be clear, what I'm proposing is that spec says something like this
    for the stretch/stretch case:

    If the grid item has an intrinsic ratio, then resize the item in a ratio-preserving way
    so that it fills its grid area in one axis without overflowing the other, while also
    respecting its min/max size constraints.

  9. dbaron commented on Sep 28, 2016

    @dbaron
    Member

    (It's possible you might want that rule to be conditional on the element having object-fit: fill.)

  10. cbiesinger commented on Sep 28, 2016

    @cbiesinger

    It seems that the proposed text is a bit underdefined in terms of how min and max sizes interact with the "ratio-preserving way". Also I'm not sure that the current definition of min sizes in grid actually allow you to preserve the aspect ratio if the image is too big in both axes and does not have a width or height explicitly specified on the image.

  11. MatsPalmgren commented on Sep 30, 2016

    @MatsPalmgren
    Author

    (It's possible you might want that rule to be conditional on the element having object-fit: fill.)

    There are some pros and cons with that, but I don't have a preference.
    Either way is fine with me.

  12. dbaron commented on Oct 5, 2016

    @dbaron
    Member

    It seems that the proposed text is a bit underdefined in terms of how min and max sizes interact with the "ratio-preserving way".

    Presumably using the rules in CSS2 section 10.4 that apply to this case.

  13. dbaron commented on Oct 5, 2016

    @dbaron
    Member

    Just discussed in today's teleconference (I'll try to link minutes later). The conclusion is that we can change the mapping of align-content/justify-content: normal so that normal doesn't turn into stretch for replaced elements in grid.

  14. 72 remaining items

  15. css-meeting-bot commented on May 10, 2017

    @css-meeting-bot
    Member

    The CSS Working Group just discussed Stretching image grid items in both dimensions.

    The full IRC log of that discussion <dael> Topic: Stretching image grid items in both dimensions
    <dael> Github Topic: https://github.com//issues/523#issuecomment-295075752
    <dael> Rossen: I don't see fantasai yet.
    <zcorpan> Github Topic: https://github.com//issues/523
    <dael> Rossen: Anyone from Mozilla want to handle this? Or do we move on? Current tag is customer not satisfied.
    <dael> TabAtkins: We should wait on fantasai because she might have more to the topic to explore.
  16. css-meeting-bot commented on May 10, 2017

    @css-meeting-bot
    Member

    The CSS Working Group just discussed Stretching image grid items in both dimensions, and agreed to the following resolutions:

    • RESOLVED: ticking with Seattle resolution: making the default instrinsic
    The full IRC log of that discussion <dael> Topic: Stretching image grid items in both dimensions
    <TabAtkins> Yeah, I think that's probably the best error, zcorpan
    <dael> Github topic: https://github.com//issues/523
    <dael> fantasai: In seattle we had three options. One we wouldn't take b/c violates design guidelines. Other two we would have contain & intrinsic size behavior. You could opt into either. We picked intrinsic for the default. There's details in https://github.com//issues/523#issuecomment-295075752
    <dael> fantasai: We closed that, but Mats disagrees with the resolution. All other issues on Grid are closed as of when we stopped accepting issues.
    <dael> fantasai: This issue has a commentor disagreement so comes back to WG. Do we stick or do we change to contain sizing by default and opt-in for intrinsic via keyword-max-content or something like that.
    <dael> Rossen: Opinions?
    <dael> jensimmons: My opinion is I agree #3 should not be considered. I'd be okay with leave as-is, but I agree with Mats that as an author having the default be contain would be more handy and make more sense. We need both as an option and the tool to switch definitely. The default I'd lean contain.
    <dael> TabAtkins: Reason why we didn't go for contain is it puts sizing control in this prop...
    <dael> fantasai: TabAtkins we changed.
    <dael> jensimmons: That was 3 which we agreed not to do
    <dael> fantasai: Option was default is contian on all keywords, not jsut normal.
    <tantek> do we have comments from anyone else who is actually implementing this besides Mats?
    <tantek> reviews the issue
    <dael> jensimmons: Ideally we would have tool to switch between, but the wayt he world works if we set default to contain we would get the switching tools quicker. Not certainly, but might.
    <rachelandrew> I'm still keen on the resolution
    <dael> Rossen: But forcing a less then optimal default as a forcing tool i sn't doing much good.
    <tantek> long issue is long
    <dael> jensimmons: Agreed. I still like contain as a default. That's a secondary non-heavy
    <dael> TabAtkins: I'm concerned that when we have contain sizing....having different defaults based on layout of parent it makes the design confusing. It's better if we have consistancy.
    <dael> jensimmons: [missed]
    <Rossen> +1 to what Tab said
    <dael> fantasai: Flexbox resizes to fit hte container. It does only do that with a single line. If you have wrapping it takes intrinisic
    <dael> TabAtkins: It obeys constraint of flexbox and a bit of aspect ratio magic. The sizing is normal flexbox, not just images.
    <dael> jensimmons: You can make the same arguments here.
    <dael> TabAtkins: I disagree. Part of flex is doing this one thing. We're not adding a different way of sizing.
    <dael> jensimmons: I think from author prospective there would be something similar to having default of flexbox where they are both text and image contained. If there's an image just left with intrinisic size it starts to overflow and that's not typically what authors want. Authors expect content to stay in grid cells.
    <tantek> "won't spill outside" e.g. the [CSS is Awe]some problem
    <dael> fantasai: Things that are smaller then grid size, contain will cause them to size up.
    <dael> rachelandrew: I don't like the upscalling. I like the original resolution b/c i t's the most consistant and easier to explain. the upscalling will cause problems.
    <tantek> didn't follow Rachel's comment
    <gregwhitworth> +1 to TabAtkins rachelandrew
    <dael> fantasai: Another thing to consider is grid is being deployed and we don't have a definition of contains that WG approved. Changing will c ause impl stress.
    <dael> TabAtkins: Adding that, even if we had a contain definition, it's still transition stress because it's shipped without this. They're getting things to look well and then this change will break pages.
    <dael> fantasai: I would say if it was significantly better thing to do it might be worth doing, but since we're debating and there's good for both sides, given the status we're at it makes sense to go with intrinsic a nd add the contain keyword. That would be my position.
    <dael> TabAtkins: I agree.
    <rachelandrew> +1 to fantasai
    <dael> fantasai: I'm sympathetic, but it's not so clearly better that it's definitely the right answer.
    <dael> TabAtkins: I would also threat it differently if it was obvious fix instead of possibly better.
    <dael> Rossen: I'm seeing people favor option 1. Let's try for resolution.
    <dael> Rossen: Unless jensimmons you feel there's something else you want to add.
    <dael> jensimmons: I don't want to block it, but I think we need to define contain.
    <dael> fantasai: We have a definition, we need comments. THere is a definition in sizing 4. Mostly waiting for dbaron and Mats there.
    <dael> jensimmons: We should keep going forward on getting that done b/c it's desperately needed.
    <dael> dbaron: Does option 1 match what impl ship today?
    <dael> Rossen: I believe so.
    <dael> tantek: It does.
    <dael> s/tantek/ TabAtkins
    <dael> jensimmons: I'm curious about that. I'm not sure what Mats impl and he did Gecko.
    <dael> TabAtkins: I'd hope he's not impl something different. Even if he is, the other browsers aren't.
    <dael> dbaron: I would disagree with TabAtkins' hope. But I don't know what he did.
    <tantek> this issue feels like it has many aspects, are there at least some aspects we can converge on?
    <dael> Rossen: Let's go back to this. Sincec Mats' isn't here I'd liket o call for consensus on #1. We'll continue working on contain.
    <tantek> I'm having trouble keeping track of n resolutions over the past on this and n options
    <dael> Rossen: Obj to sticking with Seattle resolution: making the default instrinsic?
    <fantasai> testcase -
    <jensimmons> we don’t have interop on https://jsfiddle.net/1fd948nz/1/ at the moment, fyi
    <dael> RESOLVED: ticking with Seattle resolution: making the default instrinsic
  17. atanassov commented on May 10, 2017

    @atanassov
    Contributor

    Test case for the above discussion added by fantasai:
    https://software.hixie.ch/utilities/js/live-dom-viewer/?saved=5143

  18. fantasai commented on Dec 4, 2017

    @fantasai
    Collaborator

    Was just tech-editing someone's introduction to Grid Layout and noticed her description of the default alignment behavior for grid: it's stretching unless there's a specified size, in which case it's start. Having replaced elements behave as start by default matches this -- technically they don't have a “specified” size, but the intrinsic size stands in for that specified size, yielding consistent behavior for items that have a concrete size. I think this behavior makes sense and is understandable for authors.

  19. added 3 commits that reference this issue on Dec 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions