- From: Tab Atkins Jr. <jackalmage@gmail.com>
- Date: Mon, 7 Oct 2013 16:10:33 -0700
- To: www-style list <www-style@w3.org>
I've been thinking about this lately, and I think I made a mistake in how I specified the behavior of 'flex-grow' values greater than 0 but less than 1. The current behavior isn't compatible with animation, and a small fix would also enable a useful behavior for authors. I believe this mistake can be safely corrected with insignificant, if any, compat problems. # Problem Right now, the spec treats flex-grow values between 0 and 1 the same as values 1+ - they get normalized into a share of the free space, and then space gets distributed. This means that *any* non-zero value, even something as tiny as .0001, will cause the element to flex and fill its container. This is troublesome when you try to animate between 0 and a non-zero value, because a lone flexible element stays container-filling until the final moment when its flex-grow reaches 0, at which point it's suddenly completely inflexible and flips to its normal size. Because this isn't really "transitioning", I even explicitly disallow animating between 0 and non-zero. This is annoying, because if there are *two* flexible items on the line, then transitioning one of them to 0 *does* work properly - the item gradually shrinks to its hypothetical size, as expected. This problem only occurs when there's only a single flexible item on the line, which is annoying and confusing to authors. As well, this is discontinuous behavior that exposes UA rounding behavior, which is something we try to avoid whenever possible. # Suggested Solution Lightly reinterpret flex to be literally a fraction of the free space, with the usual "1 = 100%" conversion. If the sum of the flexes on a flex line is greater than 1, normalize appropriately, but if not, leave the numbers alone. In specific edits, this would just be a change in the <http://dev.w3.org/csswg/css-flexbox/#resolve-flexible-lengths> section - insert a step 2.5 that checks if the free space is positive and the sum of the flex-grows are <1, and if so, sets all the flex items to their hypothetical main size + the corresponding fraction of the free space, then exits the algorithm. # Benefits This change would allow 'flex' to be animated between 0 and non-zero values in all cases. If there's a single flexible item, as its flex-grow drops below 1, it'll start using less than all of the free space, gradually shrinking to its hypothetical main size, exactly what you get from an inflexible item. This gives us precisely what we want, and eliminates the discontinuity. This has real worth. Without this, you can't easily do flexible accordions, where when everything is closed they pack toward flex-start, but when a section is expanded it fills the available space. Another unexpected benefit of this is that it allows a reasonable, though not perfect, solution to the "items on the last flex-line are way too big" problem, where the last line in a multi-line flexbox sometimes has 1 or 2 items which stretch to fill the entire line, ending up ridiculously larger than all the other items in the flexbox. This can be fixed by, rather than specifying everything with a flex of "1", instead specifying a flex of the maximum fraction of the line you want something to fill, approximately. For example, if your flexbox will typically have 4-6 items per line, just set each to "flex: .25", and the ones on the final line will be reasonably sized, while the rest of the lines are unaffected (the sum of flexes will be 1 to 1.5, which means they get normalized as usual and soak up all the free space). This requires you to guess how many items will fit on a line, which isn't ideal, but is often good enough. I plan to address this more thoroughly in Flexbox 2. # Compat Risk I expect the compat risk for this change to be insignificant, if not nonexistent. This only affects items with a flex value >0 and <1, which should be rare in the first place - the spec only uses integer values, every tutorial I've seen avoids values in that range, and I've never seen real code try to use values in that range either. Further, it only affects these items if the sum of the flexes on the line is less than 1. Two items both with "flex: .5;" will continue to work as normal, for example. I suspect anything hitting this case to be *very* rare. I could use a use-counter to try and track this stuff, but I fear that a 12- to 18-week delay for full results might result in a growth of the usage of this case, as unprefixed Flexbox impls move into the public web. I believe it's safe to make this change as long as we do so quickly. Thoughts? ~TJ
Received on Monday, 7 October 2013 23:11:24 UTC