Why is floated div being blocked from wrapping to container edge? - html

I have 3 <div> elements floated left inside a <div> wrapper. When the screen narrows, the 3rd <div> should wrap around and position itself under the 1st <div>. What I'm experiencing, however, is that the 3rd <div> is wrapping only as far as the 2nd <div>, and I can't figure out why. Please check my CSS and point out where I'm going wrong.
body {
background: #d2e1ff;
font-size: 80%;
font-family: Verdana,Arial,sans-serif;
}
#step2 {
min-width: 150px;
max-width: 600px;
}
label {
font-size: 80%;
}
input[type="text"] {
width: 98%;
}
.element {
float: left;
margin-right: 3%;
margin-bottom: 1%;
}
.element label {
display: inline-block;
width: 100%;
}
.column1 {
width: 30%;
}
.column2 {
width: 40%;
}
input#day,input#month {
margin-right: 2%;
width: 2em;
}
input#day,input#month,input#year {
color: #999999;
width: 3em;
}
#media all and (max-width:400px){
.element {
width: 100%;
display: block;
}
}
<div id="step2">
<div class="element column2">
<label for="telephone">Telephone number</label>
<input id="telephone" type="text" name="telephone">
</div>
<div class="element column2">
<label for="gender">Gender</label>
<select id="gender" name="gender">
<option value="">Select Gender</option>
<option value="m">Male</option>
<option value="f">Female</option>
</select>
</div>
<div class="element column1">
<label for="day">Date of birth</label>
<input id="day" type="text" name="day" value="dd">
<input id="month" type="text" name="month" value="mm">
<input id="year" type="text" name="year" value="yyyy">
</div>
</div>

This is interesting behavior. You're right: it is reasonable to think that the third div should wrap all the way back and position itself under the first div in column 1. That's how floats are supposed to work.
Here's a simple demo. Three boxes, floated left. Just like your layout. When you adjust screen width they wrap as expected.
DEMO
And this is what you're experiencing:
DEMO
The solution to the problem is very simple:
Add a height rule to each div.
.element {
float: left;
margin-right: 3%;
margin-bottom: 1%;
height: 50px; /* This solves the problem */
}
DEMO
Here's what's happening...
It seems that the padding from the Telephone input field is making div box #1 slightly taller than the Gender box. This extra height is literally blocking div box #3 from shifting to the edge of the container.
In this image, the Date of Birth box, which is floated left, is unable to wrap all the way to the container edge. The Telephone div is blocking it.
If we give the telephone input a padding: 0, the height is reduced and the obstruction is removed:
input[type="text"] { padding: 0; }
But who the hell wants text fields with no padding?
There is a clean, simple and effective solution to this problem, and it doesn't involve removing the padding from form inputs: Add a height rule to the div class (as described above).
.element { height: 50px; }
DEMO
A second possible solution is to give div #2 enough bottom margin to clear the height of div #1.
<div class="element column2" style="margin-bottom: 10px">
<!-- not necessarily recommending inline style; just for demo purposes -->
One side note...
Collapsed Container
Your parent container (id="step2") isn't wrapping anything, because you've floated the child elements – which takes them out of the normal flow – but you didn't "notify the parent". So your container div has 0 height since it has no content.
To observe this behavior yourself, highlight the div with id="step2" in Chrome Dev Tools or add a border around it.
In your code the top and bottom borders of parent container id="step2" are touching, because the box has no content and, therefore, no height.
From a practical perspective, this means that many styles will be lost on this container (try adding a background color to #step2).
There are several ways to address this issue – known as clearfix methods. In this case I've used the overflow property. Add overflow: auto to the container div.
#step2 { overflow: auto; }
DEMO
Hope this helps. Good luck!

There's no clear: left rule on the third <div>. The layout only advances to the bottom of the second <div>, which is slightly shorter than the first. The third div floats left, but the first one is, like, in the way. So it doesn't go all the way out to the margin.
If you're interested in how floats work, see Introduction to floats.
A floated box is shifted to the left or right until its margin edge touches the containing block edge or the margin edge of another float.
(emphasis added)
Here I've added some background colors to visualize the problem. I've also added clear: left to a new new-row class.
body {
background: #d2e1ff;
font-size: 80%;
font-family: Verdana,Arial,sans-serif;
}
#step2 {
min-width: 150px;
max-width: 600px;
}
label {
font-size: 80%;
}
input[type="text"] {
width: 98%;
}
.element {
float: left;
margin-right: 3%;
margin-bottom: 1%;
}
.element label {
display: inline-block;
width: 100%;
}
.column1 {
width: 30%;
background-color: lime;
}
.column2 {
width: 40%;
background-color: yellow;
}
.new-row {
clear: left;
}
input#day,input#month {
margin-right: 2%;
width: 2em;
}
input#day,input#month,input#year {
color: #999999;
width: 3em;
}
#media all and (max-width:400px){
.element {
width: 100%;
display: block;
}
}
<div id="step2">
<div class="element column2">
<label for="telephone">Telephone number</label>
<input id="telephone" type="text" name="telephone">
</div>
<div class="element column2">
<label for="gender">Gender</label>
<select id="gender" name="gender">
<option value="">Select Gender</option>
<option value="m">Male</option>
<option value="f">Female</option>
</select>
</div>
<div class="element column1 new-row">
<label for="day">Date of birth</label>
<input id="day" type="text" name="day" value="dd">
<input id="month" type="text" name="month" value="mm">
<input id="year" type="text" name="year" value="yyyy">
</div>
</div>

Related

How do I align flexbox items to the baseline on a textarea input

I have a very simple input form. I want to align the labels with the input controls so they are at the same level.
I've decided to use align-items: baseline because no matter what the padding, height, etc, it will always align correctly. But, for some reason, when using it with an input of type textarea it does NOT align to the baseline, it aligns at the bottom. Why?
Sure, I can fix it using self-align and padding-top for the textarea, but that defeats the purpose of having something flexible without the need of fixing the padding in some inputs.
I just need to understand to logic, or is this is a bug/known issue?
* {
margin: 0;
padding: 0;
}
form {
width: 500px;
margin: 0 auto;
background-color: #e4e4e4;
}
form .control ~ .control {
margin-top: 20px;
}
.control {
display: flex;
align-items: baseline;
}
.control>div:nth-child(1) {
flex: 0 1 150px;
text-align: right;
padding-right: 20px;
}
.control>div:nth-child(2) {
flex: 1;
}
.control input,
.control textarea {
width: 100%;
padding: 20px;
}
.control textarea {
height: 100px;
}
<form>
<div class="control">
<div>
<label>Label goes here</label>
</div>
<div>
<input type="text" name="pretitle" value="">
</div>
</div>
<div class="control">
<div>
<label>Article</label>
</div>
<div>
<textarea name="article"></textarea>
<p class="explain sub">HTML allowed</p>
</div>
</div>
<div class="control">
<div>
<label>Label</label>
</div>
<div>
<input type="text" name="pretitle" value="">
</div>
</div>
</form>
https://jsfiddle.net/bnaL94u6/13/
The problem is not the textarea but the padding you are adding to both input and textarea, in textarea, you won't notice the it grows because 20pxx2 (40px) is not higher than 100px, but the input itself without the padding has only 19px, and when you add 40px of padding it will have a total height of 59px. and the the label will align in the middle of those 59px

Why does the font-size of an input breaks the inline-block alignment?

I recently stumble over the problem where I had to align to inputs next to each other which had slightly different font-size parameter. It turns out that is breaks the alignment of the input elements.
Here an exaggerated example to show the problem:
div input {
display: inline-block;
width: 100px;
height: 34px;
}
.field1 {
font-size: 50px;
}
<div>
<input class="field1" type="text" value="test">
<input class="field2" type="text" value="test">
</div>
What is the best way to fix that? How do I align the two input elements in one line next to each other?
vertical-align: top; seems to help solve this problem. I added only that rule which will align the input elements to the top of its parent container (the div in this case).
div input {
display: inline-block;
width: 100px;
height: 34px;
vertical-align: top; /* added */
}
.field1 {
font-size: 50px;
}
<div>
<input class="field1" type="text" value="test">
<input class="field2" type="text" value="test">
</div>

How to align 3 divs with CSS retaining relative position while scaling window

I have this CSS:
.div0{padding:5px;height:70px;}
.pos0{float:left;height:50px;padding:5px; background: red;}
.butt{float:middle; position:relative;top:8px;height:40px;}
.pos1 { background: green; position:relative;left:15px;top:4px;min-width:100px; }
.pos2 { position:relative;left:15px;bottom:-8px; } //background: yellow;
and this HTML:
<div class="div0" id="Div0" style="background-color: rgb(255, 255, 221);">
<div class="pos0">
<button name="Pag" class="butt" id="ButtFull0">MY butt here</button>
</div>
<div class="pos1"><span> aLev:</span>
<input size="1" id="S0" type="text"/><span> vMin:</span>
<input size="1" id="n0" type="text"/><span> vMid:</span>
<input size="1" id="inp0" type="text" /><span> vM:</span>
<input size="1" id="inp1" type="text"/><span id="Q0"> text</span>
</div>
<div class="pos2">
<input id="y0" type="checkbox"/><span> 1°:</span>
<input id="y10" type="checkbox"/><span> 2°:</span>
<input id="e0" type="checkbox"/><span> 3°:</span>
<input p id="p0" type="checkbox"/>
</div>
</div>
I want the button vertically centered on the left and two lines with inputs and checkboxes at its right, both vertically even spaced. All maintaining position while shrinking the window.
I tried with this:
http://jsfiddle.net/qacp35fv/33/
Problems:
1) the 2 lines overlap the button (I put a background color green to better see the problem), so you can't easy click on it.
2) when shrinking the result window to the right, the 1° line becomes multiline: I prefer it remains one line without seeing some text and without increasing the total height.
This would be a good base to use. You can add your input elements in the correct divs.
body {
padding: 0px;
margin: 0px;
}
#wrapper {
width: 100%;
font-size: 0px;
display: table;
}
#left-column {
background: red;
display: table-cell;
height: auto;
font-size: 16px;
width: 120px;
vertical-align: top;
}
#right-column {
background: yellow;
display: table-cell;
font-size: 16px;
width: calc(100% - 120px);
vertical-align: top;
}
#row-1, #row-2 {
height: 20px;
overflow-x: hidden;
}
<div id="wrapper">
<div id="left-column">
Left column
</div>
<div id="right-column">
<div id="row-1">
Right column row 1 with extra long text that will be hidden when resized.
</div>
<div id="row-2">
Right column row 1
</div>
</div>
</div>

Textbox to fill space

Consider the following.
2 DIVS - the left one of known width, the right one of unknown width.
We can make the right-hand side fill the remaining space, however if I exchange the right-hand DIV to a textbox, it then does not fill the space, but wraps below the left-hand div.
Here's a fiddle: example
<div>
<div id="left">
left
</div>
<input type="textbox" id="right">
right
</input>
</div>
#left {
float:left;
width:180px;
background-color:#ff0000;
}
#right {
width: 100%;
background-color:#00FF00;
}
I'm confused - any advice?
Still not behaving as it should!
New fiddle here: updated fiddle
JSFiddle
Inputs are inline bydefault and only the
Block level elements can aquire the remaining space left after a floating element. So you should change the display property for input to block i.e. display:block
#left {
float:left;
width:180px;
background-color:#ff0000;
}
#right {
display:block;
background-color:#00FF00;
}
<div>
<div id="left">
left
</div>
<input type="textbox" value="right" id="right"/>
</div>
EDIT: http://jsfiddle.net/naeemshaikh27/MHeqG/1522/ using Calc.
Using Calc
If You wanted to set the width of only a single element, you may want to look at the calc() option.
Something like:
width: calc(100% - width px);
in which could be incorporated into most projects nowadays, as you can see from its browser support.
You could also make use of the auto width:
.secondElement{
width:auto;
}
to fill the space left
Have a look here...
* {
margin: 0;
padding: 0;
}
div {
display: inline-block;
width: 50%;
background: blue;
}
input {
width: 50%;
display: inline-block;
}
.fix {
border: none;
background: gray;
}
.now {
width: 49.5%;
}
.nowNew {
width: auto;
}
<div>Div on left</div>
<input type="text" placeholder="text here" />
<br/>Notice the lengths aren't the same? Yet both are defined as 50%?
<br/><br/>
<br/>That's due to the border around the input!
<br/><br/><br/>
<div>Div on left</div><input class="fix" type="text" placeholder="text here" />
<br/><br/>
<br/>To fix 'stuff' like this, I feel the general rule in web dev. is to aim to make it 99.9% instead:
<br/><br/><br/>
<div class="now">Div on left</div><input class="now" type="text" placeholder="text here" />
<br/><br/>
<br/>Or make the input width auto:
<br/><br/><br/>
<div>Div on left</div>
<input class="nowNew" type="text" placeholder="text here" />
You can accomplish this using display: table and display: table-cell.
JSFIDDLE
HTML:
<div class="container">
<div id="left">
left
</div>
<input type="textbox" value="right" id="right" />
</div>
CSS:
#left {
display: table-cell;
width: 180px;
background-color:#ff0000;
}
#right {
display: table-cell;
width: 100%;
background-color:#00FF00;
}
.container {
display: table;
width: 100%;
}

How to make responsive side by side form elements

How do you do it so that the select tag and text input will be side by side regardless of the div's width, while also making text input responsive (occupy 100% of the width of the container div)
CSS:
input[type="text"] { width: 100%; }
HTML:
<div style="width:500px; background:red; padding:10px;">
<input type="text" name="test" style="float:left;">
<select style="float:left;"><option>test</option></select>
</div>
Example: http://jsfiddle.net/F6Jtj/
Do you want to align both on the same line with a width of 100% than you can do it this way
Demo
<div class="wrap">
<select>
<option>Hello</option>
<option>World</option>
</select>
<span><input type="text" /></span>
</div>
.wrap span {
display: block;
padding-right: 5px;
overflow: hidden;
}
.wrap input[type=text] {
width: 100%
}
.wrap select {
float: right
}