Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do flexbox item images resize differently according to their initial size?

Tags:

css

image

flexbox

I have four images: two small, two big (dimensions shown in html). They all have their img width set to 100% but their parent div is set to a specific width. When I resize the browser window the smaller images shrink and the larger ones don't, right away.

I have a red border around the divs and green border around the imgs. The smaller images' green borders shrink before the larger ones. Why is that?

http://jsfiddle.net/brcrnj80/6/

img {
  border: 3px solid green;
  width: 100%;
}

.item {
  border: 1px solid red;
  max-width: 250px;
  min-width: 60px;
  margin: 10px;
}

Thanks

like image 810
tazboy Avatar asked Feb 17 '15 18:02

tazboy


People also ask

How does flexbox define size?

The main size of a flex item is the size it has in the main dimension. If you are working in a row — in English — then the main size is the width. In a column in English, the main size is the height. Items also have a minimum and maximum main size as defined by their min-width or min-height on the main dimension.

Which of these properties control the size of Flex items?

The flex-shrink property. The flex-shrink property specifies the flex shrink factor, which determines how much the flex item will shrink relative to the rest of the flex items in the flex container when negative free space is distributed.


1 Answers

tl;dr: The items are resizing differently because they have a different flex-basis, which is based on the image size and is the value that they start flexing (shrinking) from. Every item has to shrink, but the larger items shrink from a larger starting-point, so they're still larger after the shrinking. (There's also a late-in-the-algorithm "clamp" to prevent them from being bigger than their max-width; this is what keeps the large items from being crazy-huge in this case. But importantly, they start their shrinking from their flex-basis, and the max-width clamp is an afterthought.)

FIX: If you give each flex item the same flex-basis, e.g. flex-basis:250px (the same as their max-width), you'll probably get the result you're looking for. Updated fiddle: http://jsfiddle.net/brcrnj80/10/

(As noted in another answer, flex: 1 1 0 (which can be expressed more concisely as flex:1) will also work -- that's setting the flex-basis to 0, and allowing the flex items to grow (instead of forcing them to shrink) from there, up to their max-width. Produces the same results, just via a different route.)

LONGER EXPLANATION: Here's what happens:

  1. By default, everything has flex-basis:auto, which in this case means that each flex item starts out its flexing at its image's intrinsic width. So your huge-image flex items have a huge flex basis, and your small-image flex items have a small flex basis.
  2. We see if the sum of the flex items' flex-basis values are larger than the container. They are (because some of your images are huge). So, we have to shrink things.
  3. We shrink each flex item "fairly", starting from its flex-basis, by whatever portion is necessary to make all of the items fit. So e.g. each item loses 1/4 of its width, for example (if that happens to be the right fraction to make them all exactly fit the container).
  4. NOW, we check if any of these "tentative" item sizes violate the item's max-width. Your flex items with large images will likely violate their max-width at this state, because e.g. even if we take away 1/4 of their size (in my example), they're still much larger than their max-width:250px. For any such violations, we freeze the item at its max-width, and we restart the shrinking process. (We do something similar for min-width violations.)
  5. In the restarted shrinking process, the large images are frozen at 250px-width, and the smaller images are responsible for all of the shrinking.

So if there's not enough space for everyone to have 250px of width, your small flex items end up having to do all of the shrinking. (Unless we're constrained enough that the large items would be shrunk to be less than 250px in the first round of shrinking -- e.g. if we're shrinking each item by 90%, say. Though, then the small items will also be shrunk by 90%, and they'll be less than their min-width:60px, and they'll get frozen at that size and we'll restart the shrinking in the same way that I described above).

See the "Resolving Flexible Lengths" chunk of the spec for more details if you're curious.

like image 128
dholbert Avatar answered Oct 12 '22 23:10

dholbert