3

I was experimenting with div and trying to create a composite control using

  1. Label
  2. Text field

HTML

* {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}
.form-control {
  background-color: yellow;
  margin: 0;
  padding: 0;
}
.form-control[data-layoutOrder=horizontal] div[data-section=title] {
  display: inline-block;
  background-color: red;
  width: 50%;
  margin: 0;
  padding: 0;
}
.form-control div[data-section=data] {
  background-color: green;
  display: inline-block;
  width: 50%;
  margin: 0;
  padding: 0;
}
<div class="form-control" data-layoutOrder="horizontal">
  <div data-section="title">
    <label for="firstName">First Name</label>
  </div>
  <div data-section="data">
    <input type="text" placeholder="First Name" id="firstName">
  </div>
</div>

The output of the above code was expected to be label and input to be adjacent to each other, but thats not the case. The div wrapping text field is actually floating to next line, though I have set width of label div and textfield div to 50% using CSS.

Div floating to next line

I tried setting padding, margin etc to 0, but none of them worked. What is causing textfield div to float to the next line. When I changed one of the div's width to 49%, both divs got aligned on single line. I didn't understand as why it is behaving so?

Note: I could able to get both of them adjacent to each other using float property - float:left for label div & float:right property for textfield div. But I want to know as why setting 50% width didn't work without float. Do I really need to use float or am I missing something.

Expected output

EDIT 1: I found another solution by using white-space attribute as

.form-control {
background-color: yellow;
margin:0;
padding:0;
white-space:nowrap;
}

.form-control div[data-section=data] {
background-color : green;
display: inline-block;
width: 50%;
margin:0;
padding:0;
white-space:normal;
}

EDIT 2: Using flex style also has desired effect. While searching more, I also came across achieving the same effect using flex style. Note that, it isn't supported in IE 10 and below. Refer caniuse.

.form-control {
  background-color: yellow;
  margin: 0;
  padding: 0;
  display: flex;
  display: -webkit-flex;
}
.form-control[data-layoutOrder=horizontal] div[data-section=title] {
  display: inline-block;
  background-color: red;
  width: 50%;
  margin: 0;
  padding: 0;
  flex:1;
}
.form-control div[data-section=data] {
  background-color: green;
  display: inline-block;
  width: 50%;
  margin: 0;
  padding: 0;
  flex:1;
}
CuriousMind
  • 3,143
  • 3
  • 29
  • 54
  • I suspect it's a border. Try setting border: 0; and outliine: 0; EDIT: I noticed now you have box-sizing, so that shouldn't be the case – Jonas Grumann May 22 '15 at 09:10

4 Answers4

2

That's a tricky one. Inline-blocks elements will take count a new line in your HTML as a space, adding width to the total width of the elements. To fix it, add an empty HTML comment like this:

<div class="form-control" data-layoutOrder="horizontal">
    <div data-section="title">
        <label for="firstName">First Name</label>
    </div><!--
    --><div data-section="data">
    <input type="text" placeholder="First Name" id="firstName">
    </div>
</div>

Example: http://jsfiddle.net/humwrgnj/

Jonas Grumann
  • 10,438
  • 2
  • 22
  • 40
2

Simply write the tags in one line

<div class="form-control" data-layoutOrder="horizontal">
    <div data-section="title">
    <label for="firstName">First Name</label>
    </div><div data-section="data">
    <input type="text" placeholder="First Name" id="firstName">
    </div>
    </div>

* {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

.form-control {
 background-color: yellow;
 margin:0;
 padding:0;
}

.form-control[data-layoutOrder=horizontal] div[data-section=title]{
 display:inline-block;
 background-color : red;
 width: 50%;
 margin:0;
 padding:0;
}

.form-control div[data-section=data] {
 background-color : green;
 display: inline-block;
 width: 50%;
 margin:0;
 padding:0;
<div class="form-control" data-layoutOrder="horizontal">
<div data-section="title">
<label for="firstName">First Name</label>
</div><div data-section="data">
<input type="text" placeholder="First Name" id="firstName">
</div>
</div>
Dmitriy
  • 4,475
  • 3
  • 29
  • 37
2

This is a well known issue with inline-block elements. The trick here is to use font-size:0; on your container element, and then override this in your child elements using font-size:initial;

Here's a quick demo:

* {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}
.form-control {
  background-color: yellow;
  margin: 0;
  padding: 0;
  font-size:0;
}
.form-control[data-layoutOrder=horizontal] div[data-section=title] {
  display: inline-block;
  background-color: red;
  width: 50%;
  margin: 0;
  padding: 0;
  font-size:initial;
}
.form-control div[data-section=data] {
  background-color: green;
  display: inline-block;
  width: 50%;
  margin: 0;
  padding: 0;
  font-size:initial;
}
<div class="form-control" data-layoutOrder="horizontal">
  <div data-section="title">
    <label for="firstName">First Name</label>
  </div>
  <div data-section="data">
    <input type="text" placeholder="First Name" id="firstName">
  </div>
</div>

An alternative would be to use positioning if the element's are always going to be 50% width:

html,
body {
  margin: 0;
  padding: 0;
}
.parent {
  position: relative;
  min-height: 50px;
  width: 100%;
  background: rgba(0, 0, 0, 0.2);
}
.child {
  position: absolute;
  top: 0;
  width: 50%;
  height: 100%;
  background: tomato;
}
.childone {
  left: 0;
}
.childtwo {
  lefT: 50%;
  background: cornflowerblue;
<div class="parent">
  <div class="child childone"></div>
  <div class="child childtwo"></div>
</div>
jbutler483
  • 24,074
  • 9
  • 92
  • 145
  • This is consistent with IE and chrome. So are you saying this is the issue with both the browsers? OR is there any mandate from W3C specification? Can you support the statement with online references. – CuriousMind May 22 '15 at 09:57
  • @CuriousMind: there are already many [answers](http://stackoverflow.com/questions/18262300/two-inline-block-elements-each-50-wide-do-not-fit-side-by-side-in-a-single-ro) stating such. [Again](http://stackoverflow.com/questions/6871996/css-two-inline-block-width-50-elements-dont-stack), it's due to the whitespace. It's not an error, it's just 'how it is' – jbutler483 May 22 '15 at 10:10
  • Setting font-size to `0` is horrible hack. That takes away capability of setting font-size to % for inner elements. The % are relative to parent elements font size. – CuriousMind May 22 '15 at 10:43
  • I would never endorse using % font sizes. Use em units instead. – jbutler483 May 22 '15 at 10:50
  • But if you're that set on using % font-size, then you could use my second answer. – jbutler483 May 22 '15 at 10:55
  • I found another approach and that doesn't require too much of change in the code (check edit 1). – CuriousMind May 22 '15 at 11:06
  • @CuriousMind: that may still require empty comments in your markup. – jbutler483 May 22 '15 at 11:16
  • No it doesn't. Works perfect. – CuriousMind May 22 '15 at 11:18
0

Add CSS float: left; property to this class .form-control[data-layoutOrder=horizontal] div[data-section=title]

stanze
  • 2,456
  • 10
  • 13