Why Doesn't CSS Fixed Positioning Consider the Viewport Only? - css

It's my understanding that a CSS fixed position element is relative to the viewport only. However, from what I can tell, this is true except that if "left" is unspecified, it doesn't default to 0 but rather to the left edge of what would have otherwise been its container - in this case, the main div.
The HTML:
<div id="main">
<div id="fixed"></div>
<div id="content"></div>
</div >
The CSS:
#main{
width:80%;
margin-left:auto;
margin-right:auto;
}
#fixed{
position:fixed;
width:100%;
height:25px;
background:yellow;
}
#content{
width 100%;
height:300px;
background:red
}
demonstrated at http://jsfiddle.net/2dudX/99/ . If I specify left:0 the fixed element will run the width of the screen. What causes this behavior? What are the defaults if I don't specify a left, right, top or bottom?

The behavior that you are seeing is correct.
If you set position property to a value of absolute or fixed, and the offsets are not specified, then the element is positioned to the static position, that is, the position it would take with position: static.
However, the difference is that the element with position absolute/fixed is taken out of normal document flow regardless of the offset values (auto or explicitly specified).
Reference: http://www.w3.org/TR/CSS2/visudet.html#abs-non-replaced-width
Specifically, the section around (my paraphrase):
if 'left' and 'right' are 'auto' and 'width' is not 'auto', then set 'left' to the static position and then solve for 'right'
If you want to understand how height is affected by the offsets, see the following:
http://www.w3.org/TR/CSS2/visudet.html#abs-non-replaced-height

Related

CSS Position Absolute With Respect to a Parent Element Acting as Relative

In my long journey to update my CSS skills from the deprecated dust that they have turned into, I've been playing around with certain CSS properties —particularly z-index —I'm noticing something strange or maybe there's a certain condition.
Example:
http://jsfiddle.net/mEpgR/
The element div1's parent is cont, I've made div1's position property set to absolute, yet when I shift it, it's moving relative to its parent. I was under the impression that items set to absolute positioning are outsider regular flow and move only relative to browser port as their parent.
What am I missing?
If the fiddle link does not work, code:
CSS:
.cont {
position:relative;
height:200px;
top:200px;
left:100px;
background: green; width: 200px;
}
.div1 {
background:red;
position:absolute;
top:50px;
}
HTML:
<div class="cont">
<div class="div1">DIV1</div>
</div>
An absolute positioned element is positioned relative to the first parent element that has a position other than static. Since you have it inside a parent with relative it will be absolutely positioned relative to this parent.
You might be looking for fixed position, which is relative to browser window.

What is the rationale behind margin-top: auto and margin-bottom: auto amounting to 0 margin?

Since margin-right: auto and margin-left: auto center an element horizontally, I would expect their vertical counterparts to behave in the same way.
Yet I understand this does not happen, as per CSS specs:
10.6.2 Inline replaced elements, block-level replaced elements in normal flow, 'inline-block' replaced elements in normal flow and floating replaced elements
If 'margin-top', or 'margin-bottom' are 'auto', their used value is 0.
Also applies to block elements:
10.6.3 Block-level non-replaced elements in normal flow when 'overflow' computes to 'visible'
This section also applies to block-level non-replaced elements in normal flow when 'overflow' does not compute to 'visible' but has been propagated to the viewport.
If 'margin-top', or 'margin-bottom' are 'auto', their used value is 0.
Now what I would like to know, is the rationale behind this decision/behavior.
What I'm searching for is understanding and conviction. I don't think a vague explanation would do it, yet any contribution is welcome.
As noted above:
Aha... That's not so obscure! I can see it being useful. Thanks for the example you gave on jsfiddle.
So, if an element is absolutely positioned in relation to the parent element, using both top and bottom, yet it's height is defined and is less then the height of the parent element minus the top and bottom offsets, then the margin property will be used to determine it's vertical alignment in relation to the parent, and margin:auto will result in a vertically centered element.
True, it sounds complicated, yet it's clear on jsfiddle.
For example, this CSS:
.inner {
position:absolute;
top:0; bottom: 20px; left:0; right:0px;
padding:0; border:0;
margin:auto;
height:20px; width:50px;
}
and this HTML:
<div class=outer>
<div class=inner>Text</div>
</div>

How can I vertically offset child element from the center of its parent?

Here is a jsFiddle I set up.
The parent and child element's height will be uncertain(means it will change after) and the child element's position must be absolute.
How can I offset the child element vertically by five pixels from the center of the parent?
HTML:
<div class="parent">
<div class="child"></div>
</div>
CSS:
.parent{
position:relative;
margin: 10% auto;
background:lightgray;
height:50px;/*parent's height will change after*/
width:200px;
}
.parent .child{
position:absolute; /* needs to be absolutely position */
top:0;
bottom:0;
margin:auto;
width:100%;
height:20px;/*child's height will change after*/
background:darkgray;
}
offset 5px where??
Like this ----> Updated Fiddle
or
Like this ----> Updated Fiddle
If I understand you correctly, then you want to offset the child by five pixels vertically. I'm not sure whether this means the element should move up or down from the middle of the parent, but here is an example of it moving up and here is one for moving it down.
Here's the code I added to the child's CSS to move it up:
top:50%;
margin-top:-15px;
Also remove the current top and bottom declarations for the child.
We set it 50% from the top of the parent and then subtract half of its height from its top offset which centers it. We add (or subtract) 5 pixels to/from that offset to offset it further.
For variable height, use this CSS (this moves it up five pixels):
top:-5px;
bottom:0;
margin:auto;
Example.
Use border-top
See my Fiddle here
with top:0;bottom:0; and margin:auto; child element can align middle when parent and child element's height "uncertain";
border-top:10px; can make child element offset.
and maybe you'll solve your issue
Considering the element is centered, you can just add
transform(translateY: 5px)
to offset the div vertically, or
transform(translateX: 5px)
to offset it horizontally.

Setting height: 100% on my label element doesn't work

I tried to set height: 100%; in the label, but it didn't work. Why not?
.field label {
color:#3E3E3E;
font-weight:bold;
width:80px;
display:block;
float:left;
margin-top:5px;
margin-left:3px;
height:100%; /* <-- doesn't work */
}
.field {
display:block;
margin-bottom:9px;
background:none;
border:none;
}
<div class="field large">
<label>Textarea</label>
<textarea></textarea>
</div>
You have height set to 100% but 100% of what? It's always the parent of that element so what is the parent's height set to? If it's not set to anything then the browser has nothing to reference.
In this case I believe your div's height is being determined by the height of the tallest element within it: the text-area. (Reference) Perhaps you want to figure out how many pixels tall your text-area is (for instance this can be done with Firebug, or IE or Chrome's developer tools), and then set your label to that same height.
I'd also explicitly set that height for the text-area to be sure it's the same in all browsers.
The reason height: 100% isn't working as you expect is that the parent element has a height of auto. This results in your label also getting a computed height of auto.
<percentage>
Specifies a percentage height. The percentage is calculated with respect to the height of the generated box's containing block. If the height of the containing block is not specified explicitly (i.e., it depends on content height), and this element is not absolutely positioned, the value computes to 'auto'.(Reference)

Expand a relative positioned element to full container height

I have a div directly under the body. My HTML looks like this:
<body>
<div class="parent"></div>
</body>
And the css I use is this:
.parent {
border:1px solid black;
bottom:10px;
position:relative;
top:100px;
width:500px;
}
This div doesnt stretch to the entire viewport/available body height. However, if I change the position to absolute, It does stretch.
Is there a way to get a relative positioned element to stretch to its container element height. I tried height 100% as well and it works but it gives a vertical scrollbar to me as the element is positioned at 100px from TOP.
The terms top, bottom, left and right are generally used for absolute positioning. If you want a div container to be as big as it's parent's container, then you have to specify through the terms height and width, and use a percentage or integer with a measurement scale attached such as 'px'. If you are worried about a scrollbar, just use the rule overflow:hidden;

Resources