1

The example snippet below produces a layout like this:

enter image description here

The problem here is when the cyan content is too wide, it increases the size of the parent div, but what I want to happen is for it to decrease the width of the bottom-left div, resulting in something like this:

enter image description here

The inputs in the bottom-left are in a table, and in particular:

  • The select input contains a long option so it's default size is fairly wide, and
  • The textbox input default size is just... wide.

This is all using flex layouts. I'd like to shrink the bottom left by shrinking the width of the inputs only (the label column should remain the same).

Is there a way I can limit the input sizes to never cause the total width of the bottom half to exceed the total width of the top half (yellow)? Basically I want the entire thing to be the width of the yellow box, and the bottom-left div to be the one that shrinks if the bottom-right is too wide.

I do not know the size of the yellow/blue content ahead of time, it's all dynamically generated. All I know is the yellow one is wide enough to comfortably accommodate everything at the bottom assuming I can shrink the inputs a bit.

I am open to the idea of replacing that table with flex divs if needed, it's just the table is a bit easier to lay out for the form down there.

var state = true;
window.setInterval(function () {
  document.getElementById('example-stuff2').style.width = (state ? '10px' : '100px');
  state = !state;
}, 2000);
div { border: 1px solid red; }

#content, #panel, #bottom { display: flex; }
#content, #panel { flex-direction: column; }
#content { align-items: center; }
#bottom-right { flex-grow: 1; }

/* Example placeholders for content of unknown size. */
span { display: inline-block; }
#example-stuff1 { background: yellow; width: 300px; height: 120px; }
#example-stuff2 { background: cyan; width: 100px; height: 10px; }
<div id="content">
  <div id="panel">
    <div id="top"><span id="example-stuff1"></span></div>
    <div id="bottom">
      <div id="bottom-left"> 
        <table>
        <tr><td>Label:
            <td>
              <select>
                <option>Option 1</option>
                <option>Option 2 is a pretty long one</option>
                <option>Option 3</option>
              </select>
        <tr><td>Label:
            <td><input type="textbox" value="example">
        </table> 
      </div>
      <div id="bottom-right"><span id="example-stuff2"></span></div>
    </div>
  </div>
</div>

(Note: The cyan part's width is unknown ahead of time, but it is unchanging once the page is rendered (unlike the snippet). It may be narrow (in which case everything fits) or it may be a bit too wide (in which case I run into the issue where I need to shrink the inputs). The animation in the snippet is just to illustrate the two cases for this question, in reality the cyan content is determined when the page is served and stays that way.)

Jason C
  • 38,729
  • 14
  • 126
  • 182
  • You are using flex that's why it's going like this. – LKG Jul 10 '17 at 02:48
  • @LKG I'm open to non-flex alternatives as well, it's just that flex is, for the most part, keeping everything else on the site pleasantly simple. – Jason C Jul 10 '17 at 02:49
  • So you need that cyan part width has a fixed width ? – LKG Jul 10 '17 at 02:50
  • @LKG The cyan part's width is unknown ahead of time, but it *is* unchanging once the page is rendered (unlike the snippet). It may be narrow (in which case everything fits) or it may be a bit too wide (in which case I run into the issue where I need to shrink the inputs). The animation in the snippet is just to illustrate the two cases, in reality the cyan content is determined when the page is served and stays that way. – Jason C Jul 10 '17 at 02:52

1 Answers1

1

Is there a way I can limit the input sizes to never cause the total width of the bottom half to exceed the total width of the top half (yellow)? Basically I want the entire thing to be the width of the yellow box, and the bottom-left div to be the one that shrinks if the bottom-right is too wide.

The yellow element (#example-stuff1) has a defined width of 300px.

This element is a child of #top, which is a sibling #bottom – your problem element – which has no defined width.

Also, none of the containers have a defined width.

As a result, #bottom has no width limit because it has no width association with #top, and none of its ancestors have a width limit (beyond the standard width: 100% which applies to all block-level elements).

So my first suggestion would be to define a width that binds the width of both rows.

In the next step, you can use flexbox to layout your form elements.

You also need to be aware of the default minimum size of flex items, which will require an override with min-width: 0.

var state = true;
window.setInterval(function () {
  document.getElementById('example-stuff2').style.width = (state ? '10px' : '100px');
  state = !state;
}, 2000);
#bottom-left {
  display: flex;
  flex-wrap: wrap;
  min-width: 0;
}

#bottom-left > label {
  flex: 0 0 20%;
  margin: 5px;
}

#bottom-left > select,
#bottom-left > input {
  flex: 1 0 65%;
  min-width: 0;
  margin: 5px;
}

div {
  border: 1px solid red;
}

#content, #panel, #bottom {
  display: flex;
  width: 300px;
}

#content, #panel {
  flex-direction: column;
}

#content {
  align-items: center;
}

#bottom-right {
  flex-grow: 1;
}


/* Example placeholders for content of unknown size. */

span {
  display: inline-block;
}

#example-stuff1 {
  background: yellow;
  width: 100%;
  height: 120px;
}

#example-stuff2 {
  background: cyan;
  width: 100px;
  height: 10px;
}
<div id="content">
  <div id="panel">
    <div id="top"><span id="example-stuff1"></span></div>
    <div id="bottom">
      <div id="bottom-left">
        <label>Label:</label>
        <select>
          <option>Option 1</option>
          <option>Option 2 is a pretty long one</option>
          <option>Option 3</option>
        </select>
        <label>Label:</label>
        <input type="textbox" value="example">
      </div>
      <div id="bottom-right"><span id="example-stuff2"></span></div>
    </div>
  </div>
</div>

jsFiddle

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • 1
    This is a great answer. Unfortunately as it turns out, it's too hard for me to specify an actual width, because of the nature of the content in #top. Still, this answer showed me what the limitations were and what I can and can't do, so it's what I was looking for. I'm just going to set max-width on the select and inputs, accept that #bottom-right will have some unused real estate, and call it a day for now, since it's starting to get messy. I may switch to using JS to dynamically compute the appropriate width and implement the solution in this answer that way instead later. – Jason C Jul 10 '17 at 04:05
  • 1
    @JasonC [problem](https://jsfiddle.net/8g51t10y/1/) , one more [idea](https://jsfiddle.net/3dzxy5bq/) set width to bottom-left, another insane [idea](https://jsfiddle.net/uLkcy05y/) – bhv Jul 10 '17 at 04:34