42

How do achieve the following:

┌────────────────────parent────────────────────┐
│ label [text-box                   ] [button] │
│ paragraph                                    │
└──────────────────────────────────────────────┘
  • label is aligned to the left
  • button is aligned to the right
  • text-box occupies all remaining width within parent
  • paragraph is aligned to the left, must be left-aligned with label too

Both label and button should obey font properties defined elsewhere as maximum as possible. parent is center-aligned within window, and, naturally, can have arbitrary width.

Please advise.

user422039
  • 1,447
  • 4
  • 13
  • 28

6 Answers6

53

Updated [Oct 2016]: Flexbox version...

form {
  display: flex;
}
form input[type="text"] {
  flex: 1;
}
<form>
  <label>Name</label>
  <input type="text" />
  <button>Submit</button>
</form>
<p>Lorem ipsum...</p>

Original answer [Apr 2011]: Table-less CSS version (of table behavior)...

<div id="parent">
    <div id="inner">
        <label>Name</label>
        <span><input id="text" type="text" /></span>
        <input id="submit" type="button" value="Submit" />
    </div>
    <p>some paragraph text</p>
</div>

CSS...

#inner {
    display: table;
    width: 100%;
}
label {
    display: table-cell;
}
span {
    display: table-cell;
    width: 100%;
    padding: 0px 10px;
}
#text {
    width: 100%;
}
#submit {
    display: table-cell;
}

Demo: http://jsfiddle.net/wdm954/626B2/4/

wdm
  • 7,121
  • 1
  • 27
  • 29
  • It looks nice until parent block has given an extreme widths. Stretch it and there will be a large hole between label text and text input box. Compress it and text withing label and button nodes will collapse. This is an essence of the problem i'm struggling with. – user422039 Apr 28 '11 at 23:54
  • Cool, thanks, now it works completely independent of parent's width – user422039 May 03 '11 at 17:09
  • yea, it is cool but it won't work in IE7, because it doesn't support display: table-cell; – jasin_89 Dec 17 '12 at 09:46
  • here is the solution to work in IE7: http://stackoverflow.com/questions/5219175/width-100-padding – jasin_89 Dec 17 '12 at 09:57
13

I don't like first answer with the "table-less" version that actually uses table-cell. Nor the second answer that uses actual tables. Nor third answer that uses hardcoded widths. Here is solution using flex. It is by far simplest:

#parent {
  display: flex;
}
input {
  flex: 1;
}
<div id="parent">
  <label>Name</label>
  <input type="text" />
  <button>Button</button>
</div>
<div>paragraph</div>
asdjfiasd
  • 1,572
  • 15
  • 28
  • Note that `flex` doesn't work in Android 4.2 browsers thus not allowing building cross-platform Cordova applications. Flex simplifies things so much and I love it a lot, but for compatibility one or two more years we have to use floats instead. – Brian Cannard Mar 01 '17 at 20:55
10

Use tables. :D I know people tend to hate tables, but they will work in this situation...

<div id="parent">
    <table style="width:100%">
        <tr>
            <td>label</td>
            <td style="width:100%">
                <input type="text" style="width:100%">
            </td>
            <td>
                <button>clickme</button>
            </td>
        </tr>
    </table>
</div>
Community
  • 1
  • 1
Thomas Shields
  • 8,874
  • 5
  • 42
  • 77
  • Now i'm curious how it works, because it does (w/o predefined widths, even percentage) – user422039 Apr 28 '11 at 23:57
  • because the definition of a table cell is to keep going until it hits the next cell or the end of the row or table. You don't have to specify it. – Thomas Shields Apr 29 '11 at 00:18
  • 2
    make everything as simple as possible but not simpler, said Einstein. That's an argument for your table solution. Occam would agree, too, and razor away chatty div solution. Some believe in the virgin birth, others in not using tables. Gotta have faith. Just gotta. – mathheadinclouds Apr 30 '13 at 12:21
  • It works without tables when you put the button *before* the input box and assign `float: right` to it and wrap the input box inside span with `display: block` and `overflow: hidden`. No magic involved: `
    `. The basic idea that all right side buttons are specified in the reverse order.
    – Brian Cannard Mar 01 '17 at 20:53
2

Don't forget, you can use calc(). Let's assume total of width used by label and button is 100px (including margin), then the width is:

.text-box {    
  width: calc(100% - 100px);
}

If you think it doesn't support a lot of browser, well you are wrong indeed. It supports a lot now. Time has changed

Aminah Nuraini
  • 18,120
  • 8
  • 90
  • 108
2

The only way I know how to achieve this or similar, is to have the "text-box" as a block element that would automatically fill the entire width of the parent, then apply padding to the left and right equal to the total width of the containers on the left and right. Then make the "label" and "button" elements have their position set as relative and float them to where they need to be (float: left, float: right).

Something like,

HTML:

<div id="parent">
    <div id="label">label</div>
    <div id="button">button</div>
    <div id="text-box">
        text<br />
        text<br />
        text<br />
        text<br />
        text
    </div>
</div>

CSS:

div#label
{
    position: relative;
    float: left;
    width: 200px;
    background: #F00;
}

div#button
{
    position: relative;
    float: right;
    width: 120px;
    background: #0F0;
}

div#text-box
{
    padding-left: 200px;
    padding-right: 120px;
    background: #00F;
}

If the button and label elements don't need to have a set width, all elements could just have their width as a percentage value (all adding up to 100%).

Marty
  • 39,033
  • 19
  • 93
  • 162
  • Unfortunately button block floats *above* text-box block, overlappling its content (try: opacity:0.75). Also, please check out my comment to **wdm**'s answer on percentage width fragility. – user422039 Apr 29 '11 at 00:05
  • You can avoid the collapsing of the left and right elements by giving the body a minimum width - I'm not sure what you mean by the hole between label text and text input - my solution makes sure that the content of text-box is always snapped to the right-hand-side of the input element. – Marty Apr 29 '11 at 00:11
  • Both the label and button elements are overlapping the text-box area. But the content within this area won't ever be behind or underneath because of the padding applied.. – Marty Apr 29 '11 at 00:13
  • It works without tables when you put the button *before* the input box and assign `float: right` to it and wrap the input box inside span with `display: block` and `overflow: hidden`. No magic involved: `
    `. The basic idea that all right side buttons are specified in the reverse order.
    – Brian Cannard Mar 01 '17 at 20:53
0

It works without flex and tables if assign float: right and put the button (or several buttons in reverse order) before the input box.

Then place the label with float: left, give the input box 100% width and wrap it inside a span with display: block and overflow: hidden.

No magic involved:

<div style="width:100%">
  <button style="float:right">clickme 2</button>
  <button style="float:right">clickme 1</button>
  <label style="float:left">label</label>
  <span style="display:block;overflow:hidden">
    <input type="text" style="width:100%"/>
  </span>
</div>

The basic idea that all right side buttons are specified before the input box in the reverse order.

Brian Cannard
  • 852
  • 9
  • 20
  • For those who needs the label to pass clicks and taps to the input box *and* wrap it, `padding-right: 100%` and `margin-right: -100%` is the only solution in this case. But it'll be discovered that it draws the buttons unclickable. I love the advice http://stackoverflow.com/a/4408709/84661 . Complete solution is here: http://codepen.io/avesus/pen/VpaPWK – Brian Cannard Mar 02 '17 at 21:10