Strange container div behaviour - css

I'm asking this for learning purposes; there aren't any negative aspects on this behaviour, but I just wonder if this could have any negative consequences in the future.
So I have a container div: content_wrap, which has two other div's: side_bar and main_content. The container div is 980px width, and is used to center its contents using margin-left and margin-right.
It's doing this correctly, however, when I was debugging the page (in Firefox), I noticed that the browser renders the div as being 0x0px and renders the parent div off-screen. However, it does position the child divs correctly. See this JSFiddle for an example: http://jsfiddle.net/7fsXp/7/
I Googled this and most of the answers have something to do with floats and are solved by using clear:both, but I don't use any floats. I did notice that if I change the main_content div from position:absolute; to position:relative;, the content_wrap is displayed correctly. Or I can fix it by setting a height for content_wrap.
I don't actually need to be able to see the content_wrap, so there isn't really a problem, as it is doing its job in means of centering the child divs. I just wondered if it would be a bad practice to leave it like this? Is it a bad thing, or does it matter?

Try adding other elements to this HTML and enjoy the horror :D
There are actually many things in your code, that I wouldn't do. First of all, when an element is with position: absolute or position: fixed its layout is "ignored" by other elements or in other words cannot "push" any element and that is why your container is having 0 height. It's like they are ethereal (best explanation ever, I know).
You should check this article on positioning -- http://css-tricks.com/absolute-relative-fixed-positioining-how-do-they-differ/
The fact that they are in the place you expect them to be is that there are actually no other elements in the HTML and the absolute element is positioned relatively to the body and so is the fixed one (but that's what elements with position: fixed always do). Looks what happens when I add some other content to the parent div -- http://jsfiddle.net/7fsXp/13/
So long story short - you shouldn't form your layout with absolute or fixed elements if you can do it without them.

position: fixed and position: absolute take the elements out of the flow, so using either of these positions on all child divs will collapse the parent div entirely.
If you have content below a collapsed div, it will flow up and over/under that content like this.
You don't need to position the main_content div absolutely, but you'll need to change a few things to top align the sidebar and main_content.
DEMO
Since sidebar is fixed, it's using the document, not the container div as a reference for top, while main_content would use the body (unless you add position: relative to the container). Getting rid of the body's default padding/margin will fix the small alignment difference.
body {
padding: 0;
margin: 0;
}
#main_content {
//remove position: absolute;
margin-top:70px; //top: 70px won't work unless you specify position
}

It depends on what you are willing to do, but because the default position for div is position: static; changing the position: relative; will avoid the collapse of parent div.

Related

div with `position:fixed`, but stil have same behaviour as with `position:relative`

When working with position:fixed; this is the expected result one would get:
What I actually want to achive is:
as in this result when working with two position: relative; elements
Don't get me wrong, I know how position: fixed or position: absolute works and should behave, how I haven't come around how to get both properties for the same div...
One approach wich works, but isn't a satisfying solution is that I put a position: relative -div below my fixed element, not allowing the second element moving below the fixed element because it is already taken by the extra div.
So I have tried to get this second relative div working with :after or :before pseudo-elements. This doesn't quite seem to work
div:after, div:before { position: relative; }
it somehow get's mixed up because the element itself is
div { position: fixed }
and turning fixed and relative around obviously also doesn't work because fixed will be bound to the relative - element.
Any ideas?
And if somebody is wondering why I need to use fixed and don't just go with relative : it's for scrolling reasons.
why not use a margin left on the relative div?
http://jsfiddle.net/q3nQr/1/
html
<div id="fixed"></div>
<div id="relative"></div>
css
#fixed { position: fixed; width: 60px; height:100px; background: red; }
#relative { position: relative; width: 300px;height:1000px; background: green; margin-left:65px; }
UPDATE
Take a look at the w3 spec for static positioning (just read the first two paragraphs).
http://www.w3.org/wiki/CSS_absolute_and_fixed_positioning
Absolutely positioned elements are removed entirely from the document
flow. That means they have no effect at all on their parent element or
on the elements that occur after them in the source code. An
absolutely positioned element will therefore overlap other content
unless you take action to prevent it. Sometimes, of course, this
overlap is exactly what you desire, but you should be aware of it, to
make sure you are getting the layout you want!
Fixed positioning is really just a specialized form of absolute
positioning; elements with fixed positioning are fixed relative to the
viewport/browser window rather than the containing element; even if
the page is scrolled, they stay in exactly the same position inside
the browser window.
This means that elements with fixed or absolute positions do not associate with any other elements in the document, this means they cannot effect the width of another element. If the width of the static element is not known, I think you will need manipulate the DOM with javascript; something as simple as (jquery, not tested):
var staticwidth = $("#static").width();
$("#relative").css('margin-left', staticwidth + 'px');

Navigation Links Suddenly Unclickable

I'm working on a page for a class, just to display things (you can see them sorted by chapter in the body) but I originally had a list on the left that I used initially that just listed them all, and I wanted to keep it.
Problem is, once I started adding more CSS - I don't know where exactly - the area on the left just became completely unclickable. You can't highlight the text, you can't click any of it - nothing. I have absolutely no idea whatsoever what is causing this.
link to the site here
here is a pastebin link showing everything I have.
thank you, i really appreciate any help.
The .content div overlaps entire body area, because of "position: absolute;"
Add z-index: 9999; to #menu in your CSS and it should be clickable.
Other way is to use "position: relative; float: left;" to both .content and #menu, but you have to be carefull with their widths. Their sum of widths (including padding and margin and border) should be less or equal to the container width. In your case it should be body tag (actually a don't see body tag in your html).
That's because your .content div is using position: absolute; so it's taken out of the page flow and overlapping your sidebar because it has no width set (block elements span the full width of your viewport unless you give it a fixed width) ... just add a negative z-index value to your .content div and it should work fine.
More on z-index

position relative elements after absolute elements

I have a site with absolute positioned elements on it, for example the top Navigation of the site:
#topNav
{
position: absolute;
top: 100px;
left: 50%;
height: 40px;
width: 1000px;
margin-left: -500px;
}
Now I created a sticky footer like on the following site:
http://ryanfait.com/resources/footer-stick-to-bottom-of-page/
Now, the problem is that the footer will "overlap" the topNav,
because the topNav is positioned absolute, which means it's "outside of the normal float of elements". The relative position will not "notice" that there is the topNav before.
Before I start creating additional "pusher divs" for each absolute positioned element I would better ask if there are better practices than "pusher divs" or should I even not use position absolute on my elements?
EDIT:
JsFiddle here: http://jsfiddle.net/dkxUX/15/
When you scale down your browserwindow you'll find #footer overlapping all elements before it.
You could just apply a 140px top margin/padding to the body or other container element which would make the topNav's height and offset accounted for.
Better yet, don't set position to absolute in this case - it appears to me that all you're doing is horizontally centering a 1000px wide div.
/*top-margin of 100px + center the element*/
#topNav {width:1000px; height:40px; margin:100px auto 0;}
Update: I see your jsfiddle now. You could account for all absolutely positioned elements when setting the margin/padding as suggested in the first paragraph You are using absolutely positioned elements when normal document flow could be relied on.
a little bit too late to give an answer but it may help someone in the future, I came up with that problem not too long ago so here was my shot at it, using jquery since I couldn't came up with a CSS solution that wasn't removing the DOCTYPE tag (which isn't something you should do, anyways).
So here it is.
$("#CONTAINERDIV").prepend("<div id='relativefix' style='position:relative;margin-top:"+($("#YOUR_ABSOLUTE_DIV").offset().top+$("#YOUR_ABSOLUTE_DIV").outerHeight()+30)+"px'></div>");
$(window).resize(function(){
$("#relativefix").css("margin-top",($("#YOUR_ABSOLUTE_DIV").offset().top+$("#YOUR_ABSOLUTE_DIV").outerHeight()+30)+"px");
});
So yeah, that's all there is to it, you just dynamically add another div at the start of the container hard-placed under the absolute div, that will force all subsequent relative divs to me placed after it, it is like a clear fix for someone who ran out of ideas.

CSS take height of absolutely positioned child

I've got a container that's set to a max-width:780px and height is undeclared. Inside the container, there's an image slideshow. Everything on the page is responsive, so as the width decreases, the image (who's width is set to 100%) adjust's the heights container.
The slideshow change's the images to display:static; and position:absolute; which no longer "holds open" the container because it's not seen as content of the container
Is there any creative solution out there to take the height of a child element that's absolutely positioned?
Example below has NO height declared on the main container.. nothing's holding it open.
http://dhut.ch/test/santos/
Thank you!
Are the images all the same dimensions? If yes, you can use a percentage padding-top on the element that contains the images.
So if your images are all, say, 760px wide by 500px tall, that's 500/760 = .65789
Which as percentage would translate into something like:
#main {
position: relative;
max-width: 760px;
padding-top: 65.789%;
}
The reason this works is because with padding if it's set with a percentage, it is calculated as a percentage of the width. As the element shrinks in width, the height will shrink proportionately and the box will remain in the same ratio of width to height. The images, positioned absolutely, won't be adding to the height of the box.
This'll work as long as your images are all the same aspect ratio and you're not expecting that ratio to change. If you'll be using a lot of random images, this isn't for you.
I recently had a similar problem with an image that I needed to absolute position at the top of a Zurb Foundation templated page in order to pull it out of the flow and reset its dimensions (Image had to stretch to edges of wrapper, instead be enclosed by its parent .row padding). However, of course, this meant that all the fluid responsive elements below it popped right up over the top of the image. Setting a margin-top or positioning the sibling elements below meant a rigid top space that didn't resize with the width of the browser.
To get around it, I placed a duplicate of the image right after the absolute positioned image and set its visibility: hidden; I had to add a little bit of extra margin bottom to make up for the difference in height, but the end result is everything on the page flowing exactly to the height of the image in use.
I've also used the padding trick described by unexplainedBacn above, and it's a great trick as well. It takes a little bit of math, but I voted that answer up. Great solution.
I think you'd better change your approach. For sliders, the best practices is to float child elements of the container, and also use one of the known techniques to prevent parent's great collapse. So, I suggest that you remove the position: absolute CSS rule from images and float them inside your <div id='main'>, then use any of these methods to force it to encompass it's children:
div#main {overflow: hidden;}
div#main:after {content: ''; display: block; clear: both; visibility: hidden;}
Add a <div style='clear: both;'> to the end of your main div container.
Remove the absolute position. I would avoid inline styling as well.

Seeking CSS Browser compatibility information for setting width using left and right

Here's a question that's been haunting me for a year now. The root question is how do I set the size of an element relative to its parent so that it is inset by N pixels from every edge? Setting the width would be nice, but you don't know the width of the parent, and you want the elements to resize with the window. (You don't want to use percents because you need a specific number of pixels.)
Edit
I also need to prevent the content (or lack of content) from stretching or shrinking both elements. First answer I got was to use padding on the parent, which would work great. I want the parent to be exactly 25% wide, and exactly the same height as the browser client area, without the child being able to push it and get a scroll bar.
/Edit
I tried solving this problem using {top:Npx;left:Npx;bottom:Npx;right:Npx;} but it only works in certain browsers.
I could potentially write some javascript with jquery to fix all elements with every page resize, but I'm not real happy with that solution. (What if I want the top offset by 10px but the bottom only 5px? It gets complicated.)
What I'd like to know is either how to solve this in a cross-browser way, or some list of browsers which allow the easy CSS solution. Maybe someone out there has a trick that makes this easy.
The The CSS Box model might provide insight for you, but my guess is that you're not going to achieve pixel-perfect layout with CSS alone.
If I understand correctly, you want the parent to be 25% wide and exactly the height of the browser display area. Then you want the child to be 25% - 2n pixels wide and 100%-2n pixels in height with n pixels surrounding the child. No current CSS specification includes support these types of calculations (although IE5, IE6, and IE7 have non-standard support for CSS expressions and IE8 is dropping support for CSS expressions in IE8-standards mode).
You can force the parent to 100% of the browser area and 25% wide, but you cannot stretch the child's height to pixel perfection with this...
<style type="text/css">
html { height: 100%; }
body { font: normal 11px verdana; height: 100%; }
#one { background-color:gray; float:left; height:100%; padding:5px; width:25%; }
#two { height: 100%; background-color:pink;}
</style>
</head>
<body>
<div id="one">
<div id="two">
<p>content ... content ... content</p>
</div>
</div>
...but a horizontal scrollbar will appear. Also, if the content is squeezed, the parent background will not extend past 100%. This is perhaps the padding example you presented in the question itself.
You can achieve the illusion that you're seeking through images and additional divs, but CSS alone, I don't believe, can achieve pixel perfection with that height requirement in place.
If you are only concerned with horizontal spacing, then you can make all child block elements within a parent block element "inset" by a certain amount by giving the parent element padding. You can make a single child block element within a parent block element "inset" by giving the element margins. If you use the latter approach, you may need to set a border or slight padding on the parent element to prevent margin collapsing.
If you are concerned with vertical spacing as well, then you need to use positioning. The parent element needs to be positioned; if you don't want to move it anywhere, then use position: relative and don't bother setting top or left; it will remain where it is. Then you use absolute positioning on the child element, and set top, right, bottom and left relative to the edges of the parent element.
For example:
#outer {
width: 10em;
height: 10em;
background: red;
position: relative;
}
#inner {
background: white;
position: absolute;
top: 1em;
left: 1em;
right: 1em;
bottom: 1em;
}
If you want to avoid content from expanding the width of an element, then you should use the overflow property, for example, overflow: auto.
Simply apply some padding to the parent element, and no width on the child element. Assuming they're both display:block, that should work fine.
Or go the other way around: set the margin of the child-element.
Floatutorial is a great resource for stuff like this.
Try this:
.parent {padding:Npx; display:block;}
.child {width:100%; display:block;}
It should have an Npx space on all sides, stretching to fill the parent element.
EDIT:
Of course, on the parent, you could also use
{padding-top:Mpx; padding-bottom:Npx; padding-right:Xpx; padding-left:Ypx;}

Resources