Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use CSS to position a fixed variable height header and a scrollable content box?

Tags:

css

I'm trying to make a web page with a fixed header and a scrollable content area. This is trivial when the header has a known height but I'm struggling to find a solution for when the header is fluid.

The layout I want is:

--------------
head
--------------
content
--------------

where "head" is whatever height its content needs it to be and "content" has no minimum height but will reach a maximum height of the bottom of the viewport before becoming scrollable.

Is this possible these days in pure CSS? I'm targeting IE8+.

To clarify what I want, here is what I would do if I knew the height of the header:

<!DOCTYPE html>
<html>
    <head>
        <style type="text/css">

body {
    margin: 0;
}

#head {
    background: yellow;
    height: 20px; /* I can't rely on knowing this. */
}

#content {
    background: red;
    position: absolute;
    top: 20px; /* here also */
    bottom: 0;
    width: 100%;
    overflow: auto;
}

        </style>
    </head>
    <body>
        <div id="head">some variable height content</div>
        <div id="content">
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
        </div>
    </body>
</html>
like image 438
David Roe Avatar asked Jun 20 '11 16:06

David Roe


People also ask

How do I fix the position of the header and footer in HTML?

Answer: Use CSS fixed positioning You can easily create sticky or fixed header and footer using the CSS fixed positioning. Simply apply the CSS position property with the value fixed in combination with the top and bottom property to place the element on the top or bottom of the viewport accordingly.


6 Answers

Assuming by "fixed" you mean position:fixed, I don't think it's possible in pure CSS, as position:fixed takes the element out of the document flow.

However, it should just take a line or two of JavaScript to get what you want. Something like this (untested, only for example purposes, will need syntax tweaked to actually work):

var height = document.getElementById("head").offsetHeight;
document.getElementById("content").style.marginTop = height + 'px';

Something like that should get you the rendered height of the fixed <div> and set the content <div>'s margin accordingly. You'll also need to explicitly set a background color on the fixed <div>, otherwise the content will appear to bleed into the fixed one when scrolling.

like image 128
Shauna Avatar answered Oct 09 '22 09:10

Shauna


Here's a solution, but it's a cheat. Basically, you have a duplicate header element, to push down the content, under the fixed position one:

<div class="outer">
    <div class="header">Header content goes here</div>
    <div class="header-push">Header content goes here</div>
    <div class="content">
        ...
    </div>
</div>
like image 26
Eric Avatar answered Oct 09 '22 07:10

Eric


I did a combination of both the accepted and Eric's answer. An empty div is used to push the content bellow "head". The width of this div is set by jQuery when window.onresize is fired:

function resizeHeader() {
    $(".header-push").height($(".header").height());
}
$(document).ready(resizeHeader);
$(window).resize(resizeHeader);

See this jsFiddle for more info.

like image 35
geca Avatar answered Oct 09 '22 08:10

geca


This javascript will take the variable height of a fixed header and set the top margin of the content to flow underneath. Just call page load.

<script type="text/javascript">
    function AdjustHeight() {
        var height = document.getElementById("fixedheader").offsetHeight;
        document.getElementById("content").style.marginTop = height + 'px';
    }    
</script>
like image 31
Keith Avatar answered Oct 09 '22 07:10

Keith


The easiest way is to simply replace position: fixed; with position: sticky;

header {
  position: sticky;
  top:0;
  background-color: red;
  color: #fff;
}

main {
  background-color: green;
  color: #fff;
  min-height: 150vh;
}

DEMO: https://jsfiddle.net/4zndve6p/

like image 38
DimChtz Avatar answered Oct 09 '22 09:10

DimChtz


Here is a full code example of Shauna's solution above for the lazy/confused/people who can't get this working.

<html>
<head>

<style>
#FreezePaneHeader {
    position: fixed; top:0; left: 0; width: 100%;background-color: gray;
}

#FreezePaneBody {
    margin-top: 30px;
} 
</style>

 <script type="text/javascript">        
        function resizeFreezePane()
        {
            var height = document.getElementById("FreezePaneHeader").offsetHeight;
            document.getElementById("FreezePaneBody").style.marginTop = height + 'px';
        }

        //Resizes content to allow static header with dynamic height on postbacks
        function pageLoad() {
            resizeFreezePane();
        }

        var addEvent = function (elem, type, eventHandle) {
            if (elem == null || typeof (elem) == 'undefined') return;
            if (elem.addEventListener) {
                elem.addEventListener(type, eventHandle, false);
            } else if (elem.attachEvent) {
                elem.attachEvent("on" + type, eventHandle);
            } else {
                elem["on" + type] = eventHandle;
            }
        };

        //also when page is resized.
        addEvent(window, "resize", resizeFreezePane);

    function GenerateLorem(ele){
        var x = document.getElementById(ele);
        x.innerHTML = x.innerHTML + "<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur pretium euismod leoquis convallis. In ornare suscipit massa eu commodo. Pellentesque vel nibh volutpat, commodo libero et, 

porta tellus. Duis eu fringilla arcu. Etiam imperdiet lectus diam, dignissim viverra dui hendrerit id. Fusce condimentum bibendum tincidunt. Aenean fringilla felis elit, et dapibus ante tempus at. Phasellus quis dolor odio.</p>";
        resizeFreezePane();
        }
    </script>
</head>

<body>
<div id="FreezePaneHeader">Frozen Page Header</div>
<div id="FreezePaneBody">
<button id="ButtonAddText" onclick="GenerateLorem('FreezePaneHeader'); return false;">Add more header text</button>
<button id="ButtonAddText" onclick="GenerateLorem('FreezePaneBody'); return false;">Add more body text</button>
<p id="PageContents"></p>
</div>
</body>

</html>
like image 29
Ravendarksky Avatar answered Oct 09 '22 08:10

Ravendarksky