How to make container avoid float like its inner text - css

I feel like there should be an easy answer to this. I have a sidebar floated to the right, when I noticed there were some issues on the hover. Turns out my
<p>
tags on the left were crossing over into the float, even though the text inside them properly avoided the float. I made a simple jsfiddle example to show what I mean, and turned their backgrounds on so you can see them overlapping.
JSFiddle: http://jsfiddle.net/ahvs3nr3/

Adding this CSS fixes the problem:
p {
overflow: auto;
}
Working Fiddle
In your code, the container (p) overflowed the sidebar, even though its content was constrained to not overflow.
From the W3 spec:
Floats, absolutely positioned elements, block containers
... that are not block
boxes, and block boxes with 'overflow' other than 'visible' ... establish new
block formatting contexts for their contents.
This is what led me to try overflow: auto.
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).
This explains why the container overflows the sidebar, but its "line box" (which contains its text) does not.
So what exactly is a "line box"?
In an inline formatting context, boxes are laid out horizontally, one
after the other, beginning at the top of a containing block.
Horizontal margins, borders, and padding are respected between these
boxes. The boxes may be aligned vertically in different ways: their
bottoms or tops may be aligned, or the baselines of text within them
may be aligned. The rectangular area that contains the boxes that form
a line is called a line box. The width of a line box is determined by a
containing block and the presence of floats.
There are no explicit inline elements, so what causes this "inline formatting context"?
Any text that is directly contained inside a block container element
(not inside an inline element) must be treated as an anonymous inline
element.
And there you have it. The text within each paragraph is an "anonymous inline element," which creates a "line box," which is influenced by floats.

I think it's the <p> tag is a block element. Will this work in your case?
p {
display: table;
}
http://jsfiddle.net/ahvs3nr3/3/

Just add some margin right of the p tags.
.sidebar {
background-color:rgba(0,0,0,.2);
float:right;
width:25%;
height:30em;
}
p { background:red; padding:1em; margin-right: 25%; }
I also added a jsfiddle for reference.
http://jsfiddle.net/ahvs3nr3/2/
I use % margins here because they will adapt to any width browser however if you want to use a 5em sidebar just make sure the p tags have the same amount of margin right.

Related

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.

Css float drawbacks

Here goes the code:
<style>
.thumbnail
{
float:left;
width:110px;
height:90px;
margin:5px;
}
</style>
<body>
<img src="klematis_small.jpg" style="width:107px; height:140px">
<img class="thumbnail" src="klematis_small.jpg" style="width:107px; height:150px">
The confusing is why the second img which is floated appering before the first img.If we place the first img to second img everything works as expected.
Floated elements are taken out of the normal document flow:
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. However, the current and subsequent line boxes created next to the float are shortened as necessary to make room for the margin box of the float.
Only line boxes (elements in the inline formatting context) respect floats, usually this is in the form of text. Also remember that floats will always be positioned on top (in the stacking order) when colliding with in-flow block level elements, but it will appear behind all lines boxes ..
The contents of floats are stacked as if floats generated new stacking contexts, except that any positioned elements and elements that actually create new stacking contexts take part in the float's parent stacking context. A float can overlap other boxes in the normal flow (e.g., when a normal flow box next to a float has negative margins). When this happens, floats are rendered in front of non-positioned in-flow blocks, but behind in-flow inlines.
The section on floats in the Visual Formatting Model is helpful if you're interested in learning the specifics
References: Section 9.4, Floats, CSS 2.1 Specification
You copy example from W3Schools but didn't read:
How Elements Float
Elements are floated horizontally, this means that an element can only be floated left or right, not up or down.
A floated element will move as far to the left or right as it can.
Usually this means all the way to the left or right of the containing
element.
Yes. This is normal and expected. If you want the first one first, you need to float them both.
I wouldnt use floats, just use display: inline-block; which will display your items exactly in the same order as the code is written.

Formatting DIV to the right of a FLOAT LEFT problems with padding and lists

I have a quandary. I have an application where CSS seems to do what it is supposed to do, but does not show results as you would expect and I can find no solution to get the "expected" results. The issue is how content is flowed when there is a float element to the left of the content and the content styles use padding or margins.
In my application, users can enter text in a DIV. There may or may not be a float left element so that the div with the text can either be at the left of the body area or shifted to the right (i.e. after the floating element).
When there is no floating element, the text is fine with paragraphs (i.e. with divs and appropriate classes) that are left, indented, first line indented, or hanging.
The CSS for the paragraphs are:
.firstindent { text-indent:30px; }
.indent { padding-left:30px; }
.hanging { padding-left:30px; text-indent:-30px; }
However, when a a float left element is added, only the standard and first indent show properly. This is because padding, borders, and margins are outside the box model "content" and only items in the "content" area are adjusted for the float.
Floats. In the float model, a box is first laid out according to the normal flow, then >taken out of the flow and shifted to the left or right as far as possible. Content may
flow along the side of a float.
If you use Firefox with Firebug, you can highlight the divs and you will find that the padding is shown at the left edge, i.e. "underneath" the floating element, not adjusted to the right of the floating element.
As a result, the paragraphs with a float left element look like this:
(Note that the float element also effects the presentation of lists.)
So far, I have not been able to come up with a CSS solution that lets me set the main text contents and then have them properly display whether or not there is a float left element to the left.
I have posted a full HTML sample so please feel free to snag the source and see if you can find a solution! Sample Page
Thank you - I should have included the "what you expect". Here it is with the float left and the float left spacer.
To correct, set overflow: hidden on all your paragraph elements (and lists, etc.) See fiddle.

Text position inline of a div

This is live demo: http://jsfiddle.net/9Y7Cm/5/
Everything is fine with that, until the text width there is higher than the div width.
If you will add some text there, the line will break and the text will be displayed under of the image instead of next to the image (as you can see in my first fiddle).
Here you can see what happends, it text width is higher than div container width:
http://jsfiddle.net/9Y7Cm/12/
Is there a way to fix that?
Give your right side content a width and float it to the right, like so:
http://jsfiddle.net/9Y7Cm/14/
For a cleaner result, i suggest you separate both sides of your content, left and right, with a class and width and then float them to set them side by side.
Just remove display:inline-block; from the CSS for the span element (jsFiddle example).
More information on display:inline-block.
inline-block: This value causes an element to generate an inline-level block container. The inside of an inline-block is formatted as a block box, and the element itself is formatted as an atomic inline-level box.
The problem is with display:inline-block for the span. Remove it, and the text will be on the same line

div not floating along the preceding div with float property set to left

Which CSS rules explain the following sceanrio:
Assuming I have the following HTML CSS snippets
HTML:
<div id="main">
<div id="first">
first div float left
</div>
<div id="second">
second div does not have a float property set
and appears in a new line instead of next to
the first div
</div>
</div>
CSS:
#first
float: left
What I am wondering about is, why the second div floats next to the first div, only when its width is set. If I replace the second div with a paragraph, it also floats next the first div. So why does the second div only position next to the first one when its width is set or its own float property is set to float left?
By the way. I am not trying to achieve any sort of layout here. I am just trying to understand these particular behaviours of the div element and other block elements.
EDIT:
OK. First of all thanks for the answers. The problem I had was based on the fact that I did set the width of the first and the second div to the same value, so that the content of the second could not float around the first one. To sum things up, I guess it is important to know that elements with the float property set are taken put of the page flow and dont take up any space. Secondly one should remember only the content can flow around, not the actual div.
A <div> is a block level element which is 100% wide and has a line break before & after when it's within the normal content flow.
Technically, when you float a <div>, you're taking the element out of the normal flow so it no longer has a line-break before & after and also the other page content flows around it.
So why does the second div only position next to the first one when
its width is set or its own float property is set to float left?
Floated <div>'s will always appear side-by-side only if there's enough room to contain them side-by-side. Otherwise, the next floated <div> will wrap to a new line. This is because floated <div>'s are outside the content flow and defined to behave this way in the spec.
However, you've made some incorrect assumptions in your question about what happens when you set the width of the second (non-floated) <div>.
The second <div>, itself, is always underneath (meaning behind) the floated <div>. Whereas, the "content" of the second <div> always flows around the floated <div>. (see three examples below)
So whether or not you set the width of the second div, its content will still flow around the left floated div as you can see illustrated here in three examples. (For illustration purposes, the first <div> is red with 50% opacity and the second is blue with a thick green border.)
Fiddle with second div wider than first
Fiddle with no set width (100%) on second div
Fiddle with second div narrower than first
As you can see from all three examples above, despite the existence of the floated first <div>...
the second <div> always starts on the left edge of the screen despite the width of the second <div>.
the second <div> always starts on the top edge of the screen because there's no other page flow content above the second <div>.
the actual content of the second <div> flows around (to the right of) the floated first <div> only where there is enough room inside its container to allow it to flow around the floated <div>. Otherwise, it appears as if it's starting a new line where really only its content is continuing to flow around the bottom of the floated <div>.
W3C Spec: 9 Visual formatting model, 9.5 Floats
A float is a box that is shifted to the left or right on the current
line. The most interesting characteristic of a float (or "floated" or
"floating" box) is that content may flow along its side (or be
prohibited from doing so by the 'clear' property). Content flows down
the right side of a left-floated box and down the left side of a
right-floated box. The following is an introduction to float
positioning and content flow; the exact rules governing float behavior
are given in the description of the 'float' property.
A floated box is shifted to the left or right until its outer edge
touches the containing block edge or the outer edge of another float.
If there is a line box, the outer top of the floated box is aligned
with the top of the current line box.
If there is not enough horizontal room for the float, it is shifted
downward until either it fits or there are no more floats present.
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. However, the current and subsequent line boxes created next to
the float are shortened as necessary to make room for the margin box
of the float.
And here are a whole bunch of examples...
W3C Spec: 9 Visual formatting model, 9.8 Comparison of normal flow, floats, and absolute positioning
What makes you believe the div's are floated next to each other? In reality they are not. It's only that their content shows up next to each other but that's not because DIV #second is to the left of the floated DIV. It doesn't matter if you set the width or not.
What in fact is happening is that the floated DIV #first is floated to the left. Because it's floated, it's taken out of the normal flow. This means that DIV #second is actually on the same place as where DIV #first is appearing. The content of DIV #second though is inline content and inline content always flows around floated elements. Even floated elements that are outside of the container. So DIV #second is underneath DIV #first but the content of DIV #second is floating around DIV #first.
To illustrate that, I've create this CSS:
#first { float: left; background-color: rgba(255,0,0,0.3); }
#second { background-color: rgba(0,255,0,1); }
Play with the alpha value of the RGBA() value (i.e. the last parameter, it can range from 0 to 1) of the background-color of DIV #first and you will see that DIV #second is in fact below DIV #first all the time
Unless you clear your floats, the next block level element will float next to the last float by default.
I'm not sure what you're trying to achieve here, but if you want #first to float, and #second to NOT float, the rule you'd want to add to #first is : clear:both
But, that's pretty silly, you might as well just remove the float properties completely if you want to stack them.
Block elements take 100% of the width of their parent element, so even if your first div is floated, the second div will take the width of his parent, thus falling on a second line. This is why if you specify a smaller width, it stands next to the first floated div.
The reason why it also works if you float the two divs is that floated element behave a bit more like inline-block elements, wich means they will only take the space needed for the content inside of them.
Bottom line is, if you want these two divs to stand next to each other, you should probably just float the two of them.

Resources