1

I have a very simple structure and layout.

There is a #header and a #footer with a #body-container between them. The #header is position: fixed.

The #body-container has a margin-top: 3.1em to make room for the #header, which has height: 3em, but that doesn't work the way I thought it would. Even though the #header is not a child of the container, it won't render above the container (i.e. in the margin).

Why doesn't the #header render in the top margin of the #body-container? How can I achieve the desired effect?

You can fiddle with it here, and the code is here for reference:

HTML:

<body>
    <div id="header">
    </div>
    <div id="body-container">
        <div class="left">
        </div>
        <div class="right">
        </div>
    </div>
    <div id="footer">
    </div>
</body>

CSS:

div {
    margin-bottom: 0.1em;
    background-color: #99ccff;
}

#body-container {
    background-color: white;
    margin-top: 1.1em;
    width: 20em;
    height: 35em;
}

.left {
    width: 2.5em;
    height: 100%;
    float: left;
}

.right {
    margin-left: 2.6em;
    height: 100%;
}

#header {
    background-color: #99eeee;
    position: fixed;
    height: 3em;
    width: 20em;
    z-index: 1;
}

#footer {
    height: 3em;
    width: 20em;
}
kdbanman
  • 10,161
  • 10
  • 46
  • 78
  • You used "position: fixed", which essentially glues that element to the screen in the position it originally rendered in. – Marc B Jun 23 '14 at 20:13
  • 1
    Just change `margin-top: 3.1em` to `padding-top: 3.1em` http://jsfiddle.net/spK9T/1/ – Turnip Jun 23 '14 at 20:15
  • @Marc That's true. I'm wondering why the `#header` originally renders *below* the `#body-container` margin, rather than *within* it. – kdbanman Jun 23 '14 at 20:16
  • 1
    Correct link --> http://jsfiddle.net/spK9T/3/ – Turnip Jun 23 '14 at 20:19
  • @3rror404 Ok, [that worked](http://jsfiddle.net/spK9T/2/). Can you or someone else tell my why the margin of the `#body-container` affects the `#header`, while the padding doesn't? I don't see why either should. – kdbanman Jun 23 '14 at 20:20
  • possible duplicate of [Margin on child element moves parent element](http://stackoverflow.com/questions/1762539/margin-on-child-element-moves-parent-element) – T J Jun 24 '14 at 17:48
  • @TilwinJoy Yes, the questions are about the same effect, margin collapse. However, mine is discussing sibling nodes, while that one is discussing parent-child nodes. – kdbanman Jun 24 '14 at 18:01

2 Answers2

1

That's an interesting effect. It seems that the #body-container pushes the edge of the body up and it affects the placement of the fixed header. This is happening because the header is set without coordinates. Add the following rule set to place the header at the very top of the page:

#header {
    top: 0;
    left: 0;
}

Another way to prevent the margin of the #body-container affect the placement of the header is to set the padding on the body element. The rule set below will eliminate the effect of the margin-top of the #body-container and keep the fixed #header aligned with the other content, if coordinates are NOT used for the #header.

body {
    padding: 20px;
}
DRD
  • 5,557
  • 14
  • 14
  • That essentially works: http://jsfiddle.net/spK9T/4/ What do you mean when you say that the `#body-container` "pushes the edge of the body up"? The main document `` is being affected? – kdbanman Jun 23 '14 at 20:43
  • This is a very interesting phenomenon. Personally, that's the first time I've encountered something like this, because I always use fixed positioned element with coordinates. If you try setting the padding on the body and eliminate the coordinates, then it'll prevent the margin-top of the #body-container messing with the positioning of the #header. To see that effect you'll need to remove the top: 0 and left: 0 coordinates from the #header rule set. Interesting. – DRD Jun 23 '14 at 22:54
  • Neat, you're right. Setting the `body`'s padding to *anything* except zero corrects the issue completely. The behavior is actually specified by the w3c, so it's expected. It's called margin collapse, and I link to it in my answer below. – kdbanman Jun 23 '14 at 23:05
  • Good example. More folks should give this one a vote up. It's really bizarre that coordinate-free fixed blocks and their adjacent sibling's top margins can collapse. – DRD Jun 23 '14 at 23:35
1

The effect is called "margin collapse," which is discussed in this thread as well. Margin collapse behavior is specified and expected.

There are a few ways to the desired effect I've learned about since asking. Working jsfiddles are linked:

  1. Add negative margin-top to #header.

    This feels cleanest to me.

  2. Move the #body-container's margin-top to padding-top.

    This is bound to mess with some of the possible CSS style/layout properties if things get complex, and it does leave a gap between the top of the page and the header.

  3. Exactly specify the #header coordinates with top and left properties.

    See @DRD's answer.

  4. Add any nonzero padding to the body.

    Again, see @DRD's answer.

Community
  • 1
  • 1
kdbanman
  • 10,161
  • 10
  • 46
  • 78