Search code examples
htmlfootersticky-footercss

Box Model - Why does a margin for header screw with sticky footer


I am trying to use the following sticky footer solution from http://ryanfait.com/sticky-footer/

* {
    margin: 0;
}
html, body {
    height: 100%;
}
.wrapper {
    min-height: 100%;
    height: auto !important;
    height: 100%;
    margin: 0 auto -4em;
}
.footer, .push {
    height: 4em;
}
h1 {
    margin-top:1em;  
}
<html>
    <head>
        <link rel="stylesheet" href="layout.css" ... />
    </head>
    <body>
        <div class="wrapper">
            <h1>This header screws with sticky footer</h1>
            <p>Your website content here.</p>
            <div class="push"></div>
        </div>
        <div class="footer">
            <p>Copyright (c) 2008</p>
        </div>
    </body>
</html>

However, as the above snippet demonstrates adding a margin to the <h1> tag results in an undesired scrollbar.

From my basic understanding, the margin should affect only the size of the <h1> tag, which should not affect the size/position of the wrapper (unless there is no space - but clearly there is plenty of space).

EDIT: I am not trying to find a solution, I want to understand what happens. It appears that the margin does not push the <h1> tag down relative to the parent container, but instead it pushes the parent container down together with the <h1> tag. Is this correct, and if yes, why? It seems fairly counter-intuitive.


Solution

  • If you want to manipulate margins/paddings property its always save to add display:inline-block property instead of using inline elements. Add it to your h1 tag and your problem will be fixed.

    Here is a post with some of explanation about this issue Inline elements and padding

    Edit: I have an explanation for you.

    In CSS we have something like "collapsing margins". This is how W3C define it:

    In this specification, the expression collapsing margins means that adjoining margins (no non-empty content, padding, or border areas, or clearance separate them) of two or more boxes (which may be next to one another or nested) combine to form a single margin.

    Margins are adjoining only when:

    • both belong to in-flow block-level boxes that participate in the same block formatting context
    • no line boxes, no clearance, no padding and no border separate them (Note that certain zero-height line boxes are ignored for this purpose.)
    • both belong to vertically-adjacent box edges, i.e. form one of the following pairs:
      • top margin of a box and top margin of its first in-flow child bottom margin of box and top margin of its next in-flow following sibling
      • bottom margin of a last in-flow child and bottom margin of its parent if the parent has 'auto' computed height
      • top and bottom margins of a box that does not establish a new block formatting context and that has zero computed 'min-height', zero or 'auto' computed 'height', and no in-flow children

    If you want to read more about it, here you have some useful links:

    To sum this up, there are many different ways to solve this issue. For example adding display:inline-block , float:left or even border:1px black properties to your wrapper element or h1 tag will fix the "problem". Of course it's not a real problem, in some cases collapsing margins is really useful.