Search code examples
htmlcss

Sticky header input scrolls on input


I have a sticky header with a search input. To ensure anchor tags (<a href='#section'>) doesn't hide the contents behind the top of the header, I added the following CSS.

html {
    scroll-padding-top: 48px
}

However, if the sticky header includes an input, the entire page will scroll when a user types into the input.

Is there a way to preserve the current scroll-padding behavior and prevent the auto-scrolling in when using the input? Preferably with HTML and CSS only.

html {
  scroll-padding-top: 48px;
}

body {
  margin: 0;
}

header {
  position: sticky;
  top: 0;
  background: #eeeeee;
  padding: 8px 16px;
}

main {
  padding: 8px 16px;
}

main article,
main div {
  padding: 32px 0;
  border-bottom: 1px solid lightgray;
}

main div {
  background: #ddddff;
}
<html>

<body>
  <header>
    <input type='text' placeholder='type here, page scrolls' />
  </header>
  <main>
    <article>
      <p><a href='#anchor-point'>click me to skip down to the lower section</a></p>
    </article>
    <article>
      <p>some useless text just to fill up vertical space and allow for scrolling</p>
    </article>
    <article>
      <p>some useless text just to fill up vertical space and allow for scrolling</p>
    </article>
    <div id='anchor-point'>
      I also want to link to here. This section should not get cut off by the sticky header. The entire thing should be visible.
    </div>
    <article>
      <p>some useless text just to fill up vertical space and allow for scrolling</p>
    </article>
    <article>
      <p>some useless text just to fill up vertical space and allow for scrolling</p>
    </article>
    <article>
      <p>some useless text just to fill up vertical space and allow for scrolling</p>
    </article>
  </main>
</body>

</html>

Related post

Editing a sticky input element in Chrome causes the page to scroll to the top — solutions use JS to intercept the input. I'd rather not use JS in this case if possible. Furthermore, the original bug described in that post seems to be fixed.


Solution

  • This may not be a complete answer because it doesn't answer to the question "why?".

    However, if you remove the scroll-padding-top: 48px from the html style, and add scroll-margin-top on the target anchor point you will get the expected result.

    #anchor-point{
     scroll-margin-top: 48px;
    }
    

    It's also possible to avoid using the id selector, with the :target pseudo-class selector

    :target {
     scroll-margin-top: 48px;
    }