absolute position inside relative with no defined height - html

I am trying to put an absolute div inside a relatively positioned div. But I don't want to define a height for the relative div.
The relative div has a background colour and when I don't define a height the absolute div goes 'outside' the relative div. I can't control how many lines the text will be so the height of the divs change
HTML
<div class="row top-footer">
<div class="top-footer-text text-center">
<div class="test">
<h1>title</h1>
<div class="footer-btn-wrap">
<div class="footer-btn">button</div>
<div class="footer-btn">button</div>
</div>
</div>
</div>
</div><!-- /top-footer -->
CSS
.top-footer {
position: relative;
background-color: #686a6f;
width: 100%;
padding-top: 40px; margin: 0;
}
.test {
position: absolute;
top: 0px; margin: 0;
}
EDIT
I want .top-footer (position: relative) to contain .test (position: absolute) with space/padding/margin on the top and bottom of .test. the height of the div is unknown because the content may take up more than one line depending on screen size

Adding whitespace around the child div is fairly trivial. However preventing the parent div from collapsing is more tricky and is the thing you need to tackle first. The problem you are having is that with the parent relatively positioned and the child absolutely positioned, the only element on the entire page that actually "knows" where the child is is the parent... and even then it's a fairly bad parent because it won't even make enough space for the child! The rest of the DOM will behave as if the element isn't even there - other non-positioned elements will float over or above it - even text will be obscured by your child div. Assuming you want to put other content in the parent div using absolute positioning in this way only means you're going to have to use absolute positioning all around the place... which can get a bit heavy on the brain debugging layout problems later on.
The only possible solutions I can think of offhand are:
Use javaascript to sniff out the height of the child div and apply that to the parent. A fairly simple job if you use a library like jQuery but that requires extra downloaded files and makes your site unnecessarily bulky if this is the only task you're using it for. THis also wouldn't solve the problem of the child div obscuring other elements on the page.
Rework your CSS (and it might take a lot of reworking depending on how far you've got and the complexity of the styling) to use display:inline-block on the child... this will stop the parent from collapsing but might give you additional layout issues.
Rework your CSS (ditto) to float:left the child div. You would then need to use a CSS "clear hack" in order to prevent the parent divv from collapsing, although this is a tiny piece of CSS you can cut and paste from elsewhere... an easy job.
If you're determined to use absolute positioning like this my preferred solution would be to use jQuery (option 1) because most of my work tends to use a degree of it anyway... it's a tool I would have handy and the code to perform this task would be quite trivial.
EDIT - Here's a little fiddle to get you started. https://jsfiddle.net/fo8mq1vf/

This is how the output of your code looks like: https://jsfiddle.net/s3zLa54t/2/. The parent div (.top-footer) does contain the .test div. What browser are you using to view the output?
As for the padding, I guess you don't see any effect of changing padding-top. Try removing the top: 0px property in the .test div.
If this is not what you were looking for, do clarify the question here.

The answer to your question is simply remove
position:absolute from your absolute div (.test)
position:relative from your relative div (.top-footer)
height:300px from your relative div (.top-footer)
This is the tested version of https://jsfiddle.net/s3zLa54t/3/ with multiple number of divs under your main div. You can check that it is not going beyond the grey background.

.top-footer {
position: absolute;
background-color: #686a6f;
width: 100%;
padding:0px;
margin: 0;
}
.test h1{
padding-left:20px;
position: relative;
top: 5px; margin: 0;
float:left;
color:#FFF;
}
.footer-btn,.footer-btn-wrap
{
padding-left:200px;
color:#FFF;
}
.footer-btn a{
padding:5px 10px;
float:left;
color:#ffffff;
text-transform:capitalize;
text-decoration:none;
}

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.

use margin or position relative to position elements

I have always used margin to move a floating div to the correct position in a parent div (say the logo div within a header div). This has always worked but that meant you have to play with the individual height of the elements else it will affect the remainder of the layout downwards.
I found another method today and that is to make the logo div position: relative; and then use example top: 20px; to move the element around, and this does not appear to affect the layout.
I don't want to adapt to this without knowing that there may be other implications, so can anyone point out common flaws in either of the above methods or possibly suggest a better solution?
// Sample HTML
<div id='header'>
<div id='logo'>
LOGO GOES HERE
</div>
</div>
// Sample CSS
#header {
height: 100px;
}
// Version 1
#logo {
float: left;
margin-top: 20px;
}
// Version 2
#logo {
float: left;
position: relative;
top: 20px;
}
From Mozilla developer:
relative
Lay out all elements as though the element were not
positioned, and then adjust the element's position, without changing
layout (and thus leaving a gap for the element where it would have
been had it not been positioned). The effect of position:relative on
table-*-group, table-row, table-column, table-cell, and table-caption
elements is undefined.
I hope this answers your question.
Sometimes it might be the right thing to use, other times not. It really depends on your layout, if you want to make a responsive design, it might be better to have the margin there.
In your case you have a fixed height on the header, so you can use relative. I think it is a more common practice to use margin. I am only aware on issues concerning position: fixed on mobile devices.
You can learn more about CSS and positioning here.
In postion absolute and fix when u use top or bottom or right or left,you must not use float, you must for its parent use this style
postion:relative;
best regards

How to adjust relative div height with respect to inner absolute height?

For example: http://jsfiddle.net/MYvYy/182/
I have a lot of 'inner_box' elements inside of 'outer_box'. Inner_box elements a absolute.
I would like to adjust the outer_box height so that all inner_box elements fit in the outer_box.
I know it can be done with js. But I don't really like adjusting style with scripts.
So I was wondering if it is possible to be done using CSS?
I have some workaround for this problem, it may not fit your situation but consider looking at it.
First of all we need to duplicate all absolute positioned div which you want to make the parent extend to its height.
So your HTML will look like this.
<div class="outer_box">
<div class="inner_box">1</div>
<div class="inner_box ghost">1</div>
</div>
Then we need to add the "ghost div" CSS like so:
.inner_box.ghost{
visibility: hidden;
width: 100%;
top: 0;
left: 0;
position: relative;
}
It's not possible with CSS alone.
Layout flow:
An element with position:absolute is outside of the layout flow of the rest of the page. As far as the relative parent is concerned, the absolute child occupies no space in the layout.
This is very useful if you need to have a pop-up or a nav menu nested inside a container, because it won't affect the layout of the container. That's the sort of use case that position:absolute is well-suited for.
Fixed height:
If you need absolute content to behave as if it's a part of the layout flow, use fixed height. Give the relative parent and the absolute child a fixed height, and avoid placing any variable-height child elements before the absolute child. If variable-height content does precede it, use a relative placeholder div with a fixed height at the location where the absolute child needs to appear.
If position:absolute has to be used and fixed height is not an option, use JavaScript.
I only can provide you with Javscript fix for this using jQuery lib.
let me know if you use it or not,
$('.outer_box').height($('.inner_box').outerHeight());
This line will fix the outer_box height
I have tried the Fixed height method, but on small screens it is overlapping. So I have solved this problem by setting overlay background layer to seperate division and content to another division.
<div style="position:relative; background-color: blue; background-image:url('banner.png'); background-size:cover; background-position: center top;">
<div style="position:absolute; top:0; bottom:0; left:0; right:0; z-index:1; background-color:#00000099;"></div>
<div style="position:relative;z-index:2;"><h1 style="color:#fff;">Hello</h1></div>
</div>
I have uploaded the code on Codepen: https://codepen.io/shahbaz8x/pen/GRjEBze
I fixed it by changing the position property of div.inner_box into
position:relative
if this is not what you'r looking for, or this didn't fix it, then you will have to use Javascript.

css positioning

I have to create a div that should look like
<div id=1>
<img></img>
<div id=2></div>
</div>
the div with id 2 should appear at bottom-right corner of image, and the size of image is not fixed what should be the css applied to div with id=2
div with id =1 has no position defined so uses default and same is with image and i cannot change these
only div with id=2 is editable to me. Please suggest something
If you need to position the second DIV on top of the first DIV, then the best solution would be to position the first DIV with position:relative; and then use absolute positioning on the second DIV. The first DIV would have to have a fixed width or to be floated to limit it's width to that of the image.
If you have no way to control the first div, you are in a bit of a tight spot. You still need to make sure that the first div has the same width as the image, either by setting width explicitly or by using a float. You could then position the second DIV with negative margin and using position:relative in conjunction with z-index to make it flow on top of the image. But that would mean you'd have to know the height of the second DIV to make up for that exact amount using negative margin. It would work, but the solution wont be as robust as the first.
If you just need to have the text below the image it's a bit easier, just using plain old floats. I've coded up a very basicc version of all the three scenarios here: http://jsfiddle.net/laustdeleuran/7CnSh/
I hope it's useful.
If you cannot edit the CSS for div #1, you're sort of screwed.
If you could just add {position:relative} to that div, you'd be in business. Absolute positioning will target the first parent with 'Relative' positioning. Since the default of div 1 is 'Static'...Positioning won't work.
'Float' might work, div 2 would technically need to come before div 1 - thus causing div 1 to inherit the float of div 2; however, that would also stack your image atop div 2 rather than below it. ... So Float is out as well.
IF you can add CSS to div 1 and div 1 img, then an easy fix is this:
* { margin:0; padding:0 }
#one {position:relative; text-align:right;}
#two {position:absolute; bottom:0; right:0}
Good luck...
I think you are looking for float style.
Using numeric ids is a bad idea, so let's say you've called your divs div1 and div2.
As you can't style #div1 or the image, the only thing you might try is setting a negative margin on #div2. Try either one of:
#div1 { display: inline-block; width: 100px; margin-left: -100px }
Or, simply:
#div1 { margin-top: -100px }
Where the 100px values are just arbitrary and you'll need to decide on appropriate values depending on what you're putting in #div2
First, some valid HTML. But I guess that wasn't your real HTML?
<div id="div1">
<img [..] />
<div id="div2"></div>
</div>
You could this with position: absolute and negative margins.
#div1 { display: table; position: relative; }
#div2 {
position: absolute;
width: 50px;
height: 50px;
margin-top: -50px;
right: 0;
}
display: table should make the first div match the width of the image. position: relative so the second div will position itself relative to first div.
This might work (not sure of relative+table). But I haven't tested it. If it does't work, I suggest that you work with JS to position the second div, it's very easy.
try this:
<div id="d1">
<img src="https://encrypted.google.com/images/logos/ssl_logo_lg.gif"></img>
<div style="margin-left:225px;margin-top:-25px;z-index:1000;position: relative;" id="d2">Your Text</div>
</div>
you can play with the margin-left and margin-top

CSS position type change (absolute to relative) on child div causes odd effect on parent div. Why is that?

I'm trying to understand CSS positioning and I'm having trouble figuring out why a simple change that apparently should have no effect on the layout is causing a very disruptive change. I'm obviously missing something.
The initial objective was to place an inner div
vertically and horizontally within another div. That was fairly simple:
html, body {
margin:0;
padding:0;
height:100%;
}
div#container {
position:relative;
background:#4444ff;
margin: 0 auto; /* center, not in IE5 */
height:80%;
min-height:80%;
}
div#childDiv {
position:absolute;
background:#ff5555;
/* next we center it vertically and horizontally */
width:900px;
height:600px;
top:50%;
margin-top:-300px;
left:50%;
margin-left:-450px;
}
...and in the HTML page I used:
<body>
<div id=container>
<div id=childDiv>
test
</div>
</div>
</body>
which worked fine.
The curious part is what happens when I change the position attribute of the #childDiv div from absolute to relative.
My understanding is that first is should not affect the #container div at all since I'm changing only the position of the child element, and second that it should not change the layout since it is the only child element, its parent uses relative position and third I have not specified any offsets (tp, left, etc).
Instead, when I make this change, the parent #container is messed up (shows only up to the half of the viewport instead of 80% height as previously), and the position of #childDiv changes accordingly (also upwards, half outside the viewport).
My questions is: why does that happen? What concepts I'm not taking into account and why was the parent div affected by a change in the children's position setting?
If I remove #childDiv from within #container and place it inside body, then #container is no longer affected by that change so it seems something is propagating up in the DOM, which is odd to me. I've seen the same in firefox, opera, IE and chrome.
I have read W3C's spec on this topic but I haven't been able to figure this one out so far...
UPDATE: I created examples in JS fiddle to show the problem. You can see the original is here: jsfiddle.net/7Pr9y/1 and the affected one is here: jsfiddle.net/7Pr9y/3
Thank you!
Eduardo
When something is absolutely positioned, it is taken out of normal flow so its size, margins, etc. do not affect the things around it.
When something is relatively positioned, it is placed in normal flow (so its size, margins, etc. do affect the things around it) and layout is initially handled as if it were position: static, then it is moved according to the left, right, top and bottom properties.
It looks like your CSS got complex quickly because as soon as you positioned the child div absolutely, your container div would have disappeared, and putting percentage-based widths and heights on it wouldn't work.
The reason for this is that once you position something absolutely, it's taken out of the document flow, so your container div is now acting as if it contains nothing. If it contains nothing, unless you give it absolute dimensions (say, in pixels), you're saying "size yourself to a certain percentage of your container", which in this case, is the body element, which also acts as if it contains nothing.
When you start tossing heights and widths and min-heights on every element to compensate, especially when they are relative values, the results can become unpredictable very quickly. My advice would be to check out this reference on the box model by Chris Coyier: http://css-tricks.com/the-css-box-model/
It's super straightforward and uses some great diagrams to help visualize the different aspects of CSS positioning.
OK, I figured out why it becomes smaller when I change the size to relative.
Happens that because I have set the margins of the #childDiv to a negative value in order to center it, when I change it to relative that negative margin is taken into account when calculating the height of #container, resulting in a smaller #container.
I'm obviously a beginner in this, but seriously, it looks like CSS made it as complicated as possible to lay things out. No surprise most folks coming from table layouts start frustrated. :(
You don't need all these negative margin settings. Do the following:
html, body {
margin:0;
padding:0;
height:100%;
}
div#container {
background:#4444ff;
margin: 0 auto; /* center, not in IE5 */
text-align: center;
height:80%;
min-height:80%;
}
div#container:before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
margin-right: -0.25em; /* Adjusts for spacing */
}
div#childDiv {
display: inline-block;
text-align: left;
vertical-align: middle;
background:#ff5555;
width:500px;
height:200px;
}
I have used your code you provided and changed it around a little, to make the ghost spacer (the div#container:before) work.