Why does setting overflow alter layout of child elements? - css

In this question someone was having a layout problem because they had two floated divs inside a non-floated div. I suggested adding float: left to their outer div, which does fix the problem. Someone else suggested adding overflow: hidden, which to my surprise, also worked.
This doesn't seem at all like the purpose of of overflow: hidden. Clearly overflow: hidden causes elements to view their children differently somehow. What I'm really trying to understand is what that difference is. Intuitively it should only make the element smaller than it would otherwise be, never bigger and I don't see why it would affect the layout hierarchy.
Can anyone explain why this would be correct/necessary behavior or if this is just a browser quirk? Is their another facet to the overflow property I'm missing? Is either solution any better than the other?
Edit: I've discovered setting overflow: auto works too, so it doesn't seem to be the value of overflow that's important, just that it's set. I still don't understand why.

Overflow of anything but visible creates a new block formatting context which causes floats to be contained. It's standard behaviour.
Floats, absolutely positioned
elements, inline-blocks, table-cells,
table-captions, and elements with
'overflow' other than 'visible'
(except when that value has been
propagated to the viewport) establish
new block formatting contexts.
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 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).

Floating items removes them from the normal layout in many cases. It's not exactly like or unlike position: absolute; in that. Block items tend to ignore floated items (including block items that contain the item), but unlike position: absolute; items, floated ones are recognized and wrapped around by inline items, like text.
Having the wrapping item (div or otherwise) also be floated causes it to behave differently related to floated items it contains. Having the wrapping item set to overflow: hidden; forces it to consider the items it contains differently, as well. My guess is it's just a happy coincidence that the end result here appears to be the same. Not a quirk or bug... just how it works out.

Related

Effect of overflow and clear styles with floats

I'm pretty CSS-savvy, but I'm seeing some odd float/clear behavior. I have it working, but I'm not entirely sure why and am looking for an explanation.
JSFiddle: http://jsfiddle.net/ismyrnow/JV5n6/
I have a 2 column layout - sidebar and content - where the sidebar is floated but the content is not; the content div has a left margin applied to it.
If I use clear:both on any elements in the content div, the element unexpectedly drops below the height of the sidebar div (unexpectedly because the floated sidebar isn't directly affecting the positioning of items inside the content area).
What is even more unexpected, is that when I add overflow:auto to the content div, the problem goes away. (I found the solution here)
Can someone explain:
Why clear:both would cause an element to clear a floated element that isn't directly affecting its position.
Why overflow:auto on the parent element fixes the issue.
Why clear:both would cause an element to clear a floated element that isn't directly affecting its position.
It may not be directly affecting its position, but it would still have affected it anyway, because in the absence of any clearance, floats aren't normally restricted in how they affect the rest of the normal flow layout even once they are taken out of it, not even by different parent elements such as your .b content element with the left margin in this case. The only real restriction is that floating elements may only affect elements that come after them in document tree order, i.e. elements that are following (not preceding) siblings, as well as their descendants.
The content that's just above the element within your content column isn't tall enough to push it beneath the floated element. If you remove that declaration, you would see that both .c elements become positioned next to their respective floats as well.
When you add clear, what happens is that it forces the clearing element to be positioned beneath the float regardless of where it ends up horizontally.
Why overflow:auto on the parent element fixes the issue.
This is because any block boxes with overflow other than visible generate block formatting contexts. A property of a block formatting context is that floating boxes outside it can never interact with any boxes inside it, and vice versa.
Once you cause the content element to establish its own block formatting context, your floating element is no longer able to affect any elements inside the content element (see the section on the float property), and the clearing element inside it is no longer able to clear any floats that are outside the content element (see the clear property).
For clear:both
The clear CSS property specifies whether an element can be next to floating elements that precede it or must be moved down (cleared) below them.
The clear property applies to both floating and non-floating elements.
When applied to non-floating blocks, it moves the border edge of the element down until it is below the margin edge of all relevant floats. This movement (when it happens) causes margin collapsing not to occur.
When applied to floating elements, it moves the margin edge of the element below the margin edge of all relevant floats. This affects the position of later floats, since later floats cannot be positioned higher than earlier ones.
The floats that are relevant to be cleared are the earlier floats within the same block formatting context.
I hope this will clear your doubt.
This is the link from where i found the above info.....
https://developer.mozilla.org/en-US/docs/Web/CSS/clear

Overflow:hidden in float. Does it hide anything?

I understand that overflow:hidden is a way to clear float, but I do not understand why.
I suppose that If we do use overflow:hidden it is because there is something outside the element that was affected by the float? if so, what is hidden?
For example, in this case, is there anything in #second that is hidden that makes it be beside #first ?
(There is another question that is related, but this is different, this is more specific. My question is: does "overflow:hidden" hide anything? what is it?)
Here is the example: http://jsfiddle.net/NSCpD/
CSS:
#first{
float:left;
width:100px; height:100px;
background:blue;
}
#second{
width:300px; height:300px;
overflow:hidden; /* això fa que no li afecti el float */
background:red;
}
HTML:
<div id="first"> </div>
<div id="second"> </div>
An element with an overflow value other than visible establishes a new Block Formatting Context. The fiddle your provided is a bit different than when an in-flow block level element contains a float. Even if the in-flow block level element is a sibling of an out of flow float it will still acknowledge it's presence as if it were a line box when a new BFC is created. The spec describes this in these two excerpts:
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, 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).
As its name suggests, overflow:hidden hides any content that overflows the element (i.e. excesses the given dimensions). In this example there is no overflow actually, so nothing is hidden. But the side-effect of setting the overflow other than visible (as well as display: inline-block, float itself etc.) is the change of the behavior of the block. While the normal block effectively doesn't take floats into account at all (only its text content does), the block that establishes new block formatting context (see Adrift's answer) isolates all of its content inside, including nested floats, potentially collapsible margins etc.
This side effect may be used to prevent the container of floats from collapsing, but it doesn't have anything to do with clearing floats. Clearing and BFCs act very differently in case of collapsible margins, other floats earlier in the document, etc.

What is the difference between block and inline-block with width: 100%?

I've recently been trying to figure out when it is appropriate to use inline-blocks. They seem to be far more useful than just a block element. In fact, an inline-block element seems to be able to do anything a block element can do, but with a little extra styling.
Is there any reason an element with display: inline-block; width: 100%; is any different than an element with display: block;? (Aside from the fact that one is longer?)
I've been researching this topic by reading the w3c recommendation. I can't seem to find a difference.
What you said is pretty much correct: "an inline-block element seems to be able to do anything a block element can do, but with a little extra styling." This is mostly due to the fact that the one thing both have in common is the fact that they are both block containers.
However, there's a catch.
A block box participates in a block formatting context, and an inline-block participates in an inline formatting context (although it establishes a block formatting context for its descendants, just like a block box does under certain conditions). See section 9.4. Basically, this means an inline-block is treated as though it were text, which in turn means most properties that usually apply to text would also apply to an inline-block. These properties include text-indent, text-align and vertical-align, among others.
This can cause undesired side effects which you can easily prevent by not using display: inline-block in the first place. See this question for an interesting example of what can happen.
The box model for inline-blocks also differs somewhat from that of block boxes. Section 10 contains all the nitty gritty details, but the main differences are:
Without the width: 100% declaration, as you may have suspected, an inline-block will shrink to fit its contents.
Because an inline-block flows inline, you can't center it with auto left and right margins. You use text-align: center instead. It goes without saying that it must then be on its own line with no text surrounding it on the same line, but if you're setting width: 100% then this won't be a problem.
Inline-blocks are never affected by margin collapse.
If you're trying to create a block-based layout, you should be using display: block. Generally speaking, when deciding between the two, you should always default to display: block, and only choose display: inline-block if you have a very good reason to (and no, blocking margin collapse is not what I would consider a good reason).
I'd echo everything said by #BoltClock; he makes a lot of good points.
I would also add to this that because an inline-block is treated as text, the surrounding white space is also treated as text and thus comes into play in ways that it wouldn't for a block element. This frequently catches people out when trying to use inline-block for layout. This is probably the biggest 'gotcha' for using inline-block.
Another slightly more subtle point applies specifically in your case, ie when setting width:100%. In this case, you need to beware of which box model you're using, as the standard box model puts your borders, padding and margins outside of the element's width. Thus if you use borders, padding or margin your element will actually take up space a little bit more than 100% width.
This point applies equally to block and inline-block elements, but is more likely to occur with inline-block because the difference is that block doesn't normally need to be set to width:100% because it defaults to expand to fill the width anyway, and without the box model causing it to go over the edge.
To avoid this, you could switch the box model by using box-sizing:border-box, so that the borders etc are placed inside the box, and thus if you ask for with:100%, that's what you'll get. See the MDN box-sizing page for more info.

Text squashed when using position: absolute;

I have a text box that will expand across the screen when I do not use position: absolute;, however upon using it, the text is all in one column per word, and the box is very tiny.
What is causing this? Or what can cause this? I've been trying overflow settings, different sort of positions and z-indexes, etc.
This is a good question because it highlights an important aspect of absolutely positioned elements.
If you don't specify the width of an absolutely positioned element, or if you don't specify the left and right offsets, then the width is computed to be a shrink-to-fit width similar to what is done for table cells.
The details are given in the CSS specification, Chapter 10: http://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-width
There are also some subtle consequences when you place an absolutely positioned element such that it triggers an overflow condition or when one of the edges if out of the view port. In these cases, a absolutely positioned block may have a computed width smaller than you specified.
The key is to consider what type and how much content the block will hold and provide a clear constraint for setting the width, either with a fixed value of a relative value.
Example
If you absolutely position the following:
<div class="abs ex3"><b>Small amount of text:</b> shrink-to-fit</div>
as shown in http://jsfiddle.net/audetwebdesign/SHxPR/, then the computed width of the block will be smaller than the width of the page. The block will expand in width and then height as needed to accommodate more text.
The element where you have position:absolute; is doing as it is expected to do. You should use position:relative; to the parent container for this absolutely positioned element.

CSS overflow property

I've found some CSS templates where some classes have the overflow:hidden property, but no size defined. If I recall correctly, block elements stretch to fit their content unless otherwise specified. Since this is not the case, I feel that putting the overflow:hidden is pointless and I can delete it without hesitation. Is this right or am I missing something?
While that's the main purpose of the overflow property, it's not the only effect it has on rendering. The other major effect it has is that setting overflow to anything other than visible (the default) causes a block box to establish its own block formatting context.
This is mainly used to contain floats without the need for a clearfix; however that isn't the only effect of having a new BFC; there are a number of other corner cases that are better described elsewhere in the spec. Also see this lengthy write-up on the reasoning for this behavior (which, oddly enough, has very little to do with containing floats; that actually ends up being nothing more than a side effect).
So if you remove that overflow declaration, you may break float layouts, among other things. I suggest avoiding doing so unless it's absolutely necessary or you're sure it won't affect the layout.
If there are floating children inside that div, then overflow: hidden is probably there to contain them.
overflow: hidden creates a new block formatting context, and elements that create new block formatting contexts contain floats.
It may depend. if your div contains some floated elements you could use
div {
height: auto;
overflow : hidden;
}
as a workaround for the clearing. So I wouldn't delete that rule without seeing the effect on the layout
overflow:hidden can come in handy if you have a child element with a width specified which is greater than the container's max allowed width. Otherwise it will stretch the container.
See example
A common use of this is when displaying a carousel, with floated child elements. The elements need to appear inline, but hidden, so that they can come into vision when the left CSS property is changed.

Resources