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:
- the background and borders of the element forming the stacking context. <--- body
- not relevant
- 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"
- not relevant
- not relevant
- 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
- 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.