Creating a Variable Height "Fixed" Header in CSS with Scrollable Content

How to make a fixed header with variable height

You can do it with pure CSS by nesting position: sticky; elements and give the navbar as position a top: -10px

  1. You set the <nav> to the fixed height of 40px
  2. Then you use nav { position: sticky; top: -10px; }. That will allow the navbar to scroll 10px off the viewport leaving it's height at 30px visible.
  3. To have the content such as links or text not to leave the viewport, you can wrap them inside another element and apply also display: sticky; to it. Now use top: 0; to prevent those elements from leaving the viewport.

nav {
position: sticky;
top: -10px;
height: 40px;
background-color: red;
}

nav > div {
position: sticky;
top: 0;
}


/* for scrolling purpose only */
body {
min-height: 500vh;
margin: 0;
}

/* if you want the text vertically centered */
nav {
display: flex;
align-items: center;
}

nav > div {
display: flex;
align-items: center;
height: 30px;
}
<nav>
<div>Test</div>
</nav>

Fixed always-visible dynamic-height header, with scrollable block underneath

The solution turned out to be setting height: 100% and overflow-y:auto on the scrollable area.
This only works if all the ancestors of the scrollable area also have height: 100%, though.
An additional few fixes are needed to make sure you can't scroll away from header, and that the scrollable area does not leave an unreachable segment at the end, with height equal to the header.

CSS stylesheet:

html, body, .scrollableContentAncestor {
height: 100%; /* Enable the scrollable content `height: 100%` to be interpreted correctly. */
}

.scrollableContentParent {
overflow: hidden; /* Disable scrolling on the fixed header */
display: flex; /* Avoid `overflow: hidden` from interfering with ability to scroll the full length of the scrollable content. */
flex-direction: column; /* As above. */
}

.scrollableContentBelowFixedHeader {
height: 100%; /* All the height that is _not_ taken by the other blocks (i.e. the fixed header). This is the part that enables dynamic height header. */
overflow-y: auto; /* For all the content that does not fit in the part of the block that is visible within the viewpart, make it vertically scrollable. */
}

This allows a dynamic height header. An added bonus is that it also makes the vertical scroll bar display limited within the scrollable area.

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

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.

Fixed height header and scrollable div in variable height div

Set the document's height to 100% with these styles:

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

You can then set the height of the overflow div specifically with:

height: calc(100% - 100px);

Fiddle 1


The more modern way to accomplish this is by making the container a flexbox, with these styles:

height: 100%;
display: flex;
flex-direction: column;

Then use these styles for the header:

height: 100px;
flex: none;

And simply overflow: scroll; for the scrollable content.

Fiddle 2

Fixed header, footer with scrollable content

Something like this

<html>
<body style="height:100%; width:100%">
<div id="header" style="position:absolute; top:0px; left:0px; height:200px; right:0px;overflow:hidden;">
</div>
<div id="content" style="position:absolute; top:200px; bottom:200px; left:0px; right:0px; overflow:auto;">
</div>
<div id="footer" style="position:absolute; bottom:0px; height:200px; left:0px; right:0px; overflow:hidden;">
</div>
</body>
</html>


Related Topics



Leave a reply



Submit