Skip to content
This repository has been archived by the owner on Sep 5, 2024. It is now read-only.

flex-grow vs flex #2632

Closed
tkrotoff opened this issue Apr 30, 2015 · 14 comments
Closed

flex-grow vs flex #2632

tkrotoff opened this issue Apr 30, 2015 · 14 comments
Assignees
Milestone

Comments

@tkrotoff
Copy link
Contributor

Edit: my original mistake when I wrote this issue was to believe that flex-shrink in the context of flex-wrap: wrap was responsible for the widgets to shrink below their "natural" size => it is in fact "controlled" (more of a side effect?) by flex-basis.


tl;dr attribute flex-grow is most probably what users want instead of flex.

ngMaterial defines the flex attribute:

[flex] {
  flex: 1; /* Shorthand for flex-grow: 1; flex-shrink: 1 */
}

You "advertise" its use everywhere like it is the most common pattern. The item grows when space is available (good) and shrinks up to nothing if there is no space (not good). I believe this is not the most common use case.
A better approach is to not shrink below the "natural" item/widget size if space is lacking. (If I remember well, this is what GTK+, Qt and Java Swing do).

Demo: http://plnkr.co/edit/vjud32?p=preview

I propose to define flex-grow attribute and use it instead of flex:

[flex-grow] {
  box-sizing: border-box;
  flex-grow: 1;
}

I don't think it is worth to define flex-shrink attribute: I do not believe it is a common pattern.

@ThomasBurleson
Copy link
Contributor

@robertmesserle - I like this. What are your thoughts?

@epelc
Copy link
Contributor

epelc commented Apr 30, 2015

I like this too. I just ran into some buttons shrinking down to nothing because only one had flex in a row of 3. But I only wanted the one to essentially grow. I ended up just using flex-gt-md instead because it was only hiding the other ones on small devices.

@ThomasBurleson What do you think of keeping the flex name instead of using flex-grow? I think it makes sense if there isn't going to be a flex-shrink which I don't think anyone needs. It also makes the -gt-* attributes not supper long. I don't think it'd be fun to type flex-grow-gt-* all day.

@ThomasBurleson
Copy link
Contributor

My thought is to 'add' the flew-grow (and its variations) so it is an
optional.

On Thu, Apr 30, 2015 at 11:01 AM Ed Pelc notifications@github.com wrote:

I like this too. I just ran into some buttons shrinking down to nothing
because only one had flex in a row of 3. But I only wanted the one to
essentially grow. I ended up just using flex-gt-md instead because it was
only hiding the other ones on small devices.

@ThomasBurleson https://github.com/ThomasBurleson What do you think of
keeping the flex name instead of using flex-grow? I think it makes sense
if there isn't going to be a flex-shrink which I don't think anyone
needs. It also makes the -gt-* attributes not supper long. I don't think
it'd be fun to type flex-grow-gt-* all day.


Reply to this email directly or view it on GitHub
#2632 (comment).

@robertmesserle
Copy link
Contributor

@ThomasBurleson Sounds good to me

@macbleser
Copy link

+1. I added [flex-grow] to my own build the other day to provide this functionality. I've used it in a couple scenarios already.

@gkalpak
Copy link
Member

gkalpak commented May 4, 2015

First of all, the argument about flex-shrink is invalid, since according to the spec, the default value for flex-shrink is 1 anyway. I.e. having flex: X and flex-grow: X have the exact same behaviour as far as flex-shrinking is concenred.

Also, there is no difference between flex: X and flex-grow: X as far as flex-growing is concerned (since flex: X is shorthand for flex-grow: X; flex-shrink: 1; flex-basis: 0%).

Thus, the only property affected differently is flex-basis.

  1. flex: X results in flex-basis: 0%
  2. flex-grow: X results in flex-basis: main-size (originally named "auto")

The end-result of both options is showcased in the following figure (Figure 6 from the spec):

The difference between "absolute" flex and "relative" flex
(The three items have flex factors of 1, 1, and 2, respectively.)

IMO, when using the flex attributes, option 1 is what most people are aiming for.
(Especially people not too familiar with Flexbox.)


Also note, that the spec itself encourages the use of the flex property:

Note: Authors are encouraged to control flexibility using the flex shorthand rather than with component properties, as the shorthand correctly resets any unspecified components to accommodate common uses.


Considering all the above, I believe that the current implementation is the best approach.
In both cases, the user has to have a decent understanding of Flexbox, in order to understand the subtleties of what is going on, but at least the current implementation better accomodates common usecases and adheres to the principle of least surprise.

It just might be the case, that I am missing something, so please let me know :)

@tkrotoff
Copy link
Contributor Author

tkrotoff commented May 4, 2015

the argument about flex-shrink is invalid [...] the only property affected differently is flex-basis

You are right.

option 1 (flex-basis: 0%) is what most people are aiming for

Option 1 is easier to explain but then what about items/widgets shrinking below their "natural" size problem when combined with flex-wrap: wrap (edit)?

This is confusing: in the spec, 4 out of the 5 "most common flex values" use main-size instead of the default value 0%.
I believe desktop libraries/frameworks did the job to find out the most common pattern for years: no shrinking below "natural" size (I know about Qt, GTK+, Java Swing - would be interesting to check how WPF, Cocoa, Android UI API... work on this aspect).

@gkalpak
Copy link
Member

gkalpak commented May 7, 2015

Again, using flex-grow: X instead of flex: X will not prevent the element from shrinking below it's natural size. So, all arguments about what other libraries/frameworks do or what is the most common/expected pattern are irrelevant (maybe good points (maybe not), but irrelevant to this discussion).

If you meant to suggest that the flex attribute should set flex-shrink: 0 (instead of leaving the default value of 1) - i.e. that the CSS style should be flex: X 0 instead of flex: X - then I suggest you open a different issue, as this is getting confusing.
(If you do, link back to this issue for context.)

FWIW, I still believe that 0% (and not main-size) is the most expected/intuitive/common value for flex-basis.
Regarding flex-shrink I haven't made up my mind yet, but (between 0 and 1) I believe I am currently leaning toward 1. It's a different discussion though.

@tkrotoff
Copy link
Contributor Author

tkrotoff commented May 7, 2015

@gkalpak

Again,

Again? please re-read my last comment: I'm only talking about 0% vs main-size.

Let me reformulate and simplify my 'new' thoughts: one advantage (huge in my opinion) of flex-basis: main-size vs flex-basis: 0% is that items/widgets do not shrink below their "natural" size when combined with flex-wrap: wrap (edit).

Here my "decision spreadsheet":

Decision spreadsheet

https://docs.google.com/spreadsheets/d/1mWApG2YNVRSVCibfQBKyX7uQcr-qYBB2qbG9jSLIEGk/

@gkalpak
Copy link
Member

gkalpak commented May 7, 2015

Again? please re-read my last comment: I'm only talking about 0% vs main-size.

I did and still... 😃 You seem to be under the impression that flex-basis: main-size prevents elements from being shrunk below their "natural" size, which is not true. Both flex-basis: main-size (which is the default) and flex-basis: 0% (which is the default for omitting the third value of flex: X Y Z), allow the elements to be shrunk below their "natural" size (the only difference pertaining to the way their reduced size is calculated).
Here is a POC CodePen.

Your spreadsheet has a few errors; it's more like:

Advantages flex-basis: 0% flex-basis: main-size
Default value is spec FALSE TRUE
Default value if omitted in flex: X ... TRUE FALSE
Easier to explain TRUE FALSE
Spec "most common flex values" (1) - -
No shrinking below "natural" size FALSE FALSE

(1): I would argue that flex-basis: 0% is the "most common" flex value, but I left that metric out as it is kind of unclear/subjective. Let's summarize what's going on with the special values for the flex style (the way I interpret it):

Special values that use/imply flex-basis: main-size:

  1. flex: initial: Naturally uses the default value (so this is equivalent to Default value in spec).
  2. flex: none: This means that we don't want the element to be flexible, so no wonder we use the element's "natural" size. (This is hardly an argument for main-size being "most common".)
  3. flex: auto: This is indeed a special case, used for having a fully flexible (growing/shrinking) element, which grows/shrinks proportionally to its "natural" size. (Being a special case, it is hardly an argument for main-size being "most common".)

Special values that use/imply flex-basis: 0%:

  1. flex: X: This is the most common use-case, where the user wants to customize the growing factor and here flex-basis defaults to 0%.

Based on the above, my personal impression is that (if you want flexibility) the "most common" case is flex-basis: 0%.

I am not sure how this comes across, so I wanted to point out that I am very glad that such concerns are raised/discussed. I believe that Flexbox is a liberating spec and it will be great if ngMaterial ends up making (and helping developers make) good use of it :)
So, thx @tkrotoff for bringing that up !

@tkrotoff
Copy link
Contributor Author

tkrotoff commented May 7, 2015

You seem to be under the impression [...]

I've omitted to mention in the context of flex-wrap: wrap (otherwise it does not make sense). The original plunker uses flex-wrap: wrap. I've edited my previous comments to make it more clear.

Here your codepen with flex-wrap: wrap: http://codepen.io/anon/pen/GJpLMV

codepen with flex-wrap: wrap

My original mistake when I wrote this issue was to believe that flex-shrink in the context of flex-wrap: wrap was responsible for the widgets to shrink below their "natural" size => it is in fact "controlled" (more of a side effect?) by flex-basis. Thx for pointing that.

@gkalpak
Copy link
Member

gkalpak commented May 7, 2015

OK, I am totally confused now. So what is your suggetion ?

My original mistake [...] was to believe that flex-shrink [...] was responsible for the widgets to shrink below their "natural" size

This was not mistake; this is a correct assumption: flex-shrink is indeed responsible for the widgets shrinking below their "natural" size.

it is in fact "controlled" [...] by flex-basis

flex-basis only determines how much they are going to be shrunk relatively to each other and the container; not whether they are going to be shrunk below their "natural" size.

Even with flex-wrap: wrap, elements can still shrink below their "natural" size (regardless of flex-basis), so I am not really sure how flex-wrap changes anything.

The only difference I see is between flex-shrink: 0 + flex-basis: main-size and flex-shrink: 0 + flex-basis: 0%. The former combo prevents elements form shrinking below their "natural" size, while the latter doesn't.

In order for this discrpancy to appear, one has to explicitly set flex-shrink: 0 (since ngMaterial does not do that afaik), which implies that the user knows enough about Flexbox (or at least they should) to also explicitly set their desired value for flex-basis (although again, I believe that 0% would be the most common usecase).

Since ngMaterial does not set flex-shrink: 0, I don't think it should care what will be the most intuitive behaviour IF the user set flex-shrink: 0. It should be primarily concerned with what is the most intuitive behaviour with the default flex-shrink: 1 value and..yes, you guessed it...I believe in this case flex-basis: 0% makes the most sense 😛

But I would like to hear what you are suggesting, because (like I mentioned in the beginning) it is not clear to me anymore 😕

@robertmesserle robertmesserle modified the milestones: 0.10.0, Backlog May 28, 2015
@robertmesserle robertmesserle modified the milestones: 1.0-beta1, Backlog Aug 4, 2015
@naomiblack
Copy link
Contributor

Unfortunately, I don't think we can get to this before 1.0 (unless, possibly, a PR appears). Contributions welcome but I am pushing this out past beta.

@naomiblack naomiblack modified the milestones: 1.0-beta1, 0.12.0 Aug 14, 2015
@ThomasBurleson
Copy link
Contributor

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants