Changing the order of elements using absolute positioning - html

I want to move a child element to the bottom of its parent via absolute positioning.
Ie The parent will finish and then the element will appear directly after. ie the Parents bottom margin will be aligned with the childs top margin.
I have somewhat achieved this via padding however I don't see how to make this work when the child's size is changeable? ie I have a hardcoded padding size.
<body>
<footer class="footer">
<p> I am the footer </p>
<div class="after">
<h2> I want to appear after the footer</h2>
<img src="http://static.guim.co.uk/sys-images/Guardian/Pix/pictures/2014/4/11/1397210130748/Spring-Lamb.-Image-shot-2-011.jpg"/>
</div>
<h3> I should be in the footer</h3>
</footer>
</body
css ->
.footer {
position: relative;
left: 30px;
padding-bottom: 500px;
}
.after {
position: absolute;
bottom: 0px;
left: 0px;
}
codepen -> http://codepen.io/ianw92/pen/pvXYeV

Absolutely positioned elements are removed from the normal flow. By definition, they therefore won't take other elements into consideration when being positioned. As you are seeing, you would need to hardcode some value.
I'd suggest avoiding absolute positioning and using a flexbox solution to change the order of the elements:
Updated Example
.footer {
display: flex;
flex-direction: column;
}
.footer .after {
order: 3;
}

Related

How to make parent element cover children if they are positioned absolute

I want to create a slider, so here is the code:
div#list_container {
position: relative;
width: 100%;
}
div#first_list {
position: absolute;
left: 0px;
top: 0px;
}
div#second_list {
position: absolute;
left: 70%;
top: 0px;
}
<div id="list_container">
<div id="first_list">
<h1>Smth</h1>
</div>
<div id="second_list" class="aim_list">
<h1>Smth</h1>
</div>
</div>
<h2>Following elements</h2>
It kinda works (I would just change left property to move them), but since parent (div#list_container) is positioned as relative, so it doesn't cover children elements, so another elements, which will go after slider are shown above it. How can I fix it?
When you change position of child elements to absolute, they are no longer relative to their parent element. Either make parent absolute while changing children's position to relative, or add height to parent.
I also highly recommend implementing this using CSS Flexbox, otherwise it will be very difficult to maintain. See if you can work with this:
#list_container {
position: absolute;
width: 100%;
display: flex;
justify-content: space-around;
}
#list_container > *{
flex-grow: 1;
}
The problem is that, since your child elements are with absolute positioning, there is nothing that actually expands the box of the parent element. To fix it, you can add height to the div#list_container, depending on your design target.

Place absolute div under relative div

I don't know if is possible through CSS only to have one absolute footer under a relative element - being the relative one different in height due to the nature of it: either change of content or responsiveness. My HTML (using Angular 5):
<main>
<app-navbar></app-navbar>
<div class="content-container" [#fadeAnimation]="routeTransition(outlet)">
<router-outlet #outlet="outlet"></router-outlet>
</div>
<app-footer></app-footer>
</main>
The reason why I want to have that is because the relative element contains the view of the user and I'm using angular animations which happen to "require" the elements that get displayed being absolute positioned in order to get the desired visualisation.
The problem with that is that for large elements I am having issues because the footer which is also absolute, does overlap the actual content if that makes sense.
I want to have a "sticky footer" at the bottom of the page so that it has absolute configuration etc (app-footer will render footer):
footer{
position: absolute;
right: 0;
bottom: 0;
left: 0;
width: 100%;
padding: 1rem;
}
My CSS:
main{
padding-top: 10px;
padding-bottom: 100px;
}
.content-container{
position: relative;
}
/deep/ router-outlet~* {
position: absolute;
width: 100%;
height: 100%;
}
That was working fine till I added the relative to the .content-container to have the absolute position to the inner element.
A possible workaround I came across was to give a fixed height to the .content-container class and do the different resolutions so I can push down the footer. However I don't think that's possibly the best approach. I'm using Angular 4 if that's of any help. I also had a look at How to position element below relative positioned element without overlapping? but again, the suggested solution was to do with hardcoding the height.
UPDATE 1: I have updated the question with more detailed info. Hope it is now clear.
UPDATE 2: Plunker: https://plnkr.co/edit/FHhncrGBcO9jaNRiUfJQ?p=preview
Parent:
position: relative;
Child:
position: absolute;
z-index: 2;
top: 100%;
If I understood your problem, you need to set a position: relative and a z-index to your .content-container.
Keep in mind that the z-index and the absolute positioning refers to the next relative parent. This is the body by default, but it could be a div with a position: relative in-between.
.content-container{
position: relative;
z-index: 2;
background-color: rgba(180,100,50,.7);
padding: 85px 20px;
}
footer{
position: absolute;
bottom: 0;
z-index: 1;
background-color: pink;
padding: 20px;
}
<main>
<div class="content-container">
content
</div>
<footer>footer</footer>
</main>
I would suggest to use position:fixed for your footer.
For example:
footer{
position: fixed;
right: 0;
bottom: 0;
left: 0;
width: 100%;
padding: 1rem;
}
"fixed" means: relative to the view-port (and not relative to the nearest element with a position)
If I understand you, use a z-index
footer {z-index:0;}
.content-container {z-index:1;}
Currently your looks like this:
content-container is a div. It has explicitly set relative position to the document, since there is no node above with position: relative
after content-container there is a footer with position: absolute. Since there is no node with relative position above, it is absolute to the document
Based on what you write, footer overlaps content. And this is true. Because content-container and footer are positioned to the document, so are on the same level. That means they are rendered based on the document order:
Content container is rendered
Footer is rendered
Since that said, because footer is rendered last, it will overlap content container content.
To fix it you need to make sure footer will be rendered before content, or make sure whatever order they are rendered, footer will be rendered above.
To change rendering order you can just reposition container-content in the HTML code and place it after footer div.
But this is a fragile and troublesome solution.
There is fortunately a solution to this problem. You can explicitly indicate on what layer of rendering element should be. To do this you need to use z-index CSS property.
footer {
z-index: 1;
}
It tells browser that footer shoud be rendered above, way above other content elements.
Default value of z-index is auto. It translates to a value of 0. So if we set z-index to 1, node will be rendered above other elements on equal level without z-index being set.

Elements taking over the space of an element with position absolute

I am trying to have a div at the top of my page that fits with no space against the top and sides.
All the example I have seen on how to do this put the div position to absolute.
But when I do this, the following img sibling moves to the top of the page with the previous div.
So I have two questions. Why does the following sibling move? Also, how can I have a div fit with 0 space against the top, without having position:absolute
div {
position: absolute;
top: 0px;
left: 0px;
background: #888888;
width: 100%;
height: 100px;
}
<body bgcolor="#000000">
<div>
<h1>HEADER</h1>
</div>
<img src="pic_mountain.jpg" alt="Mountain View" style="width:304px;height:228px;">
</body>
</html>
You don't need position: absolute to align things to top just use margin: 0 on the body, h1 Like:
body, h1 {
margin: 0;
}
Have a look at the snippet below:
body, h1 {
margin: 0;
}
div {
background: #888888;
width: 100%;
height: 100px;
}
<!DOCTYPE html>
<html>
<body bgcolor="#000000">
<div>
<h1>HEADER</h1>
</div>
<img src="http://placehold.it/304x228" alt="Mountain View" style="width:304px;height:228px;">
</body>
Hope this helps!
When you give an element position: absolute, you remove it from the normal flow of the document. This means that it no longer takes up any space in the layout. As a result, surrounding elements don't know it exists and take over the previously used space.
But you don't need absolute positioning in this case. The reason for the gaps are default margins on elements set by the browser. Just override those defaults with your own settings.
body, h1 {
margin: 0;
}
div {
height: 100px;
background: #888888;
}
<body bgcolor="#000000"bgcolsor="#000000">
<div>
<h1>HEADER</h1>
</div>
<img src="pic_mountain.jpg" alt="Mountain View" style="width:304px;height:228px;">
</body>
More information:
Normal flow ~ MDN
Absolute positioning ~ MDN
Why does the following sibling move?
It moves to the top because the first div is position: absolute, that's what expected when we apply this property / value. This div is also relative to the parent / body and the whole document (because no position: relative was specified anywhere else). When you apply position: absolute you remove that element from the normal document flow. It kind of flies over the document.
When you have this option applied to an element nested to something using position: relative, you'll see that the child will obey the parent's top, left, right and bottom.
Also, how can I have a div fit with 0 space against the top, without having position:absolute
This way:
body {
margin: 0;
}
With:
h1 {
margin-top: 0;
}
Or:
div {
overflow: hidden;
}
Without position: absolute; top: 0px; left: 0px; width: 100%; on the div. div's default params will take over what's needed.
The margin-top: 0 or overflow: hidden must be there just to get rid of the top h1's default margin, because when there's a margin in a case like that, the div background won't follow the whole div flow. Using overflow: hidden the way I've shown you is a technique of "clearing" things, like clearfix and others. You can read more about them here.
Also, Michael_B links about normal flow and absolute positioning are very relevant and a must read.

setting html to position relative

I am curious how works position: relative in html tag. Can anyone explain? Is it positioned relative to document object or something like this?
<footer class="footer">
<div class="container">
<p class="text-muted">Place sticky footer content here.</p>
</div>
</footer>
html {
position: relative;
min-height: 100%;
}
body {
/* Margin bottom by footer height */
margin-bottom: 60px;
}
.footer {
position: absolute;
bottom: 0;
width: 100%;
/* Set the fixed height of the footer here */
height: 60px;
background-color: #f5f5f5;
}
This keyword lays 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).
An element with position: relative; is positioned relative to its normal position.
Setting the top, right, bottom, and left properties of a relatively-positioned element will cause it to be adjusted away from its normal position. Other content will not be adjusted to fit into any gap left by the element.
Source: https://www.w3schools.com/css/css_positioning.asp
Actually it won't make any sense if you use position relative with html tag.
position: relative;
positions the child with respect to its parent or to its neighboring elements.
You can try position: relative with body to position the body relative to the parent html.
Let me know if you require any further help

div with inline-block not resizing

I have two elements, both with display: inline-block, and the parent has white-space: nowrap.
When the screen is resized, the div on the right side don't resize, like this.
I'm trying to make only the blue div resize.
Full source (jsfiddle)
The structure of the html is like this:
<div class="container">
<div class="header">...</div> <!-- red -->
<div class="aside">...</div> <!-- pink -->
<article>...</article> <!-- blue -->
</div>
Relevant css:
* {
box-sizing: border-box;
}
div.container {
margin: 0 auto;
max-width: 40em;
padding: 0;
white-space: nowrap;
}
div.container > * {
white-space: normal;
}
.aside {
display: inline-block;
max-width: 15em;
vertical-align: top;
}
.article {
display: inline-block;
max-width: 25em;
}
Old question, but for the sake of knowledge of anyone who reads this and also has the doubt:
What I've found is that setting position: relative on the .container
and position: absolute on the .article does what I want.
An absolute positioned element is positioned relative to the nearest positioned ancestor, where a positioned element means anything with a position property different to static, the default; if does not found any positioned element, uses the body element.
The absolute positioned elements, if has their width and heigth in auto, resizes to fit its content, and limits the maximun sizes by its positioned ancestor. You can check this putting a short string instead a large one: the element will shrink to the length of text. If you remove the positioning from div.container, the article (if still positioned absolute) will grow (depending on its content) to cover the space between previous element and body width.
And, related to the aforementioned and to add some utility to this delayed answer, a not-very-know bonus: if you define the right and left properties of a absoluted positioned element, and leave the width in auto, the element will cover the horizontal size between the right and left defined. This way you could put something like
article {
background-color: #a0f4ec;
display: inline-block;
position: absolute;
right: 0;
left: 30%;
}
div.aside {
background-color: #faf;
display: inline-block;
max-width: 15em;
width: 30%;
}
This trick also applies in a vertical sense, but with height, top and bottom properties.
There are a few ways to do it.
Method 1:
two divs the same line, one dynamic width, one fixed
Method 2 (negative margins)
http://alistapart.com/article/negativemargins
Unfortunately, Narxx's answers require the divs to be floated. I'm sure that's what you should do if you're building a real site, but in my case, I'm trying not to use it.
What I've found is that setting position: relative on the .container and position: absolute on the .article does what I want.
Simplified fiddle
If anyone can explain why, I'll mark it as an answer.