Here is a simplification of my layout:
<div style="position: relative; width:600px;">
<p>Content of unknown length, but quite quite quite quite quite quite quite quite quite quite quite quite quite quite quite quite long</p>
<div>Content of unknown height</div>
<div class="btn" style="position: absolute; right: 0; bottom: 0; width: 200px; height: 100px;background-color: red;"></div>
</div>
The problem I'm having is that if the text/unknown div content is too long it is overlapping my absolutely positioned div.
I have searched the web and SO for a solution and the only one I found suggested putting an invisible div where absolutely positioned div is - trouble is if I could do that I wouldn't need to have the absolutely positioned div in the first place (or am I missing the point here).
Can anyone think of a css solution before I go down the jquery route?
The solution for me was to create a second invisible div at the end of the content of unknown length, this invisible div is the same size as my absolutely positioned div, this ensures that there is always a space at the end of my content for the absolutely positioned div.
This answer was previously provided here:
Prevent absolutely-positioned elements from overlapping with text
However I didn't see (until now) how to apply it to a bottom right positioned div.
New structure is as follows:
<div id="outer" style="position: relative; width:450px; background-color:yellow;">
<p>Content of unknown length</p>
<div>Content of unknown height </div>
<div id="spacer" style="width: 200px; height: 25px; margin-right:0px;"></div>
<div style="position: absolute; right: 0; bottom: 0px; width: 200px; height: 20px; background-color:red;">bottom right</div>
</div>
This seems to solve the issue.
Short answer: There's no way to do it using CSS only.
Long(er) answer: Why? Because when you do position: absolute;, that takes your element out of the document's regular flow, so there's no way for the text to have any positional-relationship with it, unfortunately.
One of the possible alternatives is to float: right; your div, but if that doesn't achieve what you want, you'll have to use JavaScript/jQuery, or just come up with a better layout.
If you are working with elements of unknown size, and you want to use position: absolute on them or their siblings, you're inevitably going to have to deal with overlap. By setting absolute position you're removing the element from the document flow, but the behaviour you want is that your element should be be pushed around by its siblings so as not to overlap...ie it should flow! You're seeking two totally contradictory things.
You should rethink your layout.
Perhaps what you want is that the .btn element should be absolutely positioned with respect to one of its preceding siblings, rather than against their common parent? In that case, you should set position: relative on the element you'd like to position the button against, and then make the button a child of that element. Now you can use absolute positioning and control overlap.
Put a z-indez of -1 on your absolute (or relative) positioned element.
This will pull it out of the stacking context. (I think.) Read more wonderful things about "stacking contexts" here: https://philipwalton.com/articles/what-no-one-told-you-about-z-index/
Thing which works for me is to use padding-bottom on the sibling just before the absolutely-positioned child. Like in your case, it will be like this:
<div style="position: relative; width:600px;">
<p>Content of unknown length, but quite quite quite quite quite quite quite quite quite quite quite quite quite quite quite quite long</p>
<div style="padding-bottom: 100px;">Content of unknown height</div>
<div class="btn" style="position: absolute; right: 0; bottom: 0; width: 200px; height: 100px;background-color: red;"></div>
</div>
<div style="position: relative; width:600px;">
<p>Content of unknown length</p>
<div>Content of unknown height</div>
<div id="spacer" style="width: 200px; height: 100px; float:left; display:inline-block"></div>
<div class="btn" style="position: absolute; right: 0; bottom: 0; width: 200px; height: 100px;"></div>
</div>
This should be a comment but I don't have enough reputation yet. The solution works, but visual studio code told me the following putting it into a css sheet:
inline-block is ignored due to the float. If 'float' has a value other than 'none', the box is floated and 'display' is treated as 'block'
So I did it like this
.spacer {
float: left;
height: 20px;
width: 200px;
}
And it works just as well.
Could you add z-index style to the two sections so that the one you want appears on top?
You should set z-index to absolutely positioned div that is greater than to relative div.
Something like that
<div style="position: relative; width:600px; z-index: 10;">
<p>Content of unknown length</p>
<div>Content of unknown height</div>
<div class="btn" style="position: absolute; right: 0; bottom: 0; width: 200px; height: 100px; z-index: 20;"></div>
</div>
z-index sets layers positioning in depth of page.
Or you may use floating to show all text of unkown length. But in this case you could not absolutely position your div
<div style="position: relative; width:600px;">
<div class="btn" style="float: right; width: 200px; height: 100px;"></div>
<p>Content of unknown length Content of unknown length Content of unknown length Content of unknown length Content of unknown length Content of unknown length Content of unknown length Content of unknown length</p>
<div>Content of unknown height</div>
<div class="btn" style="position: absolute; right: 0; bottom: 0; width: 200px; height: 100px;"></div>
</div>
I'm responding because I also ended up in this post and found a simple and effective solution: the absolute element has a fixed position and size, so you simply need to add right padding of 400px (referring to your example) to your content
put texts into a new div. Then make that div also position: absolute; . Also, you can use overflow: hidden; for that div.
Related
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>
So,
i'm guessing this has been asked before but im realy missing something here which i've been starring myself dead at for the last hour.
I've got a container with two divs, position relative and absolute since i want them to stack. The stacking part works. However, this container, the #mockupcontainer, needs to be inside the #what-container-inner which i cant seem to get to work. At the moment it just stops the #what-container-inner and placed the #mockupcontainer after it. My jsfiddle illustrates perfect whats going wrong. I hope someone can help me on this one.
https://jsfiddle.net/rvq41vaf/
CSS:
#what-container-outer {
background-color: #ececec;
margin-left: auto;
margin-right: auto;
}
#what-container-inner {
background-color: #ececec;
width: 75%;
margin-left: auto;
margin-right: auto;
position: relative;
}
.mockupcontainer{
position: relative;
}
#pin-mockup{
position: absolute;
z-index: 10;
}
#pin-mockup-site1{
position: absolute;
z-index:11;
}
HTML Code:
<div id="what-container-outer">
<div id="what-container-inner">
sdfsdfsdfsdfsdfsdfsdfsdf<br>sdfsdfsdfsdfsdf
<div id="trigger-mockup"></div>
<div class="mockupcontainer">
<div id="pin-mockup">
<img src="image2" class="img-responsive" alt="Realiseren">
</div>
<div id="pin-mockup-site1">
<img src="image1" class="img-responsive" alt="Realiseren">
</div>
</div>
</div>
</div>
Kind Regards,
Donny.
Since you have your two image-containing divs (pin-mockup and pin-mockup-site1) positioned absolutely, they are pulled out of the flow and the enclosing divs no longer leave room for them. The solution is to set the larger one to position: relative so that the enclosing div does make room for it. Setting top:0 on the second (absolutely positioned) div brings it to the top of the enclosing div.
Here's the fiddle.
See also the MDN docs on the position property.
Sorry for the messy code:
<div style="position: relative;">
<div style="position: absolute; top: 50%;">This should be vertically centered</div>
<img src="http://phaseoneimageprofessor.files.wordpress.com/2013/07/iqpw29_main_image_.jpg" width="100%" style="visibility: hidden; position: absolute;"; />
<img src="http://phaseoneimageprofessor.files.wordpress.com/2013/07/iqpw29_main_image_.jpg" width="100%" />
</div>
http://jsfiddle.net/a5as2/
as you can see, the text is almost centered vertically - but as you will shrink the width, you will see thats not 100% precise. What to fix now<
A pure css solution would be to set the inside div a height, and add margin: -height/2 px for it.
Example:
<div style="position: absolute; top: 50%; height: 20px; margin-top: -10px;">This should be vertically centered</div>
In case you don't know the height of the div, you can use js to get it, then reposition the div.
Will be something like (jQuery, directly in answer so might have some problems, adapt it pls.):
$("#idDiv").css("margin-top") = parseInt($("#idDiv").height() / 2) + "px";
Another solution, would be to use table-cell display, and vertical-align: middle (I personally don't like it, but may fit your needs).
What about this?
http://jsfiddle.net/a5as2/3/
.use-a-stylesheet-and-classes-please { top: 50%; position: absolute; }
It is in the middle, even if you shrink it.
You can position the elements when shrinked by using media queries. And... please, don't use inline styling.
I'm trying to get a layout in HTML/CSS done. The goal is about this:
Some elements in this layout have a non-fixed size. The area on the left has fixed width, the footer has fixed (content matching) height. The list on the left shall be extending it's height, the text in the footer it's width and the canvas both dimensions so the entire browser page is filled, but without causing any scrollbars to appear. Oh, and B is for button, but that's not really of importance I guess.
I have seen some examples (this) and references (this) and tried to learn from them, but I can't get it the way I want. One of the closer attempts I have made is this one:
<html><body style="margin: 0; padding: 0;">
<div style="position: absolute; background: #afa; top: 0px; bottom: 0px; left: 0; right: 0px;">
<div style="position: absolute; background: #afa; top: 0px; bottom: 0px; left: 0; width: 240px;">
<input style="width: 240px" id="selectedPosition"></input>
<select style="position: relative; width: 240px; height: 100%;" id="points" multiple="multiple"></select>
<div style="position: relative; background: #afa; left: 0; width: 240px;">
<input style="width: 80px" type="button" value="Add"></input><!--
--><input style="width: 80px" type="button" value="Up"></input><!--
--><input style="width: 80px" type="button" value="Down"></input>
</div>
</div>
<div>
<div><input style="position: absolute; bottom: 0px; left: 0px; width: 100%"></input></div>
<div><input style="position: absolute; bottom: 0px; right: 0px;" type="button" value="Button 4"></input></div>
</div>
<div style="position: absolute; background: #aaf; height: 100%; left: 240px;top: 0px;right: 0px; overflow: auto;"></div>
</div>
</body></html>
Problem here is the lower elements ant the button in the bottom right are covered by size extending elements. I probably could fix this with fixed dimensions or margins, but I'd like to have it done in a "proper" way.
Another approach was to use a 4x5 table with spanning rows and columns, but I got confused even more and quickly let that drop.
I'm fairly new to layouting in HTML/CSS, so any source "for dummies" in this matter helping me getting the job done in spite of an actual solution is appreciated also.
Update
After looking at the links and at Fico's answer. However, the closest attempt is this. Problem is that both the list and the bottom text overlap the respective button(s) when width/height is set to 100% (in the jsfiddle example I used lower numbers for demonstration purposes). As a side note, the list in the example given does not extend vertically at all. When using my local file, then it does.
All examples I have seen with a fixed footer and height filling columns use some fixed size height for the footer which is then negatively applied as margin, but my footer should just wrap it's content. Isn't there any way to set up a rule "extend until you reach the next element"?
Start by using markup for content and css for styling.
You will work cleaner and with less trouble.
It's not a good practice to include so many tags instead of using an external CSS (or eventually embedded in the HEAD of the document)
It doesn't seem to me, you are in the need of so much absolute positioning here.
Identify your big areas in your design (as the figure below)
First impression is that you got an aside column at the left width some elements in Normal document flow and in its bottom three buttons floating in a div
The canvas could be floating left or right of this aside
Both , the aside and the canvas , contained in a mainContainer div.
The text and button at the bottom could be integrated in a footer with the button floating right or left at your will
The flexible solution is simple to instrument. Use some min with properties for your canvas and probably some fixed widths for the aside.
Is there any way to clear absolutely positioned elements with CSS? I'm creating a page where I need each part of the site (section element) to be absolutely positioned, and I want to apply a footer with content below those elements.Tried to relatively position the header and footer to see if a total height would be taken into account but the footer still gets "trapped" underneath the section elements. Any ideas?
<header style="position: relative;"></header>
<div id="content" style="position: relative;">
<section id="a" style="position: absolute;"></section>
<section id="b" style="position: absolute;"></section>
<section id="c" style="position: absolute;"></section>
<section id="d" style="position: absolute;"></section>
<section id="e" style="position: absolute;"></section>
</div>
<footer style="position: relative;"></footer>
Absolutely-positioned elements are no longer part of the layout - parent items have no idea how big absolutely-positioned child elements are. You need to set the height of "content" yourself to ensure it does not overlap the footer.
Don't use absolutely-positioned elements for layouts since that elements are removed from normal flow and no longer affect elements around them. And they're not affected by other elements.
Use absolute-positioning to move elements within a container when conditions allow.
For floated elements I suggest you to use a specific clearing technique called clearfix. I use it religiously.
http://nicolasgallagher.com/micro-clearfix-hack/
http://jsfiddle.net/necolas/K538S/
Had same question, made all absolute positioned, but let the first one be relative, as for responsive layout where height does change, it did help to keep track of the elements height changes, notice in this case all elements have same height:
.gallery3D-item {
position: absolute;
top: 0;
left: 0;
}
.gallery3D-item:first-of-type {
position: relative;
display: inline-block;
}
I discovered a easy solution to this, it might not cover all possible problems but at least it solved my problem.
HTML:
<p>Content before</p>
<div class="offset-wrapper">
<div class="regular">
<img src="https://www.gravatar.com/avatar/bdf0bf75e96fa18e57769865ebeb9a6e?s=48&d=identicon&r=PG" />
</div>
<div class="special">
<img src="https://www.gravatar.com/avatar/bdf0bf75e96fa18e57769865ebeb9a6e?s=48&d=identicon&r=PG" />
</div>
</div>
<p>Content after</p>
CSS:
.offset-wrapper {
background: green;
position: relative;
width: 100px;
}
.offset-wrapper .regular {
visibility: hidden;
}
.offset-wrapper .special {
bottom: -15px;
left: -15px;
position: absolute;
}