Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make last element take remaining width with wrapping (and with IE9 support)

Tags:

html

css

I’m looking for a way to align multiple items next to each other, having them wrap once they fill up the line, and the last item take up the remaining width of the last line.

I have found multiple questions on a similar topic before, with solutions generally making the items use float: left to align them on a line, and overflow: hidden on the last element which makes it take up the remaining space automatically. Those solutions work fine in a single line, but they stop working once there are enough items before the last element, that they wrap into multiple lines. Then, the “last” element is still rendered in the first row (if there is enough space), making it no longer be the last element.

However, I want the last element to stay the last element at all times, to have it in the last row—whatever row that is—and automatically take up the remaining space there.

This is pretty simple with a wrapping flexbox, since you just need to put flex: 0 auto on the former items to make them take up whatever space they need (without taking more), and flex: 1 on the last element to make it take up the remainder. However, I need to support Internet Explorer 9, so flexbox is unfortunately out of the question.

This is how the situation looks like. When running the snippet, you can use the “Toggle flex box” button to toggle flexbox mode which shows the way it should look like.

* { box-sizing: border-box; }  .container {    width: 300px;    background: snow;    padding: 5px;    overflow: auto;  }  .element {    float: left;    margin: 2px 5px 2px 0;    background: lavender;  }  .last {    overflow: hidden;  }  .last > input {    width: 100%;  }    /* Working solution with flex box */  .flex .container {    display: flex;    flex-wrap: wrap;  }  .flex .element {    flex: 0 auto;  }  .flex .last {    flex: 1;  }
<div class="container">    <div class="element">Foo</div>    <div class="element">Foo bar</div>    <div class="element">Foo bar baz</div>      <div class="last"><input type="text" /></div>  </div>    <div class="container">    <div class="element">Foo</div>    <div class="element">Foo bar</div>    <div class="element">Foo bar baz</div>    <div class="element">Foo</div>    <div class="element">Foo bar</div>    <div class="element">Foo bar baz</div>      <div class="last"><input type="text" /></div>  </div>    <button onclick="this.parentNode.classList.toggle('flex')">Toggle flex box</button>
like image 766
poke Avatar asked Jan 08 '16 16:01

poke


People also ask

How do I make a DIV take up the remaining width?

The width property is used to fill a div remaining horizontal space using CSS. By setting the width to 100% it takes the whole width available of its parent. Example 1: This example use width property to fill the horizontal space. It set width to 100% to fill it completely.

How can I make my Div occupy full height?

Syntax: To set a div element height to 100% of the browser window, it can simply use the following property of CSS: height:100vh; Example: HTML.


2 Answers

Here is the solution:

  • Add a <div style="clear:left;margin-top:22px"></div> before the .last element*
  • Add margin-top: -22px; to .last where the amount is about the same as the line-height
  • If you dont want it to get too small add min-width to .last and it will work as you'd expect
    Also min-width: 1px; is requiered in the class to avoid it getting 0 in special cases.

Tested and working in IE8+, Edge, Chrome, Opera, Firefox

* { box-sizing: border-box; }  .container {    width: 300px;    background: snow;    padding: 5px;    overflow: auto;  }  .element {    float: left;    margin: 2px 5px 2px 0;    background: lavender;  }  .last {    overflow: hidden;    margin-top: -22px;    min-width: 1px;  }  .last > input {    width: 100%;  }  .container .unwrap {    clear: left;    margin-top: 22px  }
<div class="container">    <div class="unwrap"></div>    <div class="last"><input type="text" /></div>  </div>    <div class="container">    <div class="element">Foo</div>    <div class="element">Foo bar</div>    <div class="element">Foo bar baz</div>    <div class="unwrap"></div>    <div class="last"><input type="text" /></div>  </div>    <div class="container">    <div class="element">Foo</div>    <div class="element">Foo bar</div>    <div class="element">Foo bar baz boo</div>    <div class="unwrap"></div>    <div class="last" style="min-width: 100px">      <input type="text" placeholder="min-width 100px" />    </div>  </div>    <div class="container">    <div class="element">Foo</div>    <div class="element">Foo bar</div>    <div class="element">Foo bar baz</div>    <div class="element">Foo</div>    <div class="element">Foo bar</div>    <div class="element">Foo bar baz</div>    <div class="unwrap"></div>    <div class="last"><input type="text" /></div>  </div>    <div class="container">    <div class="element">Foo</div>    <div class="element">Foo bar</div>    <div class="element">Foo bar baz</div>    <div class="element">Foo baaaaaaaaaaaaaaaaaaaaaaar</div>    <div class="unwrap"></div>    <div class="last"><input type="text" /></div>  </div>    <div class="container">    <div class="element">Foo bar baz Foo bar baz Foo bar baz Foo bar baz Foo bar baz Foo bar baz Foo bar baz Foo bar baz Foo bar baz Foo bar baz Foo bar baz Foo bar baz</div>    <div class="unwrap"></div>    <div class="last"><input type="text" /></div>  </div>

* margin-top:22px only to avoid the input to slip over in case there are no elements in the container. It should be the absolute value of the negative margin of the input

like image 57
CoderPi Avatar answered Sep 18 '22 15:09

CoderPi


The following solution isn't perfect, it's using the position hacks. If you disable overflow: hidden; you'll see each <input> actually has the same width as the container. But with some CSS visual tweaks, it looks good and may work ok.

Issue 1: if you type in more characters than it can visually fit, the whole view shifts to the left.

Workaround 1: set a maxlength value to the <input> might help.

jsfiddle

* {    box-sizing: border-box;  }  .container {    width: 300px;    background: snow;    padding: 5px;    position: relative;    overflow: hidden; /*hide the overflow*/  }  span:after {    content: "\00A0" /*just for one no-break space*/  }  input {    width: 100%;    position: absolute; /*without any top/right/bottom/left value*/    border: 2px solid grey;    border-width: 0 0 2px 0;  }  input:focus {    outline: 0;  }
<div class="container">    <span>FooFoo barFoo bar baz</span>    <input type="text" />  </div>    <div class="container">    <span>FooFoo barFoo bar bazFooFoo barFoo bar baz bla</span>    <input type="text" />  </div>
like image 28
Stickers Avatar answered Sep 18 '22 15:09

Stickers