Why does positioning effect div width? - html

I was fiddling with my web-app to try and get a div to wrap around some p elements. The structure looks like this, i.e. pseudo-code ...
<div id='outer'>
<p></p>
<p></p>
<p></p>
</div>
What I found is that if I set the outer div to
position:absolute;
instead of
position:relative
that the div would correctly wrap around only the p elements.
Otherwise it would extend all the way to the very right of the page, and I had previously had to set the width manually.
What is governing this behavior?
Also, the p tags use
display:inline
and the containing div just uses the default display.
This CSS below works well in my app.
// outer div
#mi_control {
position: absolute;
left: 580px;
top: 660px;
width: auto;
padding-top: 5px;
padding-bottom: 5px;
}
// p elements
.menu_bottom {
margin-left: 18px;
display: inline;
}

This is a common issue..
I quote:
Question: relative div takes 100% width automatically but absolute div only takes content width. why?
Answer: Setting position:absolute removes the element in question from the normal flow of the docment structure. So unless you explicitly set a width it won't know how wide to be. you can explicitly set width:100% if that is the effect you're after.

By default, a div element is set to display: block;. Block elements will be 100% of the width of the parent element.
When you set an element to position: absolute; it takes it out of the document flow and the element is no longer sized according to the parent element. It can mess with your layout though.
My recommendation is to set the div element to display: inline-block; - this will make it sized as per its contents, but will not remove it from the flow of the document.
#outer
{
display: inline-block;
}

I don't know exactly what rules governing this behavior but what you observed is the right behavior and is consistent across all browsers. A DIV takes minimum width when its position is set to absolute or fixed; otherwise it takes full available width.

The default value for width for a div element is auto.
This means that it will take up the full with of the available space, or more if the contents forces it to. If you use position: absolute however, you take the element out of the document flow. As there is nothing that it can relate to as the full width any more, it will use the width that the contents forces it to use.

The behaviour is governed by the spec. Absolute positioned elements have dedicated rules about how widths are calculated: http://www.w3.org/TR/CSS2/visudet.html#abs-non-replaced-width and http://www.w3.org/TR/CSS2/visudet.html#abs-replaced-width

Once it is set to absolute, it is taken out of the normal flow of content. Absolutely positioned elements always appear in the top left corner, unless otherwise specified. The element will also shrink to be only as big as it has to, because that's how position:absolute works
divs naturally have a width of 100%, so that is why you have to set the width manually. Relatively positioned elements behave almost identically to statically positioned elements. The only difference is how they can be moved

Not sure what you are seeing but even if your div is positioned absolutely, it will STILL wrap your P tags
http://jsfiddle.net/8MSDH/
you are seeing it at the bottom right because you set your top and left
left: 580px;
top: 660px;

Related

DIV changed its behaviour when "position:absolute" was added to it. Why?

I'm new to CSS and I have a question.
First, my HTML and CSS code:
<!-- HTML CODE -->
<body>
<div id="container">Container
</div>
<div id="inner">Inner</div>
</body>
<!-- CSS CODE -->
#container {
background-color:#b6ff00;
width:500px;
height:500px;
position:relative;
}
#inner {
background-color:#ffd800;
}
With current code, the browser shows the following page:
This is expected.
But if I add this css property to #inner element position:absolute; there will be a following output:
As you can see, the #inner div, takes only that much space it needs. Why this changed with only position:absolute; property added to #inner div?
That's because when you use position: absolute; the element will take up width upto the elements defined/content it contains., cuz it just gets out of the document flow so it is block level in nature but won't take up entire horizontal space on the document, as it's just out of the flow of the document..
If you want it to be full width you need to define width: 100%; explicitly so that it will take 100% of the relative parent's width as well as the height if you declare height: 100%;
Also, make sure you always use position: absolute; with a wrapper element set to position: relative; or your element will fly out in the wild which will eventually end up taking the viewport as the last relative wrapper if you set the position of the element using top, right, bottom or left.
I've explained here in detail, that how CSS Positioning Works
Worth to note that, you make any element a position: absolute; element, it will behave as a block level element, but you need to define height and width so for example, if you turn an inline span element a position: absolute; you can define height and width without making it display: block; (Unless and until you are using display: none; initially)
position: absolute; does not behave the same as block elements.
You will need to set a width and a height for a div that is absolutely positioned.
This is fundamentally how position absolute works. Once taken out of the flow of the document it becomes an inline-block element that is absolutely positioned within the nearest element that is positioned relatively (or the top most element)
If you need it to then be a certain dimensions you can try to set widths and heights, or you can do things like
#inner {
position: absolute;
left: 0;
right: 0;
}
...which would ensure it always stuck to the left and right sides of the screen.
It's generally good practice to put things that are positioned absolutely inside of an element with "position:relative" on it, as your code stands it suggests you want your #inner element to be placed anywhere on the page, whereas if you wanted it to be of a size and position relative to #container your code should look like this:
<body>
<div id="container">
Container
<div id="inner">Inner</div>
</div>
</body>
with CSS such as:
#container {
position: relative;
}
#inner {
background-color:#ffd800; width:500px;
height:500px;
position:relative;
}
You can see your output here:-
http://jsfiddle.net/KggJd/
Let me explain a little:
Postition: relative
This will align itself in accordance with the elements found before (i.e) Prior Siblings.
You can change the position by using margin-top, margin-left, ....
Position: absolute
This will always consider from the browser's start point and won't be in accordance with anything.
Drawbacks:
You cannot consider this as the parent or anything when absolutely positioned.
You can change its position by using top, bottom, right, left.

Why do absolute elements stack up on each other instead of stacking one after the other?

How can get both #row1 and #row2 in the following code to be visible, one after the other vertically, as if there wasn't any absolute/relative positioning involved (though without removing the positioning properties)? I.e. having the two .row <div> to appear as "normal" block elements.
body { position:relative; min-height: 2em; width: 100%; }
.container {position:absolute;}
.row {position:relative;}
.col1, .col2 {position: absolute;}
<body>
<div class="container">
<div id="row1" class="row">
<div class="col1">Hello</div>
<div class="col2">World</div>
</div>
<div id="row2" class="row">
<div class="col1">Salut</div>
<div class="col2">le monde</div>
</div>
</div>
</body>
(Sample also available as a fiddle.)
I need the elements to have the positioning provided in the CSS rules, for reasons excluded here.
The content is programmatically dynamic; I don't know the elements' heights beforehand, so a solution can't be based on specifying an absolute length (e.g. 'px') anywhere.
Well you have some weird wishes here so let me explain you what those positions really mean in CSS and how they work, using position: relative; is just like using static position, the difference is making an element position: relative;, you will be able to use top, right, bottom and left properties, though the element will move, but physically it will be in the document flow..
Coming to position: absolute;, when you make any element position: absolute;, it gets out of the document flow, hence, it has nothing to do with any other element, so in your example
you have .col1, .col2 {position: absolute;} which are positioned absolute and since both are out of the document flow, they will overlap... Because they are already nested under position: absolute; parent i.e .container and since no width is assigned, it will take the minimal width and hence, your elements overlap, if you cannot change your CSS(which according to me doesn't make any sense why you can't change) still if you want, than you can do is this..
Demo (Without removing any of your position property) And this is really dirty
For the s characters, it will be at the top as your container element is out of the flow, and hence, no height will be considered in the document flow, unless and until you wrap that s in some element, and bring it down with, margin padding or CSS Positioning.
CSS Positions Explained
As I commented, here are few examples of how CSS Positioning actually works, to start with, there are 4 values for position property i.e static which is the default one, relative, absolute and fixed, so starting with static, nothing to learn much here, elements just stackup one below the other unless they are floated or made display: inline-block. With static positioning, top, right, bottom and left won't work.
Demo
Coming to position: relative; I've already explained you in general, it's nothing but same as static, it stacks up on other element, it is in the document flow, but you can tweak the elements position using top, right, bottom and left, physically, the element stays in the flow, only position of the element is changed.
Demo 2
Now comes absolute which generally many fails to understand, when making an element absolute it gets out of the document flow, and hence it stays independent, it has nothing to do with other elements positioning unless it's overlapped by other position: absolute element which can be fixed using z-index to change the stack level. The main thing to remember here is to have a position: relative; container so that your absolute positioned element is relative to that relative positioned element, else your element will fly out in the wild.
It's worth noting that position: absolute; element when positioned absolute; inside an absolute positioned parent element, than it is relative to that element and not relative to the grand parent element which may be positioned relative
Demo 3 (Without position: relative; container)
Demo 4 (With position: relative; container)
Last is position fixed, this is same as absolute but it flows along when you scroll, it's out of the document flow, but it scrolls, also, position: fixed; element cannot be relative to any container element having any type of position, not even relative, position fixed element is always relative to the viewport, so designers use position: absolute; when they want to have a fixed position behavior but relative to parent and tweak the top property onScroll.
Demo 5
What you want, is not possible without modifying the CSS position property. However, what you can do without touching the existing CSS, is overriding it with a more specific selector
.row .col1, .row .col2 {
position: relative;
}
See JSFiddle
when position:relative is used, the page layout will occur normally before being offset by top, left values, however position:absolute will ignore the document flow. The relative ones will work with no changes but absolute must be changed
.col1, .col2 {display:inline-block;}
http://jsfiddle.net/C4bQN/
EDIT: Depending on your circumstances, maybe you can wrap your table in an absolute positioned div then use normal document flow within the table?
<div class="absolute-wrap">
<div class="row">
<div class="col"> </div>
</div>
</div>

Position fixed element with percentage width relative to container

I know that position: fixed makes an element relative to the viewport instead of it's offsetParent however I have an issue where I have a side element which takes x amount of space and then some fixed position heading elements which I want to take up a percentage of the remaining viewport width.
See fiddle: http://jsfiddle.net/U5DSZ/
Now I could put all the h1 element's into their own container but then they lose their semantic meaning as they are no longer associated with their content.
I understand JavaScript could do this but I am against using JavaScript for page structure.
Is there a way to do this in a purely HTML or CSS way? I don't mind moving the h1 element's as long as they retain their relationship with the content and the content remains statically positioned.
You can get the effect that you want as follows.
Your HTML snippet is good as is:
<div id="content">
<section>
<h1>Heading 1</h1>
<p>...</p>
</section>
<section>
<h1>Heading 2</h1>
<p>...</p>
</section>
</div>
and the CSS is good but just requires some explanation:
#content {
overflow: visible; /* default, but important to notice */
}
section {
float: left;
width: 25%;
}
h1 {
position: fixed;
width: 25%;
background: #00FF00;
text-align: center;
}
and the demo fiddle: http://jsfiddle.net/audetwebdesign/4zLMq/
How This Works
Your #content block takes up the remaining width to the right of your 200px left floated sidebar.
Within #content, you have two left-floated section elements that take up 25% of the parent container, which in this case, is the width of the view port panel.
Your child h1 elements have position: fixed, which means that their width of 25% is also computed based on the width of the viewport (not #content).
Case 1
If you want h1 and #content to have the same width, they need to have the same relative (25%) computed from the same containing block (view port in this case).
However, the value of 25% is not 25% of the remaining space after you account for the floated sidebar. However, maybe you can live with this.
Case 2
You could make the width values a bit easier to determine if you set the sidebar width to be a relative value. Using mixed units is always an issue.
tldr; Shorter and cleaner solution:
h1 {
width: inherit;
...
I stumbled upon this question, with a similar issue : my container's size can be user defined through resize:both (and moveable too!).
If I followed the accepted solution, it implied I had to apply the same props to my fixed header inside my container (top, left, width and height…).
Instead, inheriting the width from the parent container works properly. I found this way much simpler, and it makes more sense too, tested on major browsers and mobiles (demo).

How to get a static positioned element to span the screen

I have an element that I need so span across the whole screen.
It need to be static positioned because it needs to be in the flow of elements but setting the width to 100% doesn't cover the screen.
I could make it absolute positioned and then set the left and right properties to 0 and it would cover the screen, but then the element would be taken out of the flow of DOM elements and mess it up.
How can I make a static positioned element span the whole screen?
Here is a supporting jsfiddle: http://jsbin.com/uwepij
Elements that are position: static don't, by default, span more than the width of their parent element.
In the case you're seeing, the body element has a margin of 8px on it, so all of the non-absolute positioned elements are limited to that space.
If, however, you know how much extra space you want the element to span, you can set a padding and negative margin on the element like so:
padding: 0 10px;
margin: 0 -10px;
See the above as an update to your jsbin: http://jsbin.com/amuxev
If you dont need the margin in body you can use:
Body{margin:0;}

HTML: how to set children element width = browser window width?

I want to display a children element of my html page all over the browser window.. in other words I would like to enlarge it and keep it the same size the browser window also when it is resized after loading.
I was wondering if I have to move this object outside the parent elements or I can set these properties with css.
At the moment if I set width:100% and height:100%, it fits the parent (of course) and not the window.
thanks
It is typically better to use relative positioning when possible, and any large child elements should be equal to the parent. But you can always absolutely position it:
position:absolute;
width:100%;
height:100%;
left:0px;
top: 0px;
width is easy:
width: 100%;
for height, you need something like this:
100% Height Layout Using CSS
Width always aplies regarding to the parent element. You could use absolute positioning to have that particular element "out" of it's parent (regarding positioning and flow, that is), and set it to 100%. Be carefull though, it might no end up where you want it to be visually.
.someElement {
position: absolute;
width: 100%;
height: 400px;
}
The parent element cannot have "position:relative" specified for this to work.