Absolute positioned child is displaced by static parent [duplicate] - css

This question already has answers here:
Why aren't my absolutely/fixed-positioned elements located where I expect?
(3 answers)
Is there any difference between 'margin-top, -left, -bottom, -right' and 'top, left, bottom, right' properties when element is positioned absolutely?
(2 answers)
CSS margin terror; Margin adds space outside parent element [duplicate]
(7 answers)
Closed 3 years ago.
I have a div child with absolute position (blue-box) and a parent with default (static) position hanging on body (container). When I define a margin-top for the parent, div child is displaced too.
Blue-box is positioned relative to its closest positioned ancestor, so in this case is positioned relative to body, because container is positioned statically. (See https://developer.mozilla.org/en-US/docs/Web/CSS/position#absolute)
I supposed that was a problem of margin collapsing, but I read that the margins of floating and absolutely positioned elements never collapse.
(See https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing)
body {
background-color: #1f1f1f;
height: 2000px;
}
.box {
width: 100px;
height: 100px;
margin-bottom: 10px;
}
.blue-box {
background: lightskyblue;
position: absolute;
margin-top: 110px;
}
.green-box {
background: lightgreen;
}
.container {
background: rgba(0, 0, 0, 0.4);
height: 200px;
width: 200px;
margin-top: 150px;
}
<div class="container">
<div class="box blue-box"></div>
</div>
<div class="box green-box"></div>
I expected blue-box to be on top of the viewport and not inside the container box

As the second sentence in the Mozilla docs say,
"The top, right, bottom, and left properties determine the final location of positioned elements.", you have to specify one of these values, to actually position it.
.blue-box{position: absolute;top:10px}
Check this codepen : https://codepen.io/jsuryahyd/pen/ExYGbxr
By the way, this got me thinking too. Thank you.

Related

Why is padding-bottom for a div with width=100px and padding-bottom=100% not 100px [duplicate]

This question already has answers here:
How is padding-top as a percentage related to the parent's width?
(5 answers)
Closed 3 years ago.
According to https://developer.mozilla.org/en-US/docs/Web/CSS/padding-bottom a 100% padding-bottom value should be the same as setting it to 100px when the width is 100px.
However, the value used as width is not the width set to the div (100px) but the width of the div's container, which is the body here. Why is this the case?
When display of the div is switched to table-cell then the padding becomes 100px as then the width set to the div is taken serious. Otherwise the div is considered to range across the whole body as if it had no set width.
<div>hoho</div>
div {
width: 100px;
padding-bottom: 100%;
background: lightcoral;
}
https://jsfiddle.net/citykid/zx5uptwy/4/
From MDN:
The size of the padding as a percentage, relative to the width of the containing block
Emphasis mine.
Which means this is what you're looking for:
.wrapper {
width: 100px;
}
.content {
padding-bottom: 100%;
background: lightcoral;
}
<div class="wrapper">
<div class="content">hoho</div>
</div>

position fixed div in absolute positioned div works - but why?

I need to give an element position fixed, but I can't position it relatively to the viewport, I need it to be positioned relatively to a container.
I managed to do so, but I wonder how and why it works, because actually I think position fixed is ALWAYS positioned relatively to the viewport and NOT to parent elements.
Here my (working) code:
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
body {
height: 2000px;
}
.container {
position: relative;
}
.sidebar {
width: 200px;
background-color: red;
height: 200px;
position: absolute;
left: 100px;
top: 100px;
}
.fixed {
width: 100px;
height: 100px;
background-color: green;
position: fixed;
/* top: 0;
left: 0; */
margin-left: 10px;
margin-top: 10px;
}
</style>
</head>
<body>
<div class="container">
<div class="sidebar">
<div class="fixed"></div>
</div>
</div>
</body>
</html>
Fiddle: https://jsfiddle.net/tnwLycao/
Element "fixed" can easily be positioned with margins (e.g. margin-left/margin-top). However, when I deactivate the margins and try to position "fixed" with top/left it positions itself relatively to the viewport again, not relatively to the parent container/element.
Can someone give me a hint how and why this works?
An element with position: fixed is indeed positioned relative to the viewport (or browser). However, because it is an absolutely positioned element, it is "positioned relative to the initial containing block established by the viewport".
This is laid out in the position documentation:
An absolutely positioned element is an element whose computed position value is absolute or fixed. The top, right, bottom, and left properties specify offsets from the edges of the element's containing block. (The containing block is the ancestor relative to which the element is positioned.) If the element has margins, they are added to the offset.
That is to say, when you specify margin-top and margin-left, these values are relative to the parent. And because the element is positioned relative to the parent, the default top and left are inherited from the parent. In your example, the .fixed element has a top value of 100px because it inherits the top value of 100px from .sidebar (the parent). When you set top: 0 on .fixed, you are overriding this value (going from top: 108px to top: 0):
Because of this, the element appears to be taken 'out of flow'. However, it is still always positioned relative to the viewport; it just had an initial offset (which it inherited from its parent).

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.

Centering Modal, or div when positioned

See this Fiddle, how can I center the blue div without fixed width and height in the parent and child?
This is to post in SO
<div class="parent">
<div class="child">
</div>
</div>
Update
These are positioned elements, I want child at the center of the screen.
Update 2
See it centered here, but I can't use fixed widths nor heights in parent neither children. I need positioned elements because I need them to be over other elements.
To center a div, you simply have to add this attribute:
margin-left: auto;
margin-right: auto;
or a more condensed version (assuming 0px for the top and bottom margin):
margin: 0px auto;
This assumes that you have some sort of width value on that element you want to center, whether fixed or a percentage. You shouldn't need anything in the parent to dictate the child's margins.
margin-top: -50%; /* why this takes the width of the parent ???? */
It's because your parent div has position: fixed and your child div has position: absolute and since absolute position element is positioned relative to the first parent element that has a position other than static.
So your child div will take a margin top and margin left with a value equal to -50% of your parent width which is -50% * 150 = 75px
Try this it's display in center of width.
<div class="parent">
<div class="child">
</div>
</div>
<style type="text/css">
.parent{
}
.child{
background: none repeat scroll 0 0 lightblue;
height: 50px;
margin: 0 auto;
width: 150px;
}
</style>
I think this could solve your problem, but this needs JQuery[.width()].
.parent{
position: fixed;
/* I can't use static width nor height, TO DELETE(try changing this)*/
width: 500px;
height: 400px;
background: red;
}
.child{
display: inline-block;
position: absolute;
/*Simulate width and height, these are actually calculated by content*/
width: 100px;
height:50px;
background: lightblue;
}
JQuery onLoad:[JSFiddle]
$(function changePostion() {
var s = $(".parent").width();
var e = $(".child").width();
var d= (s-e)/2;
$(".child").css({"left":d});
var sh = $(".parent").height();
var eh = $(".child").height();
var dh= (sh-eh)/2;
$(".child").css({"top":dh});
});
This article is a best tutorial for positioning html attribute in center. There might be a better way to do without using JQuery.
Dynamic modals can be the biggest pains in the world. You need JS to change the heights and widths. Can you use a plugin? If so here are some good options. Twitter bootstrap has a modal that's very easy to get set up but it's challenging to load divs via ajax and iframes. You have to choose one or the other. simplemodal (http://www.ericmmartin.com/projects/simplemodal/) is good but you still need to do a lot of the work yourself. It works with iframes and ajax content.

Can I position an inner element below its parent? [duplicate]

This question already has answers here:
Why can't an element with a z-index value cover its child?
(5 answers)
Closed 1 year ago.
It seems that with markup like http://jsfiddle.net/nwekR/
<div id="container">
Outer Div
<div id="inner">Inner Div</div>
</div>
and CSS like
#container {
position: relative;
z-index: 6;
}
#inner {
position: absolute;
z-index: 4;
}
#inner is still above #container can I have #inner below?
No.
The CSS 2.1 spec states this standard of painting elements:
the background and borders of the
element forming the stacking
context.
the child stacking contexts with
negative stack levels (most negative
first).
the in-flow, non-inline-level,
non-positioned descendants.
the floating descendants.
the in-flow, inline-level,
non-positioned descendants,
including inline tables and inline
blocks.
the child stacking contexts with
stack level 0, and the positioned
descendants with 'z-index: auto'.
the child stacking contexts with
positive stack levels (least
positive first).
Given these rules and your HTML, #container is creating the stacking context for the element #inner, which means #container has to be rendered first.
Other people have already posted alternative HTML/CSS to get the effect you desired, but if you want to know more about why what you want isn't possible, here is the documentation:
http://www.w3.org/TR/CSS21/visuren.html#layers
You just need to put it outside of inner element when it comes to HTML.
Here's your solution: http://jsfiddle.net/nwekR/23/
<div id="container">
Outer Div
</div>
<div id="inner">Inner Div</div>
#container {
background: yellow;
position: relative;
height: 100px;
-moz-box-shadow: 0 2px 6px rgba(0,0,0,0.6);
-webkit-box-shadow: 0 2px 6px rgba(0,0,0,0.6);
box-shadow: 0 2px 6px rgba(0,0,0,0.6);
z-index: 6;
}
#inner {
background: orange;
position: absolute;
z-index: 4;
width: 100px;
height: 50px;
top: 180px;
right: 0;
padding-top: 20px;
}
The cleanest solution is to add an extra wrapper element, and to move #inner outside #container.
The extra wrapper element is given position: relative, so everything else should be the same as it was before, with the exception that #inner is underneath #container.
Live Demo
It is not possible(in it's current state of having inner a child of container) because when the browser renders the DOM, it goes from top down on the DOM tree, and there is no way to draw under something that has already been drawn(i.e. drawing the parent before child).
You can read more about the z-index here.
There are ways of accomplishing(by changing the html around) this however, you can see thirtydot's solution.

Resources