Fixing fixed headers

by nathanlogan

HTML

<header>
  <h2>Fix Fixed Headers</h2>
  <button>Toggle fixed position <span>(Status: "ON")</span></button>
</header>
<section>

  <div>
    <p>Fix applied by default.</p>
    <p>To demonstrate the problem:</p>
    <ol>
      <li>Click the button to toggle fixed position to "<strong>ON</strong>".</li>
      <li>Press [TAB] many times, to traverse down the links until at least 4 or 5 of them have scrolled up to be hidden underneath the header.</li>
      <li>Use [SHIFT] + [TAB] to traverse the links backwards.</li>
      <li>Notice that many of the selected links are hidden behind the fixed header.</li>
      <li>Now toggle it back off, and try the same test with the fix applied.</li>
    </ol>
  </div>

  <ol>
    <li><a href="//abc.xyz">Main section content</a></li>
    <li><a href="//abc.xyz">Main section content</a></li>
    <li><a href="//abc.xyz">Main section content</a></li>
    <li><a href="//abc.xyz">Main section content</a></li>
    <li><a href="//abc.xyz">Main section content</a></li>
    <li><a href="//abc.xyz">Main section content</a></li>
    <li><a href="//abc.xyz">Main section content</a></li>
    <li><a href="//abc.xyz">Main section content</a></li>
    <li><a href="//abc.xyz">Main section content</a></li>
    <li><a href="//abc.xyz">Main section content</a></li>
    <li><a href="//abc.xyz">Main section content</a></li>
    <li><a href="//abc.xyz">Main section content</a></li>
    <li><a href="//abc.xyz">Main section content</a></li>
    <li><a href="//abc.xyz">Main section content</a></li>
    <li><a href="//abc.xyz">Main section content</a></li>
    <li><a href="//abc.xyz">Main section content</a></li>
    <li><a href="//abc.xyz">Main section content</a></li>
    <li><a href="//abc.xyz">Main section content</a></li>
    <li><a href="//abc.xyz">Main section content</a></li>
    <li><a href="//abc.xyz">Main section content</a></li>
    <li><a href="//abc.xyz">Main section content</a></li>
    <li><a href="//abc.xyz">Main section content</a></li>
  ...

CSS

/*
 NO CSS NEEDED FOR THE FIX
  - all of the below is just to show the problem and provide some style
*/



/* Below JUST for demonstrating the problem with fixed */
header.showProblem {
  position:fixed;
  width:100%;
}
header.showProblem button span {
  display: inline;
  font-weight: bold;
}
header.showProblem + section {
  padding-top: 135px;
  box-sizing: content-box !important;
}

/* Below JUST for "style" */
* {
  font-family: Roboto, Helvetica, sans-serif;
  color: #333;
  letter-spacing: 1px;
}
body {
  margin: 0;
  padding: 0;
}
header {
  background: #c7d4e8;
  padding: 20px;
  text-align: center;
  font-size: 1.5em;
}
header button span {
  display: none;
}
h2 {margin: 0; padding: 0;}
section {
  padding: 10px 0;
  background: #eee;
}
div {
  padding: 0 20px;
  border-bottom: 1px solid #ddd;
  font-size: 0.8em;
}
div li {
  margin-bottom: 5px;
  line-height: 1.3;
}
li {
  line-height: 1.8;
}

JavaScript

const setFixedHeader = (selectorHeader, selectorContent, listenForResize = true) => {
  const viewH = Math.max(document.documentElement.clientHeight, window.innerHeight || 0)
  const eleH = $(selectorHeader).outerHeight(true)
  
  $(selectorContent).css({
    height : (viewH - eleH) +"px",
    overflowY: "auto",
    // this is so our height means something
    boxSizing: "border-box"
  })
  
  if (listenForResize) {
  	$(window).on('resize', () => setFixedHeader(selectorHeader, selectorContent, false))
  }
}

setFixedHeader('header', 'section')






// BELOW: NOT PART OF THE SOLUTION!
// (just demonstrates the problem)

$('button').click(() => {
	$('header').toggleClass('showProblem')
})