0

I am writing a very simple web-app, which should have a long scrollable list of items, with a fixed header at the top of the viewport offering functionality to filter the items. The header should always be visible, and crucially, its height can be dynamic (because some of its content will be populated dynamically).

Assume I have the following HTML structure

<html>
  <body>
    <div class="root scrollableContentAncestor">
      <div class="app scrollableContentAncestor scrollableContentParent">
        <header class="fixedHeader">
          <h1>My web app</h1>
          ...more HTML here...
        </header>
        <ul class="scrollableContentBelowFixedHeader">
          <li>...</li>
          <li>...</li>
          <li>...</li>
          ...
        </ul>
      </div>
    </div>
  <body>
</html>

I have made it work for a header with static height, by using the position:fixed + padding-top approach as follows.

CSS stylesheet:

.fixedHeader {
  position: fixed;
  width: 100%;
  z-index: 1;
}

.scrollableContentBelowFixedHeader {
  /* Offset all the fixed header's vertical distances. */
  padding-top: 9.75rem; /* A constant value, or a calc() of constant values. */
}

This works for static height headers, but because you have to specify a static height for padding-top of the scrollable block, it is not satisfactory for dynamic height headers. As an added mild annoyance, the vertical scroll bar covers full viewport, i.e. including the fixed header, not just the scrollable block.

How can I make this work for a dynamic height header?

Anders Rabo Thorbeck
  • 1,126
  • 3
  • 18
  • 28

1 Answers1

0

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.

Anders Rabo Thorbeck
  • 1,126
  • 3
  • 18
  • 28