2

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">
      <a href="#">Menu</a>
      <div id="child">...</div>
   </li>
   <li>...</li>
   <li>...</li>
</ul>

Consider that the code represents a horizontal menu. Which appears somewhat like this:

screenshot

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:

screenshot

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.)

its_me
  • 10,998
  • 25
  • 82
  • 130
  • Please provide CSS and browser used as well, from html example your warping block div into inline a - this can have unpredictable results, i would try to adding display:block to a. As is i cant seem to repeat your issue. – drk Dec 20 '12 at 15:52
  • @drk Was working on it as soon as I realized the explanation wasn't enough. Please check my updated question. :) – its_me Dec 20 '12 at 16:00

2 Answers2

3

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.

JaredMcAteer
  • 21,688
  • 5
  • 49
  • 65
  • but that doesn't answer the OP's question: why does the parent expand if the child is removed from the flow of the document? – Matanya Dec 20 '12 at 15:29
  • JaredMcAteer and @Matanya Please see my updated question. I have added a fiddle and steps to reproduce the problem. Thanks! – its_me Dec 20 '12 at 16:01
0

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).

Community
  • 1
  • 1
its_me
  • 10,998
  • 25
  • 82
  • 130
  • Also to note you example on jsfiddle didnt have position for submenu container, adding following css reduced the size of first li to expected size : #channels-menu-item-container{ position:absolute; } – drk Dec 21 '12 at 11:20
  • @drk I think you are mistaken. I used `position:absolute;` on the class `.collapse` which targets the same element as `#channels-menu-item-container`, or am I missing something? – its_me Dec 21 '12 at 14:09
  • aah, it get removed when the menu is expanded - which was the state i did the testing, expanding the main menu after opening sub may be your goal that i didnt factor in. – drk Dec 21 '12 at 15:31
  • @drk Looks like something's wrong with JS Fiddle (or the bootstrap library that it loads), it's fine on the live site; the class shouldn't get removed. Anyway, thanks for letting me know. :) **EDIT:** The issue is caused by the old bootstrap library that JS fiddle loads. Everything should be fine with the latest version of bootstrap. Updated the fiddle: http://jsfiddle.net/bdtt3/1/ – its_me Dec 21 '12 at 16:09