Browser block float logic of different heights - css

What is the browsers logic to position elements like this:
Basically, as I understand this can be recreated without bootstrap with a simple container block and and width: 33.333333% blocks of different heights. Why is the d block not floating to the left, under a block?
Fiddle: https://jsfiddle.net/8qbuczau/

You would expect that the d block would sit on the new line with the e and f block but the reason it does not is because there is enough horizontal and vertical space on the first row for it to sit underneath the c block.
If you take away the line breaks from the b element then d will be forced to the next line as there is no more vertical space for it to fill.
.row {
overflow: auto;
}
div
{
border: 1px dashed maroon;
box-sizing: border-box;
}
div.col-md-4
{
margin-bottom: 1em;
width: 33.333333%;
float: left;
}
<div class="container">
<div class="row">
<div class="col-md-4">a</div>
<div class="col-md-4">
b
</div>
<div class="col-md-4">c</div>
<div class="col-md-4">d</div>
<div class="col-md-4">e</div>
<div class="col-md-4">f</div>
</div>
</div>
If you add more line breaks to the b element you will see that e and f also have the same behaviour.
Per the w3 spec:
If the float reference is not a line box, the element generates a box
that is floated to the block-start and line-start outer edges of the
float reference.
Also:
If the float reference is not a line box, the element generates a box
that is floated to the block-end and line-start outer edges of the
float reference.
With floats, they will naturally try to move to the start or end of their containing element going line by line if there is enough space. What stops this from happening is that usually there is not enough space for them to sit on the end of the previous line so they reposition themselves at the beginning of the next line

If you want the d become new row why dont you split it into 2 different <div class="row">
Total col in 1 row should be max 12. Never try if you make it become more than 12, may be thats what make the positioning become messy.

Related

How to resize the width of div left to another which has float:left;?

I still have problem to well understand how the float property works in CSS. I do apologize because I know this is css basics but I really want to understand that and get a good explanation. I've created an example to show you.
Here is my page :
I just want to resize the second div at the right. When I look at it in the Chrome Developer Tools, I see that this div begins at the top left of the window and not after the red square. I'd like it to begins just after the red square to change the width properly without calculating the size of the square and doing something like
width = square size + width i want
Do you know how this it happens and how to properly resize the width of the second div ?
EDIT: the solution consists in add the float property to the second div too. The explanation is the following : floated elements are removed from the flow, so they don't stack with the non-floated elements.
You need to set float for another div too.
We generally do like below:
html
<div class="float-left">
<p>floated left</p>
</div>
<div class="float-left"><!--- to float next to previous div--->
<p>floated left</p>
</div>
css
.float-left{
float: left;
}
As per your comment:
We do clear the float values because the container contents would never been collapsed.
You need to float the second div.
Heres an example.
<div class="parent-div">
<div class="left">
</div>
<div class="left">
<p>This is the description of the image</p>
</div>
</div>
You need to set
p { display:inline; }
or
div { display:inline; }
since paragraphs and divs are block elements.
http://www.w3.org/TR/CSS2/visuren.html#block-boxes
the reason is that floated elements are removed from the flow, so they don't stack with the non-floated elements. - therefore they don't "take up space" like before. This is why your text div starts at the top left of its container.
from MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/float
The float CSS property specifies that an element should be taken from the normal flow and placed along the left or right side of its container, where text and inline elements will wrap around it. A floating element is one where the computed value of float is not none.
You have to set float for both DIVs
Here is the updated code:
HTML:
<div id="main_container">
<div class="left"></div>
<div class="right">
<p>This is the description of the image <i>Random text</i>
</p>
</div>
<!--Comment below <DIV> to see the result-->
<div class="clear"></div>
</div>
CSS
#main_container {
border:5px solid #000;
}
.left, .right {
width: 100px;
height: 100px;
background: red;
float:left;
}
.right {
background: blue;
width: calc(100% - 100px);
}
.clear {
clear:both;
margin:0;
padding:0;
}
Also, just to add one more important fact related to "float" is, make sure you add "clear:both" property after "float".
Why?? Because, a common problem with float-based layouts is that the floats' container doesn't want to stretch up to accomodate the floats. If you want to add, say, a border around all floats (ie. a border around the container) you'll have to command the browsers somehow to stretch up the container all the way.
Here is the Fiddle for the same: http://jsfiddle.net/1867ud9p/7/
Hope this will help!

Align 3 divs side by side with one column having 2

I have a total of 3 divs - how to get them to appear as per the following image.
I can get 2 together using float:left, however withe 3rd one keeps sitting underneath div A.
Any ideas?
Thanks
Wrap B and C in additional div similar to A (with float left as well)
Check out masonry.js.
The reason why floats cannot be used in this case is that the float will clear after the tallest element in the row, therefore bumping element C under element A.
Alternatively, you can place A in a sub-parent floated to the left, and B and C in a sub-parent floated to the right. However, this makes dictating the order of items in a responsive/fluid layout difficult. The solution can be simplified as follow:
<div>
<div class="col">
<!-- A -->
</div>
<div class="col">
<!-- B + C -->
</div>
</div>
For the CSS:
.col { float: left; width 50%; }

Floating divs, equal height - fill space with additional div without overflow

I have two div-columns of different height which I like to have the same height. I achieved this using the padding-margin hack with the following css for my div-columns:
.lane1 {
padding-bottom: 800px;
margin-bottom: -800px;
}
The html is displaying a flow-diagram. I would like to have a line from the end of each lane to the bottom of the two-lane part to have a continuous diagram.
I tried to achieve this with an additional div with class .LineFilling that is a line going down, but I don't know how heigh the line should be. So I put
position: absolute;
overflow: hidden;
in the .lane1-class and made the .LineFilling-element of height 600px, but that doesn't work, since the overflow is displayed. Is there a way to have the .LineFilling-element extend to the end of the lane? Or extend further but the overflow being cut?
Thanks for help.
EDIT: I posted the code online here: Click here to see code
Yes it is possible with pure css.
I have used display table-row and table-cell properties to achieve it.
HTML:
<div class="parent">
<div class="child">
<p>line 1</p>
</div>
<div class="child">
<p>line 1</p>
<p>line 2</p>
<p>line 3</p>
<p>line 4</p>
</div>
</div>
CSS:
.parent{display:table-row;}
.child{display:table-cell;border:1px solid #ccc;padding:10px;}
p{margin:5px 0;}
See fiddle.
Update: probable solution DEMO
Pure CSS solution
Here is a DEMO of that solution.
In this DEMO, you see multipple Rows,
each Row can have a variable number of columns without stating anything in the markup, and without fixing any width. (the width is always divided evenly between the columns).
Each column is called ElementsHolder, and can have any number of Elements you want.
all the column in a row will always have the same height, and the last arrow in the row will fill that space.
In the DEMO you can see 3 Rows.
The First Row has the starting point, so no stretch needed there.
The Second Row has 3 ElementsHolder, without stating anything special in the markup, 2 of them will stretch to fill the gap.
The Third Row has 2 ElementsHolder, behave as expected.
notice that the stretching works regardless of the Elements height. (some of them have 2 or 3 lines of text, and it works perfectly)
If you want to use that technique, you only have to implement the other kind of boxes and arrows (Curve etc..)
The solution is done by using the new CSS flex model.
the direction is set via flex-direction: row;,
Each row has ElementsHolders that gets equal width.
each one of those ElementsHolder is also a flex box, but this time his direction is opposite (flex-direction: column;).
the child's of ElementsHolder are Elements & Arrows, I dont want them to have equal height, but to span excatly the natural height. except the last arrow, that should span the rest of the container.
all of that is achieved using the flex property with the appropriate values.
More about the flex-model can be found HERE
I don't know if I really understand what you need. I've tried the following
Adding a new absolute element in the laneContainer with height: 100% ​​
#straightLine {
background-color: #FFBF80;
height: 100%;
left: 104px;
position: absolute;
width: 3px;
z-index: 5;
}
Plus some small modifications to some other objects, you'll find them in the fiddle...
http://jsfiddle.net/RRupc/9/
Is something like that what you want?
Rather than adding another div to fill the space, wouldn't it be easier to add a class to the div on the left column, and style that to fill any spacing/line requirements you have?
So you could have:
HTML:
<div class="twoColumn">
<div class="column">
<div class="step doubleRow">
<p>One step covering two rows here</p>
</div>
</div>
<div class="column">
<div class="step">
<p>Single size step</p>
</div>
<div class="step">
<p>Single size step</p>
</div>
</div>
</div>
have you seen these 2 plugins?
jQuery Isotope
jQuery Mansonry
Eventually there is a solution for you!?
Take a look.
FlexBox could be worth a look too.
if you are ok with IE10 +
Auto Align Heights (CSS)
align-items: stretch
Good Reads here and here
Cheers,
Rob

margin-top not working with clear: both

<div style="float: left;">Left</div>
<div style="float: right;">Right</div>
<div style="clear: both; margin-top: 200px;">Main Data</div>
Why is the margin:top for 'Main Data' not working in the code above?
You could put the two floated divs into another one that's got "overflow: hidden" set:
<div style='overflow:hidden'>
<div style="float: left;">Left</div>
<div style="float: right;">Right</div>
</div>
<div style="clear: both; margin-top: 200px;">Main Data</div>
edit — To add a bit to this 5-year-old answer: I think the cause of the confusing behavior is the somewhat complicated process of margin collapse. A good trick with the original HTML from the OP is to add a CSS rule like this:
div { border: 1px solid transparent; }
Poof! Now (without my additional <div>) it works fine! Well, except for that extra pixel from the borders. In particular, I think it's a combination of the way that clear: both works and the margin collapse rules that result in the unexpected layout from the code in the OP.
edit again — For the complete (and, I think, completely accurate) story, see Mark Amery's excellent answer. The details have some complexity that this answer glosses over.
While Pointy shows how you can wrap the floats in a div, alternatively you can insert an empty div between the floats and the main data section. For example:
<div style="float: left;">Left</div>
<div style="float: right;">Right</div>
<div style="clear: both;"></div>
<div style="margin-top: 200px;">Main Data</div>
This might prove useful in cases where adding a div wrapper around some HTML is not desirable.
The logic behind this in the spec is mind-bending, and involves a complicated interaction of the rules for clearance and collapsing margins.
You're probably familiar with the conventional CSS box model, in which the content box is contained within a padding box contained within a border box contained within a margin box:
For elements with clear set to something other than none, an additional component may be introduced to this model: clearance.
Values other than 'none' potentially introduce clearance. Clearance inhibits margin collapsing and acts as spacing above the margin-top of an element.
In other words, the box model in those cases really looks more like this:
But when is clearance introduced, and how big should it be? Let's start with the first of those questions. The spec says:
Computing the clearance of an element on which 'clear' is set is done by first determining the hypothetical position of the element's top border edge. This position is where the actual top border edge would have been if the element's 'clear' property had been 'none'.
If this hypothetical position of the element's top border edge is not past the relevant floats, then clearance is introduced, and margins collapse according to the rules in 8.3.1.
Let's apply this logic to the question asker's code. Remember, we're trying to explain the position of the third div in the code below (backgrounds added to aid in visualisation):
<div style="float: left; background: red;">Left</div>
<div style="float: right; background: green;">Right</div>
<div style="clear: both; margin-top: 200px; background: blue;">Main Data</div>
Let us imagine, as the spec asks us to, that clear is set to none on the third div, instead of both. Then what would the snippet above look like?
<div style="float: left; background: red;">Left</div>
<div style="float: right; background: green;">Right</div>
<div style="clear: none; margin-top: 200px; background: blue;">Main Data</div>
Here, the third div is overlapping the two floated divs. But wait; why is this so? Sure, it's allowable for floated elements to overlap block-level ones (per the Floats spec, "Since a float is not in the flow, non-positioned block boxes created before and after the float box flow vertically as if the float did not exist."), but our third div has loads of margin-top on it, and comes after the two floated divs; shouldn't the two floated divs appear at the top of the body, and the third div appear 200px down, well below them?
The reason this doesn't occur is that the margin of the third div collapses into the margin of the divs' parent (in this case, the body - but the same behaviour happens if you wrap all three divs in a parent div). The Collapsing margins spec (quoted below with several irrelevant details omitted) tells us that:
Adjoining vertical margins collapse...
Two margins are adjoining if and only if:
both belong to in-flow block-level boxes that participate in the same block formatting context
no line boxes, no clearance, no padding and no border separate them ...
both belong to vertically-adjacent box edges, i.e. form one of the following pairs:
top margin of a box and top margin of its first in-flow child
...
The third div in our example certainly isn't the body's first child, but it is its first in-flow child. Note that per https://www.w3.org/TR/CSS22/visuren.html#positioning-scheme:
An element is called out of flow if it is floated, absolutely positioned, or is the root element. An element is called in-flow if it is not out-of-flow.
Since the first and second div in our example are floated, only the third div is in-flow. Thus its top margin adjoins the top margin of its parent, and the margins collapse - pushing down the entire body, including the two floated elements. Thus the third div overlaps its siblings despite having a large margin-top. Consequently - in this hypothetical case, where the third element's clear is set to none - we satisfy the condition that:
the element's top border edge is not past the relevant floats
Thus:
clearance is introduced, and margins collapse according to the rules in 8.3.1
How much clearance? The spec gives browsers two options, with a couple of clarifying notes:
Then the amount of clearance is set to the greater of:
The amount necessary to place the border edge of the block even with the bottom outer edge of the lowest float that is to be cleared.
The amount necessary to place the top border edge of the block at its hypothetical position.
Alternatively, clearance is set exactly to the amount necessary to place the border edge of the block even with the bottom outer edge of the lowest float that is to be cleared.
Note: Both behaviors are allowed pending evaluation of their compatibility with existing Web content. A future CSS specification will require either one or the other.
Note: The clearance can be negative or zero.
Before we can start applying these rules, we immediately hit a complication. Remember that collapsing margin that we had to take into account in the hypothetical case where clear was none? Well, it doesn't exist in this non-hypothetical case where we're calculating the clearance to use, because the existence of the clearance inhibits it. Recall the collapsing margin rules from 8.3.1, quoted earlier, dictate that margins are only adjoining if:
no line boxes, no clearance, no padding and no border separate them
(emphasis added). As such, the third div's top margin and the top margin of its parent are no longer adjoining. We can simulate this pre-clearance scenario in our example snippet by keeping clear: none but adding padding-top: 1px to the body, which also disables margin collapse, per the rule quoted above.
body {
padding-top: 1px;
}
<div style="float: left; background: red;">Left</div>
<div style="float: right; background: green;">Right</div>
<div style="clear: none; margin-top: 200px; background: blue;">Main Data</div>
Now, unlike when the margins were collapsed, our third div is comfortably below its two floated siblings. But we have already decided, based upon a hypothetical scenario where the margins did collapse, that clearance must be added; all that remains is to choose the amount of clearance, in order to:
place the border edge of the block even with the bottom outer edge of the lowest float that is to be cleared
And so we have no choice but to apply a negative clearance to the third div, in order to drag its top border edge up to touch the bottom outer edge (also known as margin edge) of the floated elements above it. As such, if the floated elements are each 10px high and the third div has 200px of top margin, -190px of clearance will be applied. That, at last, gets us to the final result seen by the question asker:
<div style="float: left; background: red;">Left</div>
<div style="float: right; background: green;">Right</div>
<div style="clear: both; margin-top: 200px; background: blue;">Main Data</div>
(Note that if you inspect the third div in the snippet above using your browser's dev tools, you will still be able to see the 200px of top margin above the div, going way out above all the rest of the content - it's just that the entire margin box has been hauled upwards by the large negative clearance.)
Simple!
Pointy and Randall Cook have excellent answers. I thought I'd show one more solution.
<div style="float: left;">Left</div>
<div style="float: right;">Right</div>
<div style="float: left; clear: both; margin-top: 200px;">Main Data</div>
If you make the 3rd element "float: left;" AND "clear: both;", it should have the desired effect of giving the 3rd element a 200 pixel margin. Here's a link to an example.
This also might affect other followup elements as to whether they need to be floats or not. However, it might also have the desired effect.
Alternative solution:
You can actually put a margin-bottom on the floated elements to push
DOWN the element underneath that has clear: both.
http://jsfiddle.net/9EY4R/
Note: Having made this suggestion I have to immediately retract it as not generally a good idea, but in some limited situations may appropriate;
<div class='order'>
<div class='address'>
<strong>Your order will be shipped to:</strong><br>
Simon</br>
123 Main St<br>
Anytown, CA, US
</div>
<div class='order-details'>
Item 1<br>
Item 2<br>
Item 3<br>
Item 4<br>
Item 5<br>
Item 6<br>
Item 7<br>
Item 8<br>
Item 9<br>
Item 10<br>
</div>
<div class='options'>
<button>Edit</button>
<button>Save</button>
</div>
</div>
The panel with items is called order-details with this css
.order-details
{
padding: .5em;
background: lightsteelblue;
float: left;
margin-left: 1em;
/* this margin does take effect */
margin-bottom: 1em;
}
In the above fiddle - the yellow panel has a margin-top, but unless it is greater than the tallest floated item then it won't do anything (of course that's the whole point of this question).
If you set the margin-top of the yellow panel to 20em then it will be visible because the margin is calculated from the top of the outer blue box.
Use 'padding-top' in your main data div instead. Or, alternatively, wrap the main data div in one with 'padding-top'.
Try setting a bottom margin on one of the floated elements. Alternatively, you can wrap the floats in a parent element, and use a css hack to clear it without additional markup.
Sometimes a combination of position relative and margin can solve these type of problems.
I use this technique for my alignright and alignleft classes in WordPress.
For instance if I want a "bottom margin" that is respected by clearing elements you can use.
.alignright{
float: right;
margin-left: 20px;
margin-top: 20px;
position: relative;
top: -20px;
}
For your example you could do something like
<div style="float: left;">Left</div>
<div style="float: right;">Right</div>
<div style="clear: both; margin-bottom: 200px; position: relative; top: 200px;">Main Data</div>

CSS 3 columns, why is the third column taking over the other 2?

Here is the smallest amount of code that clearly illustrates my problem:
<html>
<body>
<div style="float: left; width: 200px;">One</div>
<div style="float: left; width: 200px;">Two</div>
<div style="background-color: #f0f;">Three</div>
</body>
</html>
The first 2 divs are supposed to be 2 left columns. The 3rd should take up the rest of the page. Eventually, I'm going to add options to hide and show the 2 columns on the left.
But, why is the color purple extending all the way to the browser's left edge? I am trying to get it to start at the word "Three".
You need to 'float' the third column as well. Then add a clearing block after it.
See Block formatting contexts by W3C:
In a block formatting context, each box's left outer edge touches the left edge of the containing block (for right-to-left formatting, right edges touch). This is true even in the presence of floats (although a box's line boxes may shrink due to the floats), unless the box establishes a new block formatting context (in which case the box itself may become narrower due to the floats).
You can avoid that by forcing creation of new blocking formatting context:
<div style="background-color: #f0f; overflow: hidden">Three</div>
If overflow: hidden is not an option for you (popups etc.), here is another technique:
<div class="has-columns">
<div class="column first">...</div>
<div class="column second">...</div>
<div class="column third">...</div>
</div>
.has-columns {
padding-left: 400px; /* padding reserved for floats */
}
.column.first {
width: 180px;
margin-left: -400px;
float: left;
}
.column.second {
width: 180px;
margin-left: -200px;
float: left;
}
I have to admit, the behavior of floats can be confusing sometimes.
Depending what you want to have happen when columns one and two disappear, you have a few options:
1) If you want column 3 to expand and fill all the remaining space simply add overflow: hidden; to the styles of the third div. It will flow next to the two floated divs just as you expect.
2) If you want the third column to keep it's size and shape no matter what happens to columns 1 and 2, float it to the right, with a set width such as float: right; width: 200px; and it will no longer be effected by the other two, but stay 200px at the right edge of the container.

Resources