skip to Main Content

I have fixed header and footers with a scrollable content in between.
In footer, there is a button that expands a div as overlay between header and footer.

Problem: My div expands between header and footer, but it’s going out of the header. I want it to stay between header and footer and not to overlap them and the content should be scrollable.

Limitations: Footer’s height is not fixed. It would change with content. Header’s height can be fixed. Moreover, I want to keep overlay within footer class due to some code limitation.

What is achieved so far: The div opens as overlay between header and footer but it’s not scrollable, nor it stays between both header and footer. I tried with max-height, it works, but my footer’s height is dynamic and I want it to work with html and css only. No JS/TS to be involved for dynamic footer height

Fiddle link: https://jsfiddle.net/mmtes/61kmthw3/1/

Html:

<div class="wrapper">
  <div class="header">Header</div>
  <div class="content">
    Long middle content.....
    </div>
  </div>
  <div class="footer">
  Footer <a href="#" id="button">Click me</a>
  <div class="footer-wrapper">
  <div id="footer-content">Start of footer content
Long footer content....
</div>
  </div>
</div>
</div>

CSS:

    body { height: 600px; }
#content { background: salmon; display: none; height: 300px; width: 100%; }

html, body {
  height: 100%;
  margin: 0;
}
.wrapper {
  height: 100%;
  display: flex;
  flex-direction: column;
  max-height: calc(100vh - 1.5rem);
}
.header, .footer {
  padding: 10px;
  background: silver;
}

.header
{
  margin-top: 20px;
}


   .content {
        overflow-y: auto;
            min-height: 2.5rem;
            padding: 2.5rem;
            flex-grow: 1;
            position: relative;
        background: pink;
    }
    
    #footer-content { display: none;  background: white; padding: 10px; overflow-y:auto; position: absolute; bottom: 0; margin-bottom: 10px}

.footer-wrapper
{
  position: absolute
}

.footer
{
  position: relative;
}

Javascript:

$(document).ready(function(){
    
    $('#button').click( function(e) {
        
        e.preventDefault(); // stops link from making page jump to the top
        e.stopPropagation(); // when you click the button, it stops the page from seeing it as clicking the body too
        $('#footer-content').toggle();
        
    });
    
    $('#footer-content').click( function(e) {
        
        e.stopPropagation(); // when you click within the content area, it stops the page from seeing it as clicking the body too
        
    });
    
});

2

Answers


  1. Yes, this happens because the position of absolutely positioned elements always orient themselves to the next relatively positioned parent.

    For example, your div.content has positon: relative. If you put your #footer-content inside div.content, the absolute position will be relative to div.content.

    Currently, your #footer-content is a child of div.wrapper and div.wrapper is a child of body. None of them are positioned relatively so #footer-content’s absolute position orient itself to the body.

    To make the #footer-content scrollable, you need to define the top property, too.

    So to understand it, try this:

    • move #footer-content inside div.content
    • add top: 0 to #footer-content css

    Edit:

    Ok, regarding your comments, you should go basically like this:

    .grid {
      display: grid;
      grid-template-rows: max-content 1fr max-content;
      height: 100vh;
    }
    .grid__header {
      grid-area: 1 / 1 / 2 / 2;
      background: blue
    }
    .grid__content {
      background: yellow
    }
    .grid__content,
    .grid__footerWrapper {
      grid-area: 2 / 1 / 3 / 2
    }
    .grid__footer {
      grid-area: 3 / 1 / 4 / 3;
      background: green
    }
    .grid__footerWrapper {
      position: relative;
      height: 100%;
    }
    .grid__footerContent {
      position: absolute;
      top: 0;
      height: 100%;
      overflow-y: scroll
    }
    <div class="grid">
    <div class="grid__header">Header</div>
    <div class="grid__content">Content</div>
    <div class="grid__footer">Footer</div>
    <div class="grid__footerWrapper">
    <div class="grid__footerContent">
    content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>
    </div>
    </div>
    </div>
    Login or Signup to reply.
  2. You can use the footer’s height in calculations to remove it, you also are aware of the header size and the viewport size you can figure out the available height. The only problem is that your footer is not positioned completely at the bottom of the view, but rather at end of the page which may be lower than the view…

    But, if you position the footer-wrapper according to the footer (since footer is position relative) you can use bottom: calc(100%) to make the bottom of the wrapper on top of the footer. Percentage here is using the footer’s height.

    To position the top of the footer-wrapper, you’d use viewport height and substract the size of the header, and the footer. max-height:calc(100vh – 100% – 58px);

    58px = 38px header height + 20px margin top.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search