Why do relatively positioned elements ignore floated elements - css

When a static block element follows a floated element it will fill the remaining space available to it.
So, for example .right will take a width of 80%:
.left {
background-color: red;
float: left;
width: 20%;
}
.right {
background-color: blue;
}
http://jsfiddle.net/yryZR/
However, when a block element with position: relative follows a floated element, the floated element seems to be ignored and the relative element takes 100% width:
.left {
background-color: red;
float: left;
width: 20%;
}
.right {
background-color: blue;
position: relative;
}
http://jsfiddle.net/yryZR/1/
According to the W3C "Once a box has been laid out according to the normal flow or floated, it may be shifted relative to this position" (source)
So if I am not changing the left or right positions of the element, why does it set itself to the very left of its parent element rather than stay in the normal flow?

position:relative refers to the position the element would've been in had there been no CSS positioning overrides - e.g. its natural unaltered position.
floated elements are essentially removed from document positioning calculations, so your left element is invisible for the right element's positioning, so it takes the size of the next higher element - the container that these two left/right boxes are in.

Related

Positiong an element with absolute positiong without expanding the parent

I have a relative positioned div and I want to position its child using absolute positioning - easy. One question though: I was under the impression absolute positioned children dont take up any space, but if I position it right:5000px for example a huge gap appears to the right to accommodate that element.
How do I position an element as absolute say 5000px to the right from its parent without the parent expanding to take up the room to accomodate both.
Actually if you do it..the parent shouldn't get expanded.
Here's an example:
https://jsfiddle.net/0oofcd0x/1/
container{
position: relative;
background: black;
height:200px;
width: 500px;
}
.internal{
position: absolute;
background: green;
width:100px;
height:100px;
left: 800px;
}

Relative positioning without z-index causes overlapping

I created two sibling divs and applied negative margin on the last one, but when I added position: relative to the first one, it overlapped its next sibling:
.box {
width: 100px;
height: 100px;
}
.box-1 {
position: relative;
background: orange;
}
.box-2 {
margin-top: -50px;
background: yellowgreen;
}
<div class="box box-1">box-1</div>
<div class="box box-2">box-2</div>
However, MDN says that
positioned (absolutely or relatively) with a z-index value other than "auto" will create a new stacking context.
So I guess it isn't the stacking context that causes overlapping, any idea about how this happens?
Standard blocks in the normal flow, without any positioning property, are always rendered before positioned elements, and appear below them, even if they come later in the HTML hierarchy.
Example being
.absolute {
position: absolute;
background:purple;
left: 80px;
}
.relative {
position: relative;
left:50px;
background:yellow;
top:-50px;
}
div {
width:100px;
height:100px;
border: 1px dashed #999966;
background:blue;
}
<div class="absolute">absolute</div>
<div>normal</div>
<div class="relative">relative</div>
<div>normal</div>
Something cool about relative though, is that it's still considered to be in it's original location, even if it's been moved if you're using left, right, top, bottom. If you use margins to position the element the boundaries of the container are also moved with it. This can be seen using the same example above but changing the relative position to use margining. Reference to relative positioning
Non-positioned elements are always rendered before explicitly positioned elements. This means that by applying position: relative to 'box-1', it is rendered after 'box-2' and so appears on top of it.
The overlapping is caused by margin-top: -50px; in your CSS
Here is a decent explanation:
https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/Stacking_without_z-index
Standard blocks in the normal flow, without any positioning property, are always rendered before positioned elements, and appear below them, even if they come later in the HTML hierarchy.

Lay out children with equal space between each other to fill container

I have a div with a variable width, and I have a variable amount of children inside this div. I want the children to fill up the space inside the div. I first tried to change the div to display:table and the children to display:table-cell but I ended up all the children filling up all the space and not obeying their width and max-width properties. Then I've tried the table approach: I've changed the div to a table (yes, I know, it's not recommended, that's why I'm probably here asking) and wrapped the children into a tr and each in tds, but I ended up all the children cells filling up the whole space, but aligned to left (I've set the children divs display:inline-block):
If I change the alignment to center, I get this:
They are centered, but I still get spaces on the left and right of the parent (with the yellow background that I've set for distinguishing). What I actually want is this:
I've achieved this by setting the first td to align text to left, the second to center, the third to right. But I may have more of these thumbnails, so I need a general solution.
How can I lay out a variable number of children inside a container to fill the width, with the first element starting at the exact left border of the container (unlike the second image) and the last element ending at the exact right border of the container (like shown in the third image)?
Something like this?
HTML:
<div>
<span id="s1"></span>
<span id="s2"></span>
<span id="s3"></span>
</div>
CSS:
div{
background: #ff6;
text-align: justify; /* Important */
font-size: 0; /* Used to remove spaces */
}
div:after{ /* Used to create a new last line */
content: '.';
display: inline-block;
width: 100%;
height: 0;
overflow: hidden;
}
span{
display: inline-block;
height: 150px;
}
/* Use your widths, min-widths and max-widths here: */
#s1{
background: red;
width: 15%;
min-width: 50px;
max-width: 150px;
}
#s2{
background: green;
width: 40%;
min-width: 50px;
max-width: 250px;
}
#s3{
background: blue;
width: 40%;
min-width: 50px;
max-width: 200px;
}
Demo
You can obtain equally spaced boxes using text-align: justify on the wrapper. The problem is that it doesn't work for the last line (which in this case is the first too), so you can either use text-align-last, or an :after pseudo element with width: 100% in order to create a new last line.

Align & stack png images inside a bootstrap div with position:absolute

I am trying to align (and stack) some images inside a bootstrap grid.
For some reason, the images aligns to the window and not the grid.
I use position:absolute which work like this (http://www.w3schools.com/):
"An absolute position element is positioned relative to the first parent element that has a position other than static. If no such element is found, the containing block is <html>"
Here is a jsfiddle :
http://jsfiddle.net/sbE6t/
.rings img {
position:absolute;
top: 0px;
left: 0px;
}
As you quoted, they will be absolutely positioned to the next non-static element. If no such element is found, the containing block is <html>.
Set position relative to the img's parent:
.rings {
// other styles
position: relative;
}
And it works
your wrapping element must be set to position:relative
.rings {
overfow:hidden;
height: 400px;
background: #999;
position:relative;
}

Why is my div not breaking out of parent div?

I'm trying to break out of a parent div so I can have a colour div cover the width of the browser.
However, for some reason it pushes the block off to the left.
This is my site.
This is my code:
HTML:
<div class="aboutTop"></div>
CSS:
.aboutTop{
width: 100%;
height: 600px;
background-color: black;
margin-left: -100%;
margin-right: -100%;
}
Where am I going wrong?
To make your div "break out" of its parent, you'll have to use position: relative;
HTML:
<div class="aboutTop">
<div>break out!</div>
</div>​
CSS:
div
{
width: 100px;
height: 100px;
border: 1px solid #000;
}
.aboutTop div
{
position: relative;
top: 50px;
left: 50px;
}
This is because child elements are restricted to the boundaries of their parents. USing positioning takes the element out of the document flow. Using relative positioning takes it out of the flow but uses its original position within the parent as the point of reference. Absolute uses the top left corner of the browser window as its reference. :)
http://jsfiddle.net/qkU7F/
The width will always reference the parent div, no matter what. So you can use jQuery to set the width of the element based on the window width.
var winWidth = window.innerWidth;
$('.aboutTop div').css("width", winWidth);
http://jsfiddle.net/qkU7F/3/
In this:
margin-left: -100%;
margin-right: -100%;
The percentages are relative to the parent element.
So if the parent element is 200px wide 100% will be 200px.
If you want something to span the width of the browser you have a couple of options:
Use absolute position and left:0; right:0;
make the element a direct child of the body element and set it's width to 100%
.aboutTop{
position:fixed;
width: 100%;
height: 600px;
background-color: black;
margin-left: -100%;
margin-right: -100%;
}
When you give a width:100% without positioning, it will take 100% with respect to parent division. You need to make it fixed, or you need to change the width of the parent division.
The code you write, must from start be aimed at what you want to achieve. For something like this, you should not have a parent division with less width.
If yo use relative positioning, or absolute with negative margin the width will still be 100% of parent division. You will have to increse width to something like 110% to achieve.
I think it's better to remove padding of your div #site. let it to have full width of browser.
then apply padding to children divs as you want.
You're setting width: 100% but also margin-left: -100%. This means that the element will span from -100% to 0.
Since you're also setting margin-right: -100% it looks like you want it to span from -100% to +200%, which means you need to set width: 300% instead.

Resources