228

Let's say I have an html snippet like this:

<div style="width:300px;">
    <label for="MyInput">label text</label>
    <input type="text" id="MyInput" />
</div>

This isn't my exact code, but the important thing is there's a label and a text input on the same line in a fixed-width container. How can I style the input to fill the remaining width of the container without wrapping and without knowing the size of the label?

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • I know the question was long time ago but I will add good solution which of course isn't outdated. – danijar Aug 05 '12 at 11:10

9 Answers9

169

Here is a simple and clean solution without using JavaScript or table layout hacks. It is similar to this answer: Input text auto width filling 100% with other elements floating

It is important to wrap the input field with a span which is display:block. Next thing is that the button has to come first and the the input field second.

Then you can float the button to the right and the input field fills the remaining space.

form {
    width: 500px;
    overflow: hidden;
    background-color: yellow;
}
input {
    width: 100%;
}
span {
    display: block;
    overflow: hidden;
    padding-right:10px;
}
button {
    float: right;
}
<form method="post">
     <button>Search</button>
     <span><input type="text" title="Search" /></span>
</form>

A simple fiddle: http://jsfiddle.net/v7YTT/90/

Update 1: If your website is targeted towards modern browsers only, I suggest using flexible boxes. Here you can see the current support.

Update 2: This even works with multiple buttons or other elements that share the full with with the input field. Here is an example.

Bill-G
  • 305
  • 4
  • 12
danijar
  • 32,406
  • 45
  • 166
  • 297
  • This changes the html, though: the item you want at the end is listed first in the html. – Joel Coehoorn May 26 '13 at 17:00
  • @JoelCoehoorn, that's right. It is your decision whether you prefer that over using a table or not. – danijar May 26 '13 at 17:31
  • Any idea to make the button in the vertical center to the input if the input is height: 50px; ? It is already vertical aligned if I use display: table-cell; ... – VCD Dec 02 '13 at 12:58
  • @VCD My first try would be to set the height of `50px` to the `span` instead of the `input`, which gets a height of `100%` then. Don't know if `vertical-align` does work then though. – danijar Dec 03 '13 at 09:16
  • Like this? http://jsfiddle.net/v7YTT/1237/ Not working and the input bottom border gone out of screen... Sure I can use margin to adjust the button but this means I have to do manual adjustment to every layout like that – VCD Dec 04 '13 at 14:16
  • 2
    This works great. Use float:left instead of right to create a facebook style tagger or something similar. – hobberwickey Feb 24 '14 at 17:22
  • 1
    This works great! But can someone explain the logic behind how this works?! – sherlock Jul 08 '14 at 04:44
  • @sherlock, see http://www.yuiblog.com/blog/2010/05/19/css-101-block-formatting-contexts/ for an excellent write-up. Specifically, the section "Block formatting contexts do not overlap floats" is what applies here. – markrian Sep 29 '14 at 12:16
  • I gave an example using flexboxes below. I agree that it's a better solution for modern browsers. – leishman Feb 16 '15 at 16:18
  • Thanks for the solution. But what to do in cases when I cannot change the order of divs and I need the left one to be the first? My scenario is with form input fields. I need the left to be stretched and I must keep it the first field for validation focus to work properly. If I change the order, the validation focus for the first error will be on the second element, which is confusing for the user. Here is my fiddle: jsfiddle.net/qLypn7h8 and I want it to work the same even when I move date-input to be the first div. – JustAMartin Feb 16 '15 at 19:48
  • What if I need the input box to be floated left? Then I'm out of luck without flex box, I guess... – Luke Taylor Mar 22 '16 at 13:36
  • @LukeTaylor, did you take a look at the second demo? – danijar Mar 22 '16 at 13:45
  • The one in Example 2? – Luke Taylor Mar 22 '16 at 13:46
  • 1
    This is a bad answer. It looks like it works if you just glance at it, but go try the fiddle. It is actually chopping of half the input box, but you can't tell unless you start testing it out. The goal is to fit the input box to the width of the display area, not truncate it. If you try to do any styling (rounded corners, a border, right justification of text) this utterly fails. – Roger Hill Jun 30 '17 at 05:03
  • This solution may work but it's against accessibility rules to put items in the wrong order – srinced Oct 26 '21 at 10:11
154

as much as everyone hates tables for layout, they do help with stuff like this, either using explicit table tags or using display:table-cell

<div style="width:300px; display:table">
    <label for="MyInput" style="display:table-cell; width:1px">label&nbsp;text</label>
    <input type="text" id="MyInput" style="display:table-cell; width:100%" />
</div>
cobbal
  • 69,903
  • 20
  • 143
  • 156
66

I suggest using Flexbox:

Be sure to add the proper vendor prefixes though!

form {
  width: 400px;
  border: 1px solid black;
  display: flex;
}

input {
  flex: 2;
}

input, label {
  margin: 5px;
}
<form method="post">
  <label for="myInput">Sample label</label>
  <input type="text" id="myInput" placeholder="Sample Input"/>
</form>
leishman
  • 1,017
  • 11
  • 7
  • The question is very old... this is probably how I'd do it today. If I get a chance to try it, and it works with all the browsers I needed, I'll update the accepted answer. Probably, though, it will be a long time before I get to try this. I'm on the sys admin team now, don't do as much web stuff any more. – Joel Coehoorn Jul 09 '14 at 13:28
  • Could you provide an example using a ```label```? I would be especially interested in how the HTML from the original question could be layouted using ```border-box```... – lacco Dec 10 '14 at 09:18
  • 7
    Why `flex: 2` and not `flex: 1`? – Iulius Curt Oct 04 '18 at 21:04
  • @IuliusCurt According to the docs, wouldn't make a difference in this case. "Flex: This is the shorthand for flex-grow, flex-shrink and flex-basis combined. The second and third parameters (flex-shrink and flex-basis) are optional." https://css-tricks.com/snippets/css/a-guide-to-flexbox/ – Bersan May 01 '21 at 21:43
  • 1
    Well, then, `flex: 42` it is – Iulius Curt Jul 23 '21 at 13:20
60

Please use flexbox for this. You have a container that is going to flex its children into a row. The first child takes its space as needed. The second one flexes to take all the remaining space:

<div style="display:flex;flex-direction:row">
    <label for="MyInput">label&nbsp;text</label>
    <input type="text" id="MyInput" style="flex:1" />
</div>
Andy
  • 4,783
  • 2
  • 26
  • 51
basarat
  • 261,912
  • 58
  • 460
  • 511
  • 1
    Hi five! :) One thing worth adding (in the context of many of us still newly embracing the flexbox model): that INPUT will be in a FORM, which in turn may end up in the overall flex container (e.g. with other, non-form stuff), and then it will no longer work -- because the flex behavior [only applies to direct descendants](https://stackoverflow.com/questions/14148162/does-the-css-flexbox-module-work-on-direct-child-elements-only) (i.e. child elements). *So, the FORM must be a flex contrainer, too!* – Sz. Mar 17 '18 at 13:36
  • flex-direction is already `row` by default, you dont have to specify it. – fabpico Jun 08 '18 at 13:24
  • flex for the win (again); very relevant answer in 2019 – secretwep Mar 27 '19 at 19:44
18

Easiest way to achieve this would be :

CSS :

label{ float: left; }

span
{
    display: block;
    overflow: hidden;
    padding-right: 5px;
    padding-left: 10px;
}

span > input{ width: 100%; }

HTML :

<fieldset>
    <label>label</label><span><input type="text" /></span>
    <label>longer label</label><span><input type="text" /></span>
</fieldset>

Looks like : http://jsfiddle.net/JwfRX/

llange
  • 757
  • 2
  • 10
  • 14
5

Very easy trick is using a CSS calc formula. All modern browsers, IE9, wide range of mobile browsers should support this.

<div style='white-space:nowrap'>
  <span style='display:inline-block;width:80px;font-weight:bold'>
    <label for='field1'>Field1</label>
  </span>
  <input id='field1' name='field1' type='text' value='Some text' size='30' style='width:calc(100% - 80px)' />
</div>
Whome
  • 10,181
  • 6
  • 53
  • 65
3

you can try this :

div#panel {
    border:solid;
    width:500px;
    height:300px;
}
div#content {
 height:90%;
 background-color:#1ea8d1; /*light blue*/
}
div#panel input {
 width:100%;
 height:10%;
 /*make input doesnt overflow inside div*/
 -webkit-box-sizing: border-box;
       -moz-box-sizing: border-box;
            box-sizing: border-box;
 /*make input doesnt overflow inside div*/
}
<div id="panel">
  <div id="content"></div>
  <input type="text" placeholder="write here..."/>
</div>
Andik
  • 41
  • 1
3

The answers given here are a bit outdated. So, here I'm with the easiest solution using modern flexbox.

.input-container{
display:flex;
}
input{
flex-grow: 1;
margin-left: 5px;
}
<div style="width:300px;">
    <div class="input-container">
    <label for="MyInput">label text: </label>
    <input type="text" id="MyInput"/>
    </div>
    
    <div class="input-container">
    <label for="MyInput2">Long label text: </label>
    <input type="text" id="MyInput2" />
    </div>
    
</div>
0

If you're using Bootstrap 4:

<form class="d-flex">
  <label for="myInput" class="align-items-center">Sample label</label>
  <input type="text" id="myInput" placeholder="Sample Input" class="flex-grow-1"/>
</form>

Better yet, use what's built into Bootstrap:

  <form>
    <div class="input-group">
      <div class="input-group-prepend">
        <label for="myInput" class="input-group-text">Default</label>
      </div>
      <input type="text" class="form-control" id="myInput">
    </div>
  </form>

https://jsfiddle.net/nap1ykbr/

DharmaTurtle
  • 6,858
  • 6
  • 38
  • 52