Naguib Ihab
Naguib Ihab

Reputation: 4496

Header turns into fixed when user scrolls

In a web app, I have a header and want to make to keep showing it as the user scrolls, I used position: fixed; to achieve that but the body now starts from the top of the page as opposed to starting from underneath the header.

Originally:

enter image description here

Now:

enter image description here

What I want to do is give the header a fixed position when the user starts scrolling or give it a fixed position but keep that area under the header according to the height of the header (I can currently just add a div with fixed height in there but if the header changes that means i have to change that as well and it feels like a double up)

Fiddle: https://jsfiddle.net/zmp7fbrx/3/

Upvotes: 0

Views: 44

Answers (2)

Michael Coker
Michael Coker

Reputation: 53664

You can do this with a flex layout, then .header can be whatever height, and the rest of the page will automatically adapt.

Set body as the flex parent, and wrap .body and .footer in a new element and set that element to flex-grow: 1 and overflow: scroll so that it will fill the rest of the window, and that element will scroll with overflow, and .header will stay put (mimicking position: fixed).

body {
  display: flex;
  flex-direction: column;
  height: 100vh;
  margin: 0;
}
.header {
  background: black;
  color: white;
}
.body {
  min-height: 200vh; /* you can remove. just for demo purposes */
  flex-grow: 1;
}
main {
  overflow-y: scroll;
}
<div class="header">My menu</div>
<main>
  <div class="body">body</div>
  <div class="footer">footer</div>
</main>

Upvotes: 0

cyr_x
cyr_x

Reputation: 14257

You could just set padding-top of body to the header's height and add top: 0 to header's css.

body {
  padding-top: 50px;
}

.header{
  position: fixed;
  top: 0;
}
.header, .body, .footer {
    width:100%;
    height:200px;
    border:1px solid blue;
}

.header {height: 50px;}
.body {text-align:center;}
.footer {}

.center-horiz{width:200px;height:100px;border:1px solid #666;  display: inline-block;}
<div class="header">My menu</div>
<div class="body">some text2 
    <br>
    <div class="center-horiz">div centered horizontally</div>
</div>
<div class="footer">some text3</div>

Or you could give .body an margin-top of the header's height.

.header{
  position: fixed;
  top: 0;
}
.header, .body, .footer {
    width:100%;
    height:200px;
    border:1px solid blue;
}

.header {height: 50px;}
.body {
  margin-top: 50px;
}
.body {text-align:center;}
.footer {}

.center-horiz{width:200px;height:100px;border:1px solid #666;  display: inline-block;}
<div class="header">My menu</div>
<div class="body">some text2 
    <br>
    <div class="center-horiz">div centered horizontally</div>
</div>
<div class="footer">some text3</div>

Use JavaScript to get the header height on DOM loaded and set margin-top of the .body element. (this also works for dynamic height of the header)

document.addEventListener('DOMContentLoaded', function(e) {
  var headerElement = document.querySelector('.header');
  var bodyElement = document.querySelector('.body');
  
  bodyElement.style.marginTop = headerElement.getBoundingClientRect().height + 'px';
})
.header{
  position: fixed;
  top: 0;
}
.header, .body, .footer {
    width:100%;
    height:200px;
    border:1px solid blue;
}

.header {height: 50px;}
.body {text-align:center;}
.footer {}

.center-horiz{width:200px;height:100px;border:1px solid #666;  display: inline-block;}
<div class="header">My menu</div>
<div class="body">some text2 
    <br>
    <div class="center-horiz">div centered horizontally</div>
</div>
<div class="footer">some text3</div>
Note: If the header as and dynamic height which is changing on window resize, you have to add an resize listener which sets the margin on resize.

Upvotes: 1

Related Questions