1

Assume, that I have three boxes (divs) on website (see image below):

  • header with logo
  • content with some text
  • footer with contact info

Each box have unique color (in order: yellow, orange and blue) and black border. I would like to website always fills the entire screen, the logo was on the top and the footer was at the bottom. So if there is not enough text in content, content should be extended, so that the footer was on the bottom. And if will be a lot of text in content, slider should appear on the right.

How do this in CSS? Important is that boxes have backgrounds. I found many solutions, but none doesn't work properly with backgrounds.

example

veeveeoor
  • 205
  • 1
  • 2
  • 11
  • http://stackoverflow.com/questions/5189238/how-to-make-a-footer-fixed-in-the-page-bottom/5189304#5189304 – Chris Sobolewski Dec 18 '13 at 17:19
  • 1
    I believe you are asking for 'fixed headers and footers'? – DA. Dec 18 '13 at 17:21
  • I update example image. This should explain everything. – veeveeoor Dec 18 '13 at 17:32
  • You should really look at the highest upvoted comment on the question I linked earlier. AFAIK it exactly answers the question. – Chris Sobolewski Dec 18 '13 at 19:43
  • 1
    Chris, it does not answer the OP. 1) It does not provide a header or header offset, per the very clear diagram in the OP's question. 2) It does not include a central area that actually expands accordingly, as it always runs under the footer. It is not easily adapted to do this either. This is fine if you aren't actually displaying per the OP bottom-middle diagram, with intervening padding or a content-area-sized object. 3) It actually does not work at all, due to what is most likely a typo. See my paste of the (corrected) code into jsfiddle, here: http://jsfiddle.net/syndicatedshannon/mRbQd/ – shannon Dec 18 '13 at 23:18

2 Answers2

2

Solution Explained

  • The black box in your diagram gets min-height 100%, is the scrolling container, and is position relative, to allow child positions to be respective to it.
  • The red box in your diagram is actually composed of 2 boxes:
    • one for your dynamically-sized content; this has sufficient top and bottom padding to make room for your header and footer, and force the scrolling container to expand
    • one for the background; this is position absolute, with top and bottom position specified relative to the black box, its parent.
  • The yellow and blue boxes in your diagram can be position: absolute, top: 0 and bottom: 0, respectively... or however you choose to position them.

Here's a fiddle of it: http://jsfiddle.net/syndicatedshannon/F5c6T/

And here is another version with explicit viewport elements just to clarify, matching colors, and borders added to replicate the OP graphics (although per the OP the black border is actually the window).

Sample HTML

<html>
    <body>
        <div class="background"></div>
        <div class="content"></div>
        <div class="header"></div>
        <div class="footer"></div>
    </body>
</html>

Sample CSS

html { position: absolute; height: 100%; left: 10px; right: 10px; overflow: auto; margin: 0; padding: 0; }
body { position: relative; width: 100%; min-height: 100%; margin: 0; padding: 0; }
.background { position: absolute; top: 120px; bottom: 120px; background-color: red; width: 100%; }
.content { position: relative; padding: 120px 0; }
.header { position: absolute; top: 10px; height: 100px; width: 100%; background-color: yellow; }
.footer { position: absolute; bottom: 10px; height: 100px; width: 100%; background-color: cyan; }

Also note that this assumes you cannot rely on CSS3 yet.

shannon
  • 8,664
  • 5
  • 44
  • 74
  • In response to your "the black box is the screen" comment, then add an element. Although HTML or BODY tags will work fine. – shannon Dec 18 '13 at 17:35
  • 1
    Can you explain on code? Assume that footer and header height is 100px. – veeveeoor Dec 18 '13 at 17:36
  • You mean something like this: html { position: relative; min-height: 100%; } div#header { height: 100px; position: absolute; top: 0; } div#content { top: 100px; bottom: 100px; } div#footer { height: 100px; position: absolute; bottom: 0; } – veeveeoor Dec 18 '13 at 17:47
  • I added a fiddle link to the answer above. I don't think the example you gave in your comment just above this will work. That would fix the header and footer to the top and bottom of the html height, yes, but nothing would ever cause the HTML element to need to scroll. Instead the #content child with a fixed top and bottom would become a scrolling area. – shannon Dec 18 '13 at 18:12
  • Let me know if you have any questions, although the working fiddle probably makes it pretty clear. – shannon Dec 18 '13 at 18:16
  • Also added the gaps per your initial diagrams, just to make it clear that it does exactly what you are looking for, although the added 10px spacing everywhere makes the CSS a little less clear; – shannon Dec 18 '13 at 18:25
  • How will you get the border around the viewport? – Aust Dec 18 '13 at 18:38
  • Aust, he said the border is actually the screen. However, you can see it is quite easy, as it already exists as a white border. Additionally, it's easy enough to add additional containing boxes for MORE borders :) – shannon Dec 18 '13 at 18:44
  • Can you fiddle it? Your CSS is very good but I can't get the border. I'm learning here too. =) – Aust Dec 18 '13 at 18:47
  • I did fiddle it. It's up there. Here, I'll embolden it. :) Oh, I'm sorry, you mean fiddle the border. Hey! Ask your own question, I'm working for points here ;). Oh, Okaaaay... – shannon Dec 18 '13 at 18:48
  • Here you go, Aust. I also moved all the functional CSS to DIVs just to help clarify what is going on. There shouldn't be anything special about the HTML and BODY elements, but unfortunately they are treated differently by some older browsers. http://jsfiddle.net/JJpyf/10/ – shannon Dec 18 '13 at 19:09
  • Very nice solution; however, putting the header after the content might not be very screen-reader friendly. – aebabis Dec 18 '13 at 20:32
  • Acbabis: it isn't necessary, of course, I simply wished to avoid confusing matters with z-index or additional divs. – shannon Dec 18 '13 at 22:42
  • acbabis: also, it might actually be more screen reader friendly, depending on the content. It also may improve SEO in many of the same cases. :) – shannon Dec 18 '13 at 23:31
0

If you're only targeting modern browsers, you can use calc()

body, html {
    height: 100%;
    padding: 0;
    margin: 0;
}

.header {
    height: 50px;
    margin-bottom: 10px;
}

.footer {
    height: 100px;
    margin-top: 20px;
}

.content {
     min-height: calc(100% - 50px - 10px - 100px - 20px);
}

The drawback is that you need to know the header and footer sizes and they need to be fixed. I don't know any way around this without using Javascript. For slightly less modern browsers, you can use border-box to get the same effect as above.

body, html {
    height: 100%;
    padding: 0;
    margin: 0;
}

.header {
    height: 50px;
    margin-bottom: 10px;
    z-index: 5;
    position: relative;
}

.footer {
    height: 100px;
    margin-top: -100px;
    z-index: 5;
    position: relative;
}

.content {
    box-sizing: border-box;
    padding: 60px 0 120px 0;
    margin-top: -60px;
    min-height: 100%;
    z-index: 1;
    position: relative;
}

Lastly, here is the JS solution:

$(function(){
    $('.content').css('min-height',
            $(window).height()
            - $('.header').outerHeight()
            - $('.footer').outerHeight() - $('.content').marginTop()
            - $('.content').marginBottom());
});

EDIT: My JS solution assumed border-box and no border. This solution should be more robust:

function setContentSize() {
    $('.content').css('min-height',
            $(window).height()
            - $('.header').outerHeight()
            - $('.footer').outerHeight()
            - ($('.content').outerHeight()
                - $('.content').innerHeight()));
}

$(setContentSize);
$(window).on('resize', setContentSize);
aebabis
  • 3,657
  • 3
  • 22
  • 40