Why does absolute positioning of child makes parent's height collapse? - html

please don't mark this question as duplicate because I don't think anyone asked this before. I know that position:absolute takes the element out of the flow, but that doesn't explain why its parent's height collapses to 0. If I have this markup:
<div class="container">
<div class="inside">
some content
</div>
</div>
Then I add these styles:
.container {
background-color: red;
position: relative;
}
.inside {
background-color: green;
position: absolute;
}
Applying absolute positioning to the child will make the container's height collapse to 0. The only way to make it visible is to apply height, but not in percentages.
Does anyone know why this happens?
And is there a way to make it not happen?
Thanks in advance

Related

What's the standard of width % for child positioned: absolute [duplicate]

This question already has answers here:
Pseudo element not full container width when border used
(3 answers)
Closed 1 year ago.
As I know, child's width percentage's standard is parent's content box(only the content, without padding or margin.). So if there's a padding in parent and child's width is 100%, child's width is smaller than parents. But If I position child as a absolute and parent as a relative, child's width is just equal to the parent's no matter padding and margin in parents. Like this:
<div class="first">HI
<div class="second">
HELLO
</div>
</div>
css code
.first{
background-color: yellow;
width:100px;
height:100px;
padding:10%;
position:relative;
}
.second{
background-color: blue;
position:absolute;
width: 100%;
height:100%;
opacity:40%;
}
Eventhough parent's position and relative so Child is totally dependent on '.first'. What's the standard of child's width in this case?
This snippet shows the result of setting the second div to have position relative and then position absolute. You can see that the absolutely positioned element takes on the width of its parent including the padding.
.first {
background-color: yellow;
width: 100px;
height: 100px;
padding: 10%;
position: relative;
}
.second {
background-color: blue;
width: 100%;
height: 100%;
opacity: 40%;
}
.relative {
position: relative;
}
.absolute {
position: absolute;
}
<h2>The blue square has relative position</h2>
<div class="first">HI
<div class="second relative">
HELLO
</div>
</div>
<h2>The blue square has absolute position</h2>
<div class="first">HI
<div class="second absolute">
HELLO
</div>
</div>
The reason seems to be that:
when a box has position: absolute its containing box is the parent's padding box.
See the accepted answer to: Absolute positioning ignoring padding of parent though I am struggling to find the exact description of that in the actual standard documents and it would be good if someone could point out a primary reference.
UPDATE: thanks to Temani Afif who has pointed out this SO answer which has info. from an actual specification:
The standard of the % for position:absolute is of the nearest positioned ancestor block and if no ancestor is positioned, it is relative to body element. In your case since the first is positioned relative the second will be relative to first and if u remove the position attribute of first, second will be positioned relative to body.
You can also check this - https://www.w3schools.com/css/css_positioning.asp

Why does an image of position:absolute have no height? When I can see in the browser it has height

I am trying to understand why a div with display:block will not sit under another div with display:block
My mark-up is this:
.container{
display: block;
position: relative;
}
.container img{
width: 100%;
position: absolute;
top:0;
left:0;
}
.container .text-left{
position: absolute;
top:35rem;
left:35rem
}
.container .text-right{
position: absolute;
top:35rem;
right:35rem
}
<div class="container" >
<img src="/image1.jpg" alt="">
<div class="text_left">
<h2>HEADING 1</h2>
</div>
</div>
<div class="container" >
<img src="/image2.jpg" alt="">
<div class="text_right">
<h2>HEADING 2</h2>
</div>
</div>
I am trying all sorts of stuff to make this work - overflows etc - but can't seem to get the second display block div to sit under the first.
EDIT: It seems that if you put position:absolute element/s inside a position:relative element - that may have height due to that element being an image - the absolute element/s removes this height. So you need to add it back in as height: X.
But why??
Is this due legacy mark up - using absolutes in ways not designed for?
Why would the browser not take into consideration the image height as default. And we could override this if needed.
Can anyone please enlighten me?
thanks
The reason you have lost height is because position:absolute; removes element from the flow, therefore your parent container won't be able to use it to work out its height. It's not legacy markup, it's part of the scope.
A quick excerpt from CSS-Tricks
The trade-off (and most important thing to remember) about absolute positioning is that these elements are removed from the flow of elements on the page. An element with this type of positioning is not affected by other elements and it doesn't affect other elements. This is a serious thing to consider every time you use absolute positioning. Its overuse or improper use can limit the flexibility of your site.
If for whatever reason you are required to have that specific element as position:absolute; your next best bet would be to adjust the parent container using JavaScript/jQuery, however that might be a bulky fix.
My suggestion would be to try and achieve your preferred layout without using the absolute positioning, and then if you get stuck, post another question here explaining your desired layout and current code trying to achieve it.
EDIT
That being said, if the mentioned JavaScript/jQuery solution does not sound to bulky to you, you could try the following:
$('.container').each(function(){
$(this).css({
'padding-top': $(this).find('img').height()+'px'
});
});
This will add padding-top to the container based on the image size. Alternative, you could add an empty div below the image and adjust its height based on the image size.
To make it work just make the img and test_* position to relative instead of absolute. Why ? Position absolute removes element from the flow, that means that because all your container's childrens are absolute, it is like your container has no content, that's why it collapse.
.container{
display: block;
position: relative;
}
.container img{
width: 100%;
position: relative;
top:0;
left:0;
}
.container .text_left{
position: absolute;
top:90%;
left:5%;
color: #fff;
}
.container .text_right{
position: absolute;
top:90%;
right:5%;
color: #fff;
}
<div class="container" >
<img src="https://placeimg.com/640/480/any" alt="">
<div class="text_left">
<h2>HEADING 1</h2>
</div>
</div>
<div class="container" >
<img src="https://placeimg.com/640/480/any" alt="">
<div class="text_right">
<h2>HEADING 2</h2>
</div>
</div>

Expand absolute parent div to height of relative child

I need to animate my ng-view with a slide effect. Therefore I got 3 divs
<div style="overflow:hidden">
<div ng-view style="position:absolute">
<div style="position:relative"> LONG CONTENT </div>
</div>
</div>
I´m testing these effect. The outer div needs to be overflow:hidden to let my slide effekt work.The inner div needs to be absolute. If the inner div contains some text, the other 2 divs should expand the height according to the very inner div. Same like when all divs would be relative. How to achieve this?
Like in my example link but with variable height.
EDIT: This is a complete other question then the "possible" duplicate.
The problem is the size of your contents, you`re making your inner div absolute, so the parents it won’t
have any height. First thing you have to do is define size to your elements and than you can use absolute elements to make your layout.
see the example below, i define a div named .page with min-height:200px, that will be enough to appear your element (.slide), because if you don’t do this, your element(.page) height will be 0, and it will be cut by overflow:hidden.
<style>
.page {
background-color: #DDD;
overflow: hidden;
position: relative;
min-height: 200px;
}
.slider{
position: absolute;
}
.slide{
position: relative;
}
</style>
<div class="page">
<div class="slider" ng-view>
<div class="slide"> LONG CONTENT </div>
</div>
</div>

Issue with putting div over another div

Before giving negative vote or placing the question as duplicate, please read the issue first.
I'm having some issue with putting one div under another. I know that make people have asked this question here and I've read all of them and also tried everything out, but none of them worked for me.
Everyone days to give position: relative to to div and then give one higher z-index and another lower. None of them worked for me. So, I'm here for help.
In my project (http://loadtest.isaumya.com/) I have 2 divs i.e.
<body>
<div class="conteiner">blah blah blah</div>
<div id="particle-js"></div>
</body>
I want to put the <div id="particle-js"></div> behind of container, but nothing is working out. So please help.
You have ordered them badly:
<div class="container">...</div>
<div id="particles-js">...</div>
invert positions:
<div id="particles-js">...</div>
<div class="container">...</div>
makes sense since you want your full-screen canvas particles to be naturally z-index lower than the latter #container. Precedence rule.
also add this styles to your particle-js element:
#particles-js{
position:absolute;
top:0;
width:100%;
height:100%;
}
If the above still does not helps (it should) add:
.container {
position: relative;
z-index: 1;
}
Make your canvas element display:block;
Result image:
its just a very simple concept you need to remember about position in css
A relative positioned element is positioned relative to its normal
position
An absolute position element is positioned relative to the first
parent element that has a position other than static.
JSFiddle
this is how you may solve this problem:
<body>
<div class="container">blah blah blah</div>
<div id="particle-js"></div>
</body>
and the css
div {
width: 100px;
height: 100px;
}
.container {
position: absolute;
background-color: blue;
z-index: 1;
}
#particle-js {
position: absolute;
background-color: red;
}
make the z-index higher to wichever element you want a be displayed at the top

Div doesn't have height

Why does wrapper div not have a height? If I set the height (height:200px) the green background appears but how to set with auto height?
Here is my code (JSFiddle):
HTML:
<div class="wrapper">
<div class="effect"></div>
<div class="content">
...content
</div>
</div>
CSS:
.content {
position: absolute;
background-color:red;
}
.wrapper, .effect {
background: green;
}
.wrapper {
position: relative;
width: 630px;
}
.effect {
width:100%;
position: absolute;
}
It is not working (i.e. parent element not having any height) because all the immediate descendant of the .wrapper element is absolutely positioned — this will have the effect of taking them out of the flow of the document, therefore causing the parent's dimension to collapse to nothing.
You will also notice that the effect is the same when you float all
descendants of the parent wrapper, because float also has the
effect of taking normal elements out of the document flow.
There are only two ways to prevent this from happening, both of which involving declaring a certain height for the parent .wrapper element:
Either you explicitly state a height for the parent (see example fiddle)
Or use a relative height (say, in percentages or viewport units) that is not dependent on its own content.
You should reconsider your design strategy, and what you're trying to achieve. There is probably other ways to achieve what you intend to do, will you mind showing us?