Home > Software engineering >  Keep page header always centered in viewport when scrolling horizontally
Keep page header always centered in viewport when scrolling horizontally

Time:10-22

Given this code:

header {
  text-align: center;
}
/* no necessary, only using it to simulate a big table */
p.text {
  width: 20rem;
  height: 50rem;
}
<html>

<body>
  <header>
    <h1>Page Title</h1>
    <details>
      <summary>Click Me</summary>
      <p>More information</p>
      <p>Even more stuff</p>
    </details>
  </header>
  <table>
    <tr>
      <td><p >Lorem</p></td>
      <td><p >ipsum</p></td>
      <td><p >dolors</p></td>
      <td><p >itamet</p></td>
      <td><p >consectetura</p></td>
      <td><p >dipiscinge</p></td>
      <td><p >litsed</p></td>
      <td><p >doeiusmod</p></td>
    </tr>
    <tr>
      <td><p >Lorem</p></td>
      <td><p >ipsum</p></td>
      <td><p >dolors</p></td>
      <td><p >itamet</p></td>
      <td><p >consectetura</p></td>
      <td><p >dipiscinge</p></td>
      <td><p >litsed</p></td>
      <td><p >doeiusmod</p></td>
    </tr>
  </table>
</body>

</html>

I would like the contents of <header> to stay centered when scrolling horizontally, but scroll out of view when scrolling vertically.

I've tried position: sticky; left: 0; with several variations of display, margin, etc, to no avail. The closest I've gotten it to work is this:

    header {
      text-align: center;
      position: fixed;
      top: 0;
      left: 0;
      width: 100vw;
      z-index: -1;
    }
    table {
      margin-top: 7rem;
    }

but that breaks when opening the <details> element and doesn't work at all in Firefox Mobile.

Trying to stick to a "pure", semantic solution. Not against a little Javascript, but would rather not use a framework.

Thanks in advance for your help.

CodePudding user response:

For position sticky to work horizontally (which would seem to be what is wanted here) the containing element must be bigger than the thing you want to stick.

Also, you have to be cautious of the overflow settings for ancestor elements. See position:sticky is not working for further discussion.

<!doctype html>
<html>
<head>
<title>sticking</title>
<style>
body {
  margin: 0;
  overflow: visible;
  width: fit-content;
}
header {
  width: 100vw;
  text-align: center;
  position: sticky;
  left: 0px;
}
/* no necessary, only using it to simulate a big table */
p.text {
  width: 20rem;
  height: 50rem;
}

</style>
</head>
<body>
  <header>
    <h1>Page Title</h1>
    <details>
      <summary>Click Me</summary>
      <p>More information</p>
      <p>Even more stuff</p>
    </details>
  </header>
  <table>
    <tr>
      <td><p >Lorem</p></td>
      <td><p >ipsum</p></td>
      <td><p >dolors</p></td>
      <td><p >itamet</p></td>
      <td><p >consectetura</p></td>
      <td><p >dipiscinge</p></td>
      <td><p >litsed</p></td>
      <td><p >doeiusmod</p></td>
    </tr>
    <tr>
      <td><p >Lorem</p></td>
      <td><p >ipsum</p></td>
      <td><p >dolors</p></td>
      <td><p >itamet</p></td>
      <td><p >consectetura</p></td>
      <td><p >dipiscinge</p></td>
      <td><p >litsed</p></td>
      <td><p >doeiusmod</p></td>
    </tr>
  </table>
</body>

Note: I don't have mobile Firefox to test this on. Let me know whether it works there or not.

CodePudding user response:

Adding a scroll element wrapping the table would work but that would push the scroll bar towards the bottom.

header {
    text-align: center;
  }
  /* no necessary, only using it to simulate a big table */
  p.text {
    width: 20rem;
    height: 50rem;
  }
  .scroll {
    overflow-x: scroll;
  }
<header>
            <h1>Page Title</h1>
            <details>
                <summary>Click Me</summary>
                <p>More information</p>
                <p>Even more stuff</p>
            </details>
        </header>
        <div >
            <table>
                <tr>
                    <td><p >Lorem</p></td>
                    <td><p >ipsum</p></td>
                    <td><p >dolors</p></td>
                    <td><p >itamet</p></td>
                    <td><p >consectetura</p></td>
                    <td><p >dipiscinge</p></td>
                    <td><p >litsed</p></td>
                    <td><p >doeiusmod</p></td>
                </tr>
                <tr>
                    <td><p >Lorem</p></td>
                    <td><p >ipsum</p></td>
                    <td><p >dolors</p></td>
                    <td><p >itamet</p></td>
                    <td><p >consectetura</p></td>
                    <td><p >dipiscinge</p></td>
                    <td><p >litsed</p></td>
                    <td><p >doeiusmod</p></td>
                </tr>
            </table>
        </div>

CodePudding user response:

Simplest solution is to put the header outside the element you are trying to scroll horizontally.

<body>
  <header ></header>
  <table ></table>
</body>

note: don't scroll the body element, this causes all child elements to behave unexpectedly, use .fixed { position: fixed; } .scroll { overflow-x: scroll }

  • Related