'position: static;' vs 'position: relative;' when child element is absolutely positioned - css

I am struggling to understand why I need to add position: relative; for a container element when its child element is positioned absolutely (i.e. position: absolute;). Let me explain by example.
Sample HTML Code:
<ul>
<li>...</li>
<li id="parent">
Menu
<div id="child">...</div>
</li>
<li>...</li>
<li>...</li>
</ul>
Consider that the code represents a horizontal menu. Which appears somewhat like this:
The problem is when the value of the position property of #parent is default (i.e. position: static;), its width increases with the width of the #child even though the child element is positioned absolutely, which shouldn't be happening as #child is now out of the flow due to position: absolute;.
Everything falls in place, when I use position: relative; on #parent i.e. its width stays the same, no matter what the size of the #child.
What am I missing here? Why do I need to use position: relative; for something that (I presume) should be the default behavior?
UPDATE: I've created a fiddle to better explain my point. Please take a look.
Steps to reproduce the problem:
In the preview of the fiddle, click on the "Channels" menu, which should slide out its hidden menu-item.
Now, hit F12 key in your browser (Chrome, Safari, or Firefox with Firebug installed), use the inspect tool to inspect the "Channels" menu.
That should immediately point you to the relevant HTML code in the "Elements" tab of the now open Dev Tools or Firebug pane.
Look for the first instance of <li class="float-left top-menu"> inside <ul id="top-navbar"> and hover your mouse over that line. It should show you something like this:
Why is the blue indicator box (i.e. the menu) that big when it should be the size of the red border? Get the idea of what I am saying now?
Now, apply position: relative; on the li (i.e. li.float-left.top-menu { position: relative; } and see the difference for yourself.)

position:relative creates a new containing box from which any absolutely positioned child elements will set their top/left relative to.
position: static will not create a containing box and any child elements that are absolutely positioned will start walking up the DOM tree to find a containing box until it hits the body and use the ancestor it finds for the top/left.
Edit: Sorry I misread your question. I cannot seem to reproduce your description of the problem (see this fiddle). Can you please post the code a minimal test case of your problem.

Okay. I feel stupid now. I was using min-width on the child element, and since the width is pretty much defined, the menu's (i.e. parent's) width expanded as well. Removing min-width cleared all doubts.
And a MUST READ: Absolute Positioning Inside Relative Positioning (also this comment and this answer).

Related

Position:Sticky Not Working in CSS Squarespace

Looking to have a block within the page stick when you scroll down
i.e. https://auratenewyork.com/
(Note: "Fine jewelry designed to be worthy of the women who wear it" text block sticks while the right side still scrolls)
.sticky {
position: sticky;
top: 0px;
}
This is to be a custom CSS code within squarespace. Sticky is just not working and it's wracking my brain. I've even changed the overflow to visible or auto (not hidden). Still doesn't work. Sticky does not even come up highlighted like position:fixed does.
This article goes over how position sticky works. But since you haven't provided any code yet, we can only guess what the issue might be. But please note this part from the article:
While playing with it, I quickly noticed that when an element with a position: sticky style is wrapped, and it is the only element inside the wrapper element, this element, which was defined position: sticky will not stick. [...] When I added more elements inside the wrapper element, it started working.
Hopefully this wil help you.

Weird css width issue?

Or i have been building web pages for too long without a break or something really weird happened.
<div style="background-color:#0F0; margin:5px; height:5px;"></div>
Will result in a long bar of 5 height across the width of the parent div. This should normally not be visible since i gave the div no width.
I tried everything, messed up my whole CSS layout and nothing seemed to get rid of it. I even check some divs of me in that same project that still work like this.
So i opened a new project and just filled in that line above to make sure there wasn't some style setting messing things up. But still there is a green bar showing.
I just want my div to be the size of the text in it.
Again, i could be seeing things but this happened all of a sudden and i'm really clueless...
use display:inline because a div element automatic get the display:block
Your div must have display:block either in your code or inherited from your browser.
change it to display:inline for your desired outcome.
Example here.
http://jsfiddle.net/Hn2xP/1
Break the document flow
By default, div element has it's style display property set to block, what makes it's width to fill the dimensions of parent.
You have two options to make it clip to text, position: absolute or float: left (right works also, depends), as in:
<div style="background-color:#0F0; margin:5px; height:5px; position: absolute;"></div>
or:
<div style="background-color:#0F0; margin:5px; height:5px; float: left;"></div>
For more information, see CSS Floats and/or CSS Positions.
P.S. Bear in mind, that absolute position and/or floated element will remove it from document flow.
span instead of div (display: inline)
If you want to keep the document flow, use span instead of div - it's display property is inline by default, as Blowsie suggested.
<span style="background-color:#0F0; margin:5px; height:5px;"></span>
display: inline-block
There is also an option with display property set to inline-block, but it's compatibility is limited. See CSS Display property information for more details.
<div style="background-color:#0F0; margin:5px; height:5px; display: inline-block;"></div>
Usually a padding issue. Difficult to diagnose without seeing code or example of site error.
try:
div {padding: 0px;}
in your css
By default, the width of a div is auto, meaning that it will fill the entire available content. To have "no width" as you seem to want, set the width to zero explicitly. Or, use one of the other answers...

Positioning things inside a DIV (css-related)

i'll try to make my question really simple 2 you
Basically, i have a DIV, in which i have a picture
What CSS styles should i apply to the picture to position it correctly inside the div
with the condition that everytime i resize the browser window it stays there (inside the div) at the same distance from the borders
Sorry for wasting your time but i'm still a newbie which needs help, thank you alot!
EXAMPLE HERE
code
html
<div id="super_div">
<img id="eyes" src="images/eyes.png" />
</div>
css
that's the question :)
You need to look at absolute positioning. First, you set the containing div's position attribute to relative. For example:
#super_div
{
position: relative;
}
Then, you set the image's position property to absolute and use the top and left or right properties to place it inside the parent div. So, for example:
#eyes
{
position: absolute;
top: 20px;
left: 20px;
}
That's how you make the image keep its current position no matter what. Here's a link to an article explaining the basics. Hope this helps.
This will get it horizontally centered:
margin:auto;
If you need it vertically centered as well then things get a bit more tricky. You can either resort to tables, use a background image (if this is appropriate to your situation) or fiddle with the css. I used the code on http://css-tricks.com/snippets/css/absolute-center-vertical-horizontal-an-image/ as a basis for solving a similar situation I had a while ago..

A depth (z-index) nightmare

The best way to illustrate this question is with...a Fiddle! Before you visit the fiddle, notice there is text behind the grayest element, which is on top of a light gray element that has a border.
There is a main wrapping div (root), and two wrapping divs inside (wrap1 and wrap2). The problem here is that I need the content of wrap2 (highlight) to be behind the content of wrap1 (text), but in front of the background of the root.
This, however, must not change:
The HTML, the elements and wraps should be left untouched. Excluding the order of wrap1 and wrap2 inside root.
The highlight div must keep the absolute positioning.
Styling highlight with background-color is not an option, the existence of highlight is a must.
PS: the italics reference the id's of <div>s in the fiddle example, for whomever was too lazy to visit it.
I was able to display the text in front of the highlight by adding a z-index to text. (Adding the z-index to wrap1 also works.) The trick is to remember that z-index doesn't apply to statically-positioned elements, so you need to give the same div position: relative.
#text {
position: relative;
z-index: 1000;
}
(Large z-index because I've been bitten by IE not respecting low values in the past. May or may not still be an issue. ;-)
z-index can be difficult to grasp. I think somebody already answered your question, but if you want to learn more how they work, this is a pretty comprehensive guide:
http://www.onextrapixel.com/2009/05/29/an-indepth-coverage-on-css-layers-z-index-relative-and-absolute-positioning/
And also, here is a link where you can try out different z-index and how they are affected by different position properties (the main reason for difficulty)
http://tjkdesign.com/articles/z-index/teach_yourself_how_elements_stack.asp
#wrap1{position:absolute;z-index:2;}

IE 6 & IE 7 Z-Index Problem

http://madisonlane.businesscatalyst.com
I'm trying to get the div#sign-post to sit above the div#bottom. This works fine in all browsers except IE6 & IE7. Can anyone see what the problem is here?
Also IE6 is displaying an additional 198px to the top of div#bottom.
Most of the answers here are wrong; some work, but not for the reason they state. Here is some explanation.
This is how z-index should work according to the spec:
you can give a z-index value to any element; if you don't, it defaults to auto
positioned elements (that is, elements with a position attribute different from the default static) with a z-index different from auto create a new stacking context. Stacking contexts are the "units" of overlapping; one stacking context is either completely above the another (that is, every element of the first is above any element of the second) or completely below it.
inside the same stacking context, the stack level of the elements is compared. Elements with an explicit z-index value have that value as a stack level, other elements inherit from their parents. The element with the higher stack level is displayed on top. When two elements have the same stack level, generally the one which is later in the DOM tree is painted on top. (More complicated rules apply if they have a different position attribute.)
In other words, when two elements have z-index set, in order to decide which will show on top, you need to check if they have any positioned parents which also have z-index set. If they don't, or the parents are common, the one with the higher z-index wins. If they do, you need to compare the parents, and the z-index of the children is irrelevant.
So the z-index decides how the element is placed compared to other children of its "stacking parent" (the closest ancestor with a z-index set and a position of relative, absolute or fixed), but it doesn't matter when comparing to other elements; it is the stacking parent's z-index (or possibly the z-index of the stacking parent's stacking parent, et cetera) which counts. In a typical document where you use z-index only on a few elements like dropdown menus and popups, none of which contains the other, the stacking parent of all the elements which have a z-index is the whole document, and you can usually get away with thinking of the z-index as a global, document-level ordering.
The fundamental difference with IE6/7 is that positioned elements start new stacking contexts, whether they have z-index set or not. Since the elements which you would instinctively assign z-index values to are typically absolutely positioned and have a relatively positioned parent or close ancestor, this will mean that your z-index-ed elements won't be compared at all, instead their positioned ancestors will - and since those have no z-index set, document order will prevail.
As a workaround, you need to find out which ancestors are actually compared, and assign some z-index to them to restore the order you want (which will usually be reverse document order). Usually this is done by javascript - for a dropdown menu, you can walk through the menu containers or parent menu items, and assign them a z-index of 1000, 999, 998 and so on. Another method: when a popup or dropdown menu becomes visible, find all its relatively positioned ancestors, and give them an on-top class which has a very high z-index; when it becomes invisible again, remove the classes.
Agree with validator comment - validating usually helps. But, if it doesn't heres a few pointers for z-index in IE:
1) elements who's z-index you're manipulating should be on the same level ie. you should be setting the z-index of #bottom and #body
if this is not feasible then
2) IE sometimes wont apply the z-index correctly unless the elements ou are applying it to have a position:relative. Try applying that property to #bottom and #body (or #signpost)
let me know how that works out
Darko
I just had this problem and the fix I found (thanks to Quirksmode) was to give the direct parent of the node you are trying to set a z-index of it's own z-index that is at less than the z-index of the node you are trying to set. Here is a quick example that should work in IE6
<html>
<head>
<style type="text/css">
#AlwaysOnTop {
background-color: red;
color: white;
width: 300px;
position: fixed;
top: 0;
z-index: 2;
}
#Header {
color: white;
width: 100%;
text-align: center;
z-index: 1;
}
</style>
</head>
<body>
<div id="Header">
<div id="AlwaysOnTop">This will always be on top</div>
</div>
<div id="Content">Some long amount of text to produce a scroll bar</div>
</body>
</html>
Welcome, I solved the problem with:
.header {
position: relative;
z-index: 1001;
}
.content {
position: relative;
z-index: 1000;
}
Looks to me like you have some malformed HTML in there. I tried counting, and perhaps I lost count of the opening and closing tags, but it looks like div#container isn't closed. Try running your page through a validator (such as W3C's HTML Validator, or something) and fixing some of the errors. That's helped me with these sorts of problems in the past. Good luck!
I've recently had an ongoing problem displaying one layer above another. In my case I was programmatically creating two layers in Javascript, one for diaplaying a custom control and one for creating a full screen layer behind it. FF was fine, bu IE displayed the full screen layer always on top of everything else.
After numerous trawls over the interweb, trying everyone's suggestions, the only way I eventually get it working was to remove position: attributes from both layers, and tweak the margin-top: attribute until I got a satisfactory result.
A bit of a hash, but it works and it'll be fine until IE 8 sorts out all of the current bugs......
the only reliable solution is, to put the top elements below in the code and then push them over the other stuff with absolute positioning.
e.g. Wordpress:
put the navigation in the footer file, but still inside the page wrapper.
might also bring some advantages for search engines, because they can directly start with the content, without crawling through the menu first...
UPDATE:
I need to correct myself. While putting the element below and then pushing it over is still the easiest way, there are certain cases when this is not possible in reasonable time. Then you have to make sure that each and every parent element has some kind of positioning and some senseful z-index. Then the z-index should work again even in IE7.

Resources