2

I have two input elements in a flexbox:

<div style="display: flex; width: 200px; background: black; padding: 2px">
  <input style="flex: 1" type="text" />
  <input style="flex: 1" type="text" />
</div>

(fiddle)

I want those to get the width of 200px evenly shared. They aren't however. Instead, they have have some mysterious default size. They don't listen to min-width either. They do listen to width though, so this does the desired thing:

<div style="display: flex; width: 200px; background: black; padding: 2px">
  <div style="flex: 1">
    <input style="width: 100%" type="text" />
  </div>
  <div style="flex: 1">
    <input style="width: 100%" type="text" />  
  </div>
</div>

(fiddle)

My question: why? And is this defined somewhere for some reason?

EDIT: This is what Chrome's inspector gives me:

enter image description here

EXTRA QUESTION:

As kukkuz pointed out, min-width is heeded - but only when the inputs are direct children of the flex container. Otherwise, they again like to be broader:

<div style="display: flex; width: 200px; background: black; padding: 2px">
  <div style="background: red; padding: 2px">
    <input style="flex: 1; min-width: 0" type="text" />  
  </div>
  <div style="background: red; padding: 2px">
    <input style="flex: 1; min-width: 0" type="text" />  
  </div>
</div>

(fiddle)

Bizarre. Is there a way to make this work without restorting to a width: 100%?

EDIT:

There is a way without resorting to a width: 100%: A nested flexbox. (fiddle)

<div style="display: flex; width: 200px; background: black; padding: 2px">
  <div style="background: red; padding: 2px; flex: 1; display: flex; min-width: 0">
    <input style="min-width: 0; flex: 1" type="text" />  
  </div>
  <div style="background: red; padding: 2px; flex: 1; display: flex; min-width: 0">
    <input style="min-width: 0; flex: 1" type="text" />  
  </div>
</div>
John
  • 6,693
  • 3
  • 51
  • 90
  • Are you trying to avoid setting `width: 100%` on the `input`? ... If so, why? – Asons Sep 10 '17 at 07:32
  • I sometimes like to get the bottom of things. It's more a curiosity-driven question at this point. – John Sep 10 '17 at 08:11

2 Answers2

4

Input element's width behaviour is mysterious
My question: why? And is this defined somewhere for some reason?

There is nothing mysterious here. An input element without a set width get its size from its size attribute, which defaults to 20.

Based on your 2nd fiddle, if you remove width: 100% and set the size to 5, you'll see it changes

<div style="display: flex; width: 200px; background: black; padding: 2px">
  <div style="flex: 1">
    <input style="" type="text" size="5" />
  </div>
  <div style="flex: 1">
    <input style="" type="text" size="5" />  
  </div>

Since the size attribute is based on n amount of character, it will be difficult to use it to match a parent's set width, so either use the CSS property width or one of the Flexbox properties flex-grow/flex-basis (nesting them included) to make them ...get the width of 200px evenly shared


EXTRA QUESTION:
As pointed out, min-width is needed - but only when the inputs are direct children of the flex container. Otherwise, they again like to be broader.
Bizarre.

Still nothing strange (or bizarre), as when they aren't flex items (children of a flex container), they yet again become standard input elements and my first explanation applies.

Is there a way to make this work without resorting to a width: 100%?

Yes, as you suggest your self, nest Flexbox so the inputs become flex items, though it appears unnecessary to do that when you simply can drop their parents (the extra div wrappers).


Based on the given comments, the min-width: 0 does work because a flex items default flex-basis is auto, which the specs. translate to:

auto

When specified on a flex item, the auto keyword retrieves the value of the main size property as the used flex-basis. If that value is itself auto, then the used value is content.

Here is a great answer (where the above comment is taken), that explain flex-basis a little deeper

Asons
  • 84,923
  • 12
  • 110
  • 165
  • Ok, that explains why inputs are special. I doesn't yet explain why a `min-width: 0` as a flex child makes it ignore the `size` attribute whereas as a non-flex child it has no effect. – John Sep 10 '17 at 08:06
  • @John See my last comment below _kukkuz_ answer – Asons Sep 10 '17 at 08:07
  • I read that, but: If that was true than either `size` shouldn't matter when it isn't a flex child or `min-width: 0` shouldn't have any effect when it is a flex child. – John Sep 10 '17 at 08:10
  • @John I guess you might misunderstood, it is the exact opposite. – Asons Sep 10 '17 at 08:11
  • Let's say a `input` element isn't a flex child. Then it's `min-width` defaults to zero as you say in the comment. Yet it clearly has a minimum width determined by the size. That means that the `min-width` property isn't what's causing the minimum-width behavior. If that's the case, then why is `min-width: 0` having an effect when it *is* a flex child? – John Sep 10 '17 at 08:14
  • Or more simply: Do you know any way to make `input`s lose their minimum width without resorting to a flex box? If not, then clearly something is missing in the picture, right? – John Sep 10 '17 at 08:16
  • 1
    @John Why `min-width` works on `input` being a flex items is because the _width_ is set to `flex-basis: auto`, hence override the `size`, and then the `min-width: 0` does its job. – Asons Sep 10 '17 at 08:19
  • @John _any way to make inputs lose their minimum width without resorting to a flex box?_ change its `size` value or use `width` – Asons Sep 10 '17 at 08:23
  • @John Be aware, form elements aren't what standard HTML elements are, so you can't apply standard HTML element's logic on them – Asons Sep 10 '17 at 08:27
  • @John What do you wan't to achieve with _...make inputs lose their minimum width_ ? – Asons Sep 10 '17 at 08:29
  • Nothing, that was just a way to clarify what I still thought was mysterious. I think your 4th last comment is what I needed, but I only have my phone right now... will think about this in an hour. – John Sep 10 '17 at 08:33
  • Ok, to this 4th-last comment: `flex-basis: auto` overrides the `size`, but why doesn't `width: auto` do the same thing when not a flex child? – John Sep 10 '17 at 09:33
  • @John Because the default of `width` is `auto`, hence the `size` is used, so bottom line, if not a _width_ is set, the `size`kicks in – Asons Sep 10 '17 at 09:40
  • That would mean that the `auto` for `flex-basis` and the `auto` for `width` mean different things, correct? – John Sep 10 '17 at 09:42
  • 1
    @John Not in itself as both says _size me based on content_, but a flex item also has `min-width: auto`, which makes all the difference since flex items have a different behavior. The linked post describes this very well. – Asons Sep 10 '17 at 09:44
  • Ok, this article says that `width` and `flex-basis` are different when `flex-basis` is `auto`. I still can't [get an `input` to fill it's container without using either `width: 100%` or a flex box](https://jsfiddle.net/tLyouu3t/3/) - but perhaps some things are not for man to know... – John Sep 10 '17 at 09:56
  • @John As I stated in my answer, the only way, if not Flexbox or `width`, is to elaborate with its `size` – Asons Sep 10 '17 at 10:07
1

Input elements have a default computed width due to the user agent / browser. So it responds to width.

You can set min-width: 0 - see demo below:

div {
  display: flex;
  width: 200px;
  background: black;
  padding: 2px;
}

div input {
  min-width: 0;
  flex: 1;
}
<div>
  <input type="text" />
  <input type="text" />
</div>
kukkuz
  • 41,512
  • 6
  • 59
  • 95
  • You're right. I thought I tried that. At least Chrome doesn't tell me about that though - the inspector doesn't show where the width is coming from in that case. – John Sep 09 '17 at 13:44
  • Added what's in the computed section in this case. As you see, it's greyed out which means Chrome can't tell me the rule the width is coming from. Super-confusing. – John Sep 09 '17 at 13:47
  • I have a slight variation of the problem coming up as `inputs` are often nested in `divs` - thought it was too similar to warrant a new question. – John Sep 09 '17 at 17:23
  • @John `flex: 1` (and `min-width: 0` on the flex child) only applies to *flex children* (*flexbox* behaviour only applies to direct children of the flexbox container).... see https://jsfiddle.net/9cgd78uh/ – kukkuz Sep 09 '17 at 17:29
  • But that's using `width: 100%`. The `min-width: 0` really shouldn't have had anything to do with the flexbox and it's only necessary for `input` children. In your last fiddle, you can just remove it as simple `div`s don't need it.(And `flex: 1` was missing but doesn't make a difference.) – John Sep 09 '17 at 17:32
  • 2
    `min-width: auto` is the default for *flex children* which means it takes the width of the content (here the *default* width of the `input`)... when we set it to `min-width: 0` the flexbox can shrink beyond the *default* – kukkuz Sep 09 '17 at 17:34
  • Right, `min-width` *is* necessary on the divs if the contents are an `input` ([fiddle](https://jsfiddle.net/s06L5sut/)). I still don't get why a `min-width: 0` works on an input when it's a direct child of a flex container but not when it's in a div that is itself already correctly sized. – John Sep 09 '17 at 17:42
  • `min-width` works with `flex: 1` here... if its nested, the intrinsic size of the `input` may cause an *overflow* as it is *not* a flex child... that's how things work in css I guess :) – kukkuz Sep 09 '17 at 17:46
  • 1
    @John `min-width` on a direct child of a flex container, a flex item, defaults to `auto`, but on a non flex item it defaults to `0`, hence you won't see any difference on regular items – Asons Sep 10 '17 at 07:27