Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select element grows differently than input in display flex

Tags:

html

css

flexbox

I'm getting an unexpected behavior in my setup. The inputs grow horizontally as expected but on the row with a select control, the growth seems to be distorted.

I suspected some style to be different but a close inspection led me nowhere. Googling gave nothing and I can't find anything about implicit margin nor padding for selects.

What is this about and how do I kill it?

div.full-page {
  margin: 20px;
  padding: 20px;
  background: ghostwhite;
}

div.input-section {
  border: 3px none darkorchid;
  width: 600px;
}

div.input-title {
  font-family: Arial, Helvetica, sans-serif;
  font-weight: bold;
  font-size: 18px;
  border-bottom: 2px solid darkorange;
  padding-bottom: 5px;
}

div.input-row {
  border: 3px none darkolivegreen;
  display: flex;
}

div.input-element {
  border: 3px none darkcyan;
  padding: 10px;
  flex-grow: 1;
  // display:flex;
}

div.input-element input,
div.input-element select {
  width: 100%;
  // border: solid 1px mediumvioletred;
  // padding: 0;
  // margin: 0;
}

div.input-caption {
  font-family: Verdana, Geneva, Tahoma, sans-serif;
  color: darkgrey;
  font-size: 14px;
}
<div class="full-page">

  <div>

    <div class="input-section">
      <div class="input-title">Title 1</div>

      <div class="input-row">
        <div class="input-element">
          <div class="input-caption">Uno</div>
          <input type="text" placeholder="Konrad">
        </div>
        <div class="input-element">
          <div class="input-caption">Duo</div>
          <input type="text" placeholder="Viltersten">
        </div>
      </div>

    </div>

    <div #privs class="input-section">
      <div class="input-title">Title 2</div>

      <div class="input-row">
        <div class="input-element">
          <div class="input-caption">Tress</div>
          <input placeholder="Is really">
        </div>

        <div class="input-element">
          <div class="input-caption">Quatro</div>
          <select>
            <option>The one and only</option>
          </select>
        </div>
      </div>

    </div>

</div>
like image 472
Konrad Viltersten Avatar asked Mar 30 '17 16:03

Konrad Viltersten


People also ask

Does display flex inherit?

The display property is not inherited, so display: flex is not either.

What happens when display property is set to flex?

If the items don't have a size then the content's size is used as the flex-basis. This is why when we just declare display: flex on the parent to create flex items, the items all move into a row and take only as much space as they need to display their contents.

Why Flex-grow is not working?

Firstly, you can't apply a fixed width AND flex-grow. Secondly, flex-grow only works if the parent element has display:flex . In this case the section has display flex but the links do not and the flexgrow divs are children of the link…not the section.


2 Answers

You're using flex-grow: 1 to size your flex items. That's fine when all items are identical or contain identical content.

Except one of your flex items is different. It has the select element. That will affect the sizing of the item because an initial value of a flex item is flex-basis: auto.

With flex-basis: auto the flex-grow property goes into effect after the width of the item is factored in. Because the width of your items are different, their size after flex-grow is applied will be different.

You need to use flex-basis: 0, which allows flex-grow to ignore the width of the item and focus only on the available space in the container.

Instead of flex-grow: 1 use this:

  • flex: 1

Which is shorthand for:

  • flex-grow: 1
  • flex-shrink: 1
  • flex-basis: 0

See the spec for more details: https://www.w3.org/TR/css-flexbox-1/#flex-common

Also, to counter problems such as these, the spec recommends always using the flex shorthand as opposed to longhand properties:

7.2. Components of Flexibility

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

like image 93
Michael Benjamin Avatar answered Mar 16 '23 20:03

Michael Benjamin


The parent of the select needs to be set at 100% for it to stretch since now it's constrained.

.input-element {width:100%;}

By the way, it has nothing to do with the flex-grow because the issue of width still existed when I removed that style, which led me to see it was the containing element's problem :)

https://jsfiddle.net/hhft4ke6/

div.full-page {
  margin: 20px;
  padding: 20px;
  background: ghostwhite;
}

div.input-section {
  border: 3px none darkorchid;
  width: 600px;
}

div.input-title {
  font-family: Arial, Helvetica, sans-serif;
  font-weight: bold;
  font-size: 18px;
  border-bottom: 2px solid darkorange;
  padding-bottom: 5px;
}

div.input-row {
  border: 3px none darkolivegreen;
  display: flex;
}

div.input-element {
  border: 3px none darkcyan;
  padding: 10px;
  flex-grow: 1;
  width:100%;
  // display:flex;
}

div.input-element input,
div.input-element select {
  width: 100%;
  // border: solid 1px mediumvioletred;
  // padding: 0;
  // margin: 0;
}

div.input-caption {
  font-family: Verdana, Geneva, Tahoma, sans-serif;
  color: darkgrey;
  font-size: 14px;
}
<div class="full-page">

  <div>

    <div class="input-section">
      <div class="input-title">Title 1</div>

      <div class="input-row">
        <div class="input-element">
          <div class="input-caption">Uno</div>
          <input type="text" placeholder="Konrad">
        </div>
        <div class="input-element">
          <div class="input-caption">Duo</div>
          <input type="text" placeholder="Viltersten">
        </div>
      </div>

    </div>

    <div #privs class="input-section">
      <div class="input-title">Title 2</div>

      <div class="input-row">
        <div class="input-element">
          <div class="input-caption">Tress</div>
          <input placeholder="Is really">
        </div>

        <div class="input-element">
          <div class="input-caption">Quatro</div>
          <select>
            <option>The one and only</option>
          </select>
        </div>
      </div>

    </div>

</div>
like image 28
Rachel S Avatar answered Mar 16 '23 22:03

Rachel S