Why the CSS's overflow property clear float? - html

I tried the next code:
div.a {
position: relative;
width: auto;
height: auto;
border: 3px solid #73AD21;
}
div.b {
float: right;
width: 200px;
height: 100px;
border: 3px solid #73AD21;
}
<div class="a">The outer box;
<div class="b">The inner box</div>
</div>
But for some reason, when I use float instead of another way of positioning, then the outer box become to be with small height, and the inner box flows out of the outer box.
When I asked my friend, then he told me to add the property overflow: hidden; to the outer box.
It worked, and the outer box streched enough to contain the inner box.
When I learned about this property, I learned that the porpose of this, is to show\disappear etc scroll bar.
Somebosy can please explain me the aother thing about overflow I didnt understood?

Quoting from Block formatting contexts
Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions) that are not block boxes, and block boxes with 'overflow' other than 'visible' (except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.
In a block formatting context, boxes are laid out one after the other, vertically, beginning at the top of a containing block. The vertical distance between two sibling boxes is determined by the 'margin' properties. Vertical margins between adjacent block-level boxes in a block formatting context collapse.
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).
According to the above quoted text and what I understand,
overflow:hidden causes a new float context, which clears the float from the child elements which are floating. Hence the parent auto adjusts.
It would be similar to clearing the parent like this:
#parent:after {
content: "";
display:table;
clear: both;
}
Example with manual clearing the parent:
div.a {
position: relative;
width: auto;
height: auto;
border: 3px solid #73AD21;
}
div.b {
float: right;
width: 200px;
height: 100px;
border: 3px solid #73AD21;
}
div.a:after {
content: "";
display: table;
clear: both;
}
<div class="a">The outer box;
<div class="b">The inner box</div>
</div>

You are using float but not clearing. Use following code it will works
First Option
<div class="a">The outer box;
<div class="b">The inner box</div>
<div class="clear"></div>
</div>
<div class="clear"></div>
div.a {
position: relative;
width: auto;
height: auto;
border: 3px solid #73AD21;
}
div.b {
float: right;
width: 200px;
height: 100px;
border: 3px solid #73AD21;
}
.clear {
clear:both;
}
Second Option
<div class="a">The outer box;
<div class="b">The inner box</div>
</div>
div.a {
position: relative;
width: auto;
height: auto;
border: 3px solid #73AD21;
}
div.b {
float: right;
width: 200px;
height: 100px;
border: 3px solid #73AD21;
}
div.a:after,div.b:after {
content"";
display:block;
clear:both;
}

Related

Why does margin-left not work on block elements to the right of float:left images? [duplicate]

Here is my code:
.wrapper {
border: 1px dashed red;
overflow: auto;
/*clear floating*/
}
.left {
width: 120px;
border: 5px solid #ddd;
float: left;
margin-right: 20px;
}
.right {
border: 5px solid #ddd;
overflow: auto;
/*make div.right become a new BFC*/
}
<div class="wrapper" id="wrapper">
<div class="left">This is a float div, width 120px.</div>
<div class="right">This is a div.</div>
</div>
why cannot I use margin-left:20px; in .right to get the same result as margin-right:20px; in .left?
I know margin-left:150px in .right can get the same result, but why div.right as a new BFC still ignore the floating div.left while div.left doesn't ignore div.right?
margin-left:20px in .right
margin-right:20px in .left
The relevant part of the spec is https://www.w3.org/TR/CSS22/visuren.html#bfc-next-to-float which says:
The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap the margin box of any floats in the same block formatting context as the element itself. If necessary, implementations should clear the said element by placing it below any preceding floats, but may place it adjacent to such floats if there is sufficient space. They may even make the border box of said element narrower than defined by section 10.3.3. CSS2 does not define when a UA may put said element next to the float or by how much said element may become narrower.
Which gives browsers a bit of latitude in what they actually do here, but the point is, if they place the BFC next to the float, the Border Box of the BFC must not overlap the Margin Box of the float. So changing the size of the margin on the BFC won't impact on that constraint, but changing the size of the margin on the float will.
The MDN doc says :
when you float the element to left the elements comes after taken out of the normal flow of the document (though still remaining part of it). It is shifted to the left, or right, until it touches the edge of its containing box, or another floated element.
so if the right element have width of 100px
the floated element comes after it will not take any action if you give it margin lower than 100px e.g 20px because it already far enough from this point but if you give it 200px it will take action
.wrapper {
border: 1px dashed red;
overflow: auto;
/*clear floating*/
}
.left {
width: 120px;
border: 5px solid #ddd;
float: left;
margin-right: 20px;
}
.wrapper:after {
content: "";
display: table;
clear: both;
}
.right {
border: 5px solid #ddd;
overflow: auto;
/*make div.right become a new BFC*/
margin-left:200px; ๐Ÿ‘ˆ๐Ÿ‘ˆ
}
<div class="wrapper" id="wrapper">
<div class="left"></div>
<div class="right"></div>
</div>

Why margin-left of a Block Formatting Context element cannot get a same result as margin-right of a float element?

Here is my code:
.wrapper {
border: 1px dashed red;
overflow: auto;
/*clear floating*/
}
.left {
width: 120px;
border: 5px solid #ddd;
float: left;
margin-right: 20px;
}
.right {
border: 5px solid #ddd;
overflow: auto;
/*make div.right become a new BFC*/
}
<div class="wrapper" id="wrapper">
<div class="left">This is a float div, width 120px.</div>
<div class="right">This is a div.</div>
</div>
why cannot I use margin-left:20px; in .right to get the same result as margin-right:20px; in .left?
I know margin-left:150px in .right can get the same result, but why div.right as a new BFC still ignore the floating div.left while div.left doesn't ignore div.right?
margin-left:20px in .right
margin-right:20px in .left
The relevant part of the spec is https://www.w3.org/TR/CSS22/visuren.html#bfc-next-to-float which says:
The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap the margin box of any floats in the same block formatting context as the element itself. If necessary, implementations should clear the said element by placing it below any preceding floats, but may place it adjacent to such floats if there is sufficient space. They may even make the border box of said element narrower than defined by section 10.3.3. CSS2 does not define when a UA may put said element next to the float or by how much said element may become narrower.
Which gives browsers a bit of latitude in what they actually do here, but the point is, if they place the BFC next to the float, the Border Box of the BFC must not overlap the Margin Box of the float. So changing the size of the margin on the BFC won't impact on that constraint, but changing the size of the margin on the float will.
The MDN doc says :
when you float the element to left the elements comes after taken out of the normal flow of the document (though still remaining part of it). It is shifted to the left, or right, until it touches the edge of its containing box, or another floated element.
so if the right element have width of 100px
the floated element comes after it will not take any action if you give it margin lower than 100px e.g 20px because it already far enough from this point but if you give it 200px it will take action
.wrapper {
border: 1px dashed red;
overflow: auto;
/*clear floating*/
}
.left {
width: 120px;
border: 5px solid #ddd;
float: left;
margin-right: 20px;
}
.wrapper:after {
content: "";
display: table;
clear: both;
}
.right {
border: 5px solid #ddd;
overflow: auto;
/*make div.right become a new BFC*/
margin-left:200px; ๐Ÿ‘ˆ๐Ÿ‘ˆ
}
<div class="wrapper" id="wrapper">
<div class="left"></div>
<div class="right"></div>
</div>

Positioning divs inside a container

I have a general, possibly beginner question about HTML.
#container {
height: 200px;
max-width: 600px;
border: 1px solid black;
margin: auto;
margin-top: 10px;
}
#item1 {
height: 100px;
max-width: 200px;
border: 1px solid red;
}
#item2 {
height: 100px;
max-width: 200px;
border: 1px solid blue;
}
<div id="container">
<div id="item1"></div>
<div id="item2"></div>
</div>
My question is, why do #item1 and #item2 divs go underneath each other as opposed to next to each other? Isn't it true that they are no longer block-level elements because I have specified a set width for them? Why are they not lined up next to each other inside of #container? The #container has more than enough width to accommodate both items.
Note: This is strictly for learning/curiosity. I know that I can use margins and positioning to place them where I want to. However, I'm just curious as to why it behaves this way.
Thanks.
Div elements are block elements, unless you specify the display property to inline or inline-block it wont align to to the right like other inline elements do.
adding display : inline-block to the css of div's will give you what you want.
You have two ways to place you blocks horizontally: display property or float property.
It doesn't matter that you have set width to your elements. They are still block and displayed vertically.
To change this behaviour, use stylesheet (note that in both cases width, not max-width should be set):
#container {
height: 200px;
max-width: 600px;
border: 1px solid black;
margin: auto;
margin-top: 10px;
}
#item1 {
height: 100px;
width: 200px;
border: 1px solid red;
display: inline-block;
}
#item2 {
height: 100px;
width: 200px;
border: 1px solid blue;
display: inline-block;
}
or this:
#container {
height: 200px;
max-width: 600px;
border: 1px solid black;
margin: auto;
margin-top: 10px;
}
#item1 {
height: 100px;
width: 200px;
border: 1px solid red;
float: left;
}
#item2 {
height: 100px;
width: 200px;
border: 1px solid blue;
float: left;
}
<div> tag always start with new line if you are not using frameworks like bootstrap or other. If you want to see multiple items in single line then add css like display: inline-block
just add float:left; property in child divs or display:inline-block; https://jsfiddle.net/8tvn0kw6/5/
div is the standard block-level element. A block-level element starts on a new line and stretches out to the left and right as far as it can. Other common block-level elements are p and form, and new in HTML5 are header, footer, section, and more.
Even if you specify width it wont allow other elements right next to it. This the property of block level element.
Use the css inline-block it will occupy the specified width or content width.
https://developer.mozilla.org/en-US/docs/CSS/display
The height of the container should be the sum of heights of the child divs and the heights of the borders of the children
ie., height of parent container = 100+ 100+ 1+ 1+ 1+ 1 = 204px
#container {
height: 204px;
}
The #container ie you div has a display property of block. This is a default property if you don't set it to anything else. In your case the div takes this default display property.
To view #item1 and #item2 side by side just use display: inline-block in your #container.
Please replace your class like below.
#item1{
height:100px;
max-width:200px;
border:1px solid red;
display:inline-block;
}
#item2{
height:100px;
max-width:200px;
border:1px solid blue;
display:inline-block;
}

css relative positioning breaks div into new line

I have the following fiddle for this question: http://jsfiddle.net/jcb9xm44/
There are 2 inline-block div's in a parent div:
<div class="outer">
<div class="inner1">
Y
</div>
<div class="inner2">
X
</div>
</div>
The css assigns a width to the parent div and 2 widths to the child div's.
.outer {
width: 210px;
border: 1px solid red;
}
.inner1 {
width: 200px;
border: 1px solid orange;
display: inline-block;
}
.inner2 {
width: 50px;
position:relative;
left: -50x;
display: inline-block;
border: 1px solid lightblue;}
I was expecting that both divs appear on the same line. Although the parent is not wide enough to hold both children, since the second child has a negative offset, it should be possible to fit them both on the same line. Why does it break the line?
Why does it break the line?
As you stated, it's because the parent element isn't wide enough for both elements. To change this behavior, you could add white-space: nowrap to the parent element in order to prevent the inline-block elements from wrapping.
Example Here
.outer {
width: 210px;
border: 1px solid red;
position:relative;
white-space: nowrap;
}
Side notes:
You had a typo - left: -50x -> left: -50px.
inline elements respect whitespace in the markup.
The element's border is included in its width calculations. Use box-sizing: border-box to include it.
You could alternatively use margin-left: -50px as Mary Melody pointed out.

`margin:auto;` doesn't work on inline-block elements

I have a "container" div to which I gave margin:auto;.
It worked fine as long as I gave it a specific width, but now I changed it to inline-block and margin:auto; stopped working
Old code (works)
#container {
border: 1px solid black;
height: 200px;
width: 200px;
}
.MtopBig {
margin-top: 75px;
}
.center {
margin-left: auto;
margin-right: auto;
text-align: center;
}
<div class="center MtopBig" id="container"></div>
New code (doesn't work)
#container {
border: 1px solid black;
display: inline-block;
padding: 50px;
}
.MtopBig {
margin: 75px auto;
position: relative;
}
.center {
text-align: center;
}
<div class="center MtopBig" id="container"></div>
DEMO fiddle.
It is no longer centered because it now flows on the page in the same way inline elements do (very similarly to img elements). You will have to text-align: center the containing element to center the inline-block div.
#container {
border: 1px solid black;
display: inline-block;
padding: 50px;
}
.MtopBig {
margin: 75px auto;
position: relative;
}
.center {
text-align: center;
}
<div class="center">
<div class="MtopBig" id="container"></div>
</div>
What 'auto' means:
Using auto for the horizontal margin will instruct the element to fill up the available space (source: http://www.hongkiat.com/blog/css-margin-auto/).
Why 'display: inline-block' does not center:
There is no available horizontal space in an inline setting. Before and after it are other inline elements (characters) that take up their own space. Therefore, the element will act as if the horizontal margin is set to zero.
Why 'display: block' centers:
When used as an element with display: block set to it, the available horizontal space will be the full width of the parent element minus the width of the element itself. This makes sense because display: block is reserving this horizontal space (thus making it 'available'). Note that elements with display: block cannot be placed next to each other. The only exception occurs when you use float, but in that case you also get the (expected) zero-margin-behaviour, as this disables the horizontal 'availability'.
Solution for 'inline-block' elements:
Elements with display: inline-block should be approached as characters. Centering characters/text can be done by adding text-align: center to their parent (but you probably knew that already...).
For elements with property display: inline-block;
A computed value of 'auto' for 'margin-left' or 'margin-right' becomes a used value of '0'. [reference: CSS2ยง10.3.9]
margin-left:50%;
transform: translateX(-50%);
.container{
border:solid 1px red;
}
.container img{
display:inline-block;
margin-left:50%;
transform: translateX(-50%);
}
<div class="container">
<img src="https://placekitten.com/100/300" />
</div>