Forum Moderators: not2easy

Message Too Old, No Replies

fixed sidebar navigation

how to eliminate overlap and stuff

         

nyteshade

3:38 pm on Nov 11, 2011 (gmt 0)

10+ Year Member



I am currently deconstructing my website fixed sidebar navigation (some css I borrowed) in an attempt to understand the last bit of borrowed css I use that I never fully comprehended. Most of what I eliminated appearred to be html hacks. So here's what I've got left:


* {
padding: 0;
margin: 0;
}

#left_sidebar {
margin-top: 50px;
position: fixed;
width: 250px;
height: 100%;
background-color: red;
}

#content {
margin: 0 100px 0 255px;
text-align: left;
font-size: 1.3em;
color: #000;
background-color:yellow;
min-width:800px;
}


And here is the html:

<body>
<div id="left_sidebar">
<ul>
<li><a href="testfile.html">a element content</a></li>
<li><a href="testfile.html">a element content</a></li>
<li><a href="testfile.html">a element content</a></li>
</ul>
</div>
<div id="content">
<h1>h1 content of div content</h1>
<p><a href="#one">one</a></p>
<p><a href="#two">two</a></p>
<p><a href="#three">three</a></p>
<h2 id="one">three h2 content of div content</h2>
<p>paragraph element content of div element</p>
<p>paragraph element content of div element</p>
<p>paragraph element content of div element</p>
<h2 id="two">three h2 content of div content</h2>
<p>paragraph element content of div element</p>
<p>paragraph element content of div element</p>
<p>paragraph element content of div element</p>
<h2 id="three">three h2 content of div content</h2>
<p>paragraph element content of div element</p>
<p>paragraph element content of div element</p>
<p>paragraph element content of div element</p>
</div>
</body>


This works BUT when the viewport is resized then the horizontal scroll bar appears and allows the 'content' container to underlap the 'left_sidebar' container.

AND, one reason I included bookmarks here is because when the viewport is resized and a bookmark is clicked then the
response is to move the 'content' container under the left_sidebar instead of where I WANT it to be, that is, to the right of the sidebar.

I think that if I could resolve my width property somewhere that this would fix my bookmark problem too but I'm just guessing and trying anything and everthing with no success.

I understand, or think so, that the fixed property removes the container from the normal document flow but the content property values ignore it anyway when I set the margins, right? So, why when the window is resized does it ignore this? I'd like the 'content' to stay put to the right of the left_sidebar, always. Thanks in advance for corrections, suggestions.

alt131

10:45 am on Nov 13, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi nyteshade, what fun :) - and good on you for "deconstructing" and eliminating hacks. I hope this helps, but note it is a longish because there are several issues producing this behaviour. Also, keep in mind that the observed behaviour is correct (although not desired), and that you are also correct - the issue is the width on div#content.

OK, lets start there. Any viewport that is narrower than the total of margin-left +width +margin-right will generate a horizontal scrollbar. The undesired behaviour you are seeing after the viewport is re-sized is just manually creating that condition. So I'd suggest consider the likely viewport widths of your target audience, and unless you can be sure they will be wider, consider reducing the total width of div#content.

There are two reasons div#content "underlaps" div#left_sidebar. The first is that (as you have identified), position:fixed removes div#left_sidebar from the normal flow so it has no impact on later siblings like div#content. What is important to note is that div#left_sidebar takes its position from the edge of the viewport, while div#content takes its margins from the parent element which is <body>. See a fuller explanation at 9.3.1 Choosing a positioning scheme: 'position' property [w3.org]. However, in summary it means that div#content is drawn as if div#left_sidebar did not exist, even if that means the elements overlap.

The second reason (and what causes div#content to "underlap" rather than overlap) is the z-index. That isn't explicitly stated in the css, so both divs default to auto which is the same as z-index:0. We would ordinarily expect the element later in the HTML to be painted "higher" (closer to the viewer) and therefore "on top" of the earlier element, but that is reversed here because of the "stack context".

First <body> creates the stack context for both divs. However, div#left_sidebar is positioned and that means it creates a stack context for its own descendants. This is explained at 9.9.1 Specifying the stack level: the 'z-index' property [w3.org]. Follow that link, then scroll to the list numbered 1-7. Given <body> is the parent and both divs are sibling children, applying the stack order to your HTML structure produces:
  1. the background and borders of the element forming the stacking context. <--- body
  2. not relevant
  3. the in-flow, non-inline-level, non-positioned descendants. <--- div#content because it is not positioned, has not been removed from the flow (say using float), and as <divs> are block it is "non-inline"
  4. not relevant
  5. not relevant
  6. the child stacking contexts with stack level 0 and the positioned descendants with stack level 0. <--- div#left_sidebar because it is a positioned descendent of <body> and is z-index:auto which = 0, and also the <ul> because div#left_sidebar creates a "child" stack context" for it's own descendants
  7. not relevant
So, div#content is painted at #3 which is below div#left_sidebar at #6 - and so the "underlap"

Whew! ;) Ok, but why the side-ways "jump" when activating the in-page anchors? I find it easiest to see the "why" by setting background-color on the target element. Something like :target {background-color:blue} works in the sample code. Activating the in-page anchor orders the browser to bring the "target" (in this case the <h2>'s) into view. However, when the viewport is narrower than margin-left+width+margin-right the target is wider than the viewport width, so to get the right-hand edge of the <h2> into view (or as much of the target as possible) the document is "scrolled" to the left.

Now recall div#side-bar takes it's position from the viewport edge - not the edge of the document. At the same time other elements are drawn as if it was not present. So although the document has been scrolled left to show as much as possible of the target, div#left_side bar remains "fixed' in place at the left edge of the viewport. div#content is drawn as if div#left_sidebar does not exist, except the stack context/order places it below div#left_sidebar, so it "underlaps" .

I understand, or think so, that the fixed property removes the container from the normal document flow but the content property values ignore it anyway when I set the margins, right? So, why when the window is resized does it ignore this? (my bold)
Hopefully by now you can see the margins are not being ignored. If not, reduce the viewport width until you have a horizontal scrollbar, activate the in-page anchor, then drag the scrollbar fully back to the left - div#content definitely has a margin-left:255px. The trick to understanding is to remember div#content margin is measured from the left edge of <body> - not the left edge of the viewport, while div#left_sidebar is positioned by measuring from the viewport edge and will remain firmly "fixed' in that place regardless of how much the document is scrolled left/right.

What to do? You could do lots of things to try to get more control but I think a better approach is to ask whether you actually require a fixed width, and if so consider the likely viewport width of your target viewers. If it will be less than the total width of div#content, I would consider modifying the design to enable you to reduce the total width.

nyteshade

3:59 pm on Nov 15, 2011 (gmt 0)

10+ Year Member



alt131: Thank you for your detailed reply. I've been doing some considerable head-scratching and re-re-reading of it over the past day or so. I understand now that careful thought should precede building a presentation format (or arbitrarily changing it ;). I've since discovered that the <table> and <img> elements appear to be the primary confounding elements to document width when attempting to work with a position:fixed <div> element.

I'm still experimenting with your explanation and applying differing values to width, min-width, max-width and taking into consideration how the vertical scroll-bar comes to be displayed, ie, when the viewport width is less than the sum of margin-left + width + margin-right. The combinations seem inexhaustible!

Of course I've searched the web for similar examples and found that most pages that use a fixed left sidebar are displaying the 'undesired behavior' so I don't feel so much like the lone-ranger.

Even the grand high wizards at [w3.org ] have allowed pages to exhibit the undesired behavior, so again, I not only feel I'm not alone, but in esteemed company.

Another site that specializes in fixed position element tutorials [limpid.nl ]also appears to ignore the undesired behavior.

I'm assuming that some page designers figure that if user shrinks the viewport to a size that is not workable then making it look unjumbled is pointless.

One person seems to have it figured out at [lokeshdhakar.com ] yet I've been unable to replicate the behavior.

Thanks again for taking some considerable time to reply with such detail. Peace.