2

I have a page that overflows the viewport both horizontally and vertically, and I'd like to sticky a nav so that it is always at the top and horizontally centered.

Right now, I can get sticky top working, but the centering does not work. Can anyone help?

body {
  text-align: center;
}

#header {
  background-color: yellow;
  width: max-content;
  position: sticky;
  top: 0;
  left: 50%;
  translate: -50%
}

#container {
  background-color: black;
  color: white;
  width: 200vw;
  height: 200vh;
  display: flex;
  justify-content: center;
  align-content: center;
  flex-direction: column;
}
<div id="header">
  I should always be at the top and centered
</div>
<div id="container">
  <span>
  I am extremely large and wide
  </span>
</div>

CodePen: https://codepen.io/hbchin/pen/bGjpQLJ

TylerH
  • 20,799
  • 66
  • 75
  • 101
user1834200
  • 152
  • 1
  • 13
  • sticky top:0 + margin:auto & max-content is perfectly fine, why are you dealing with left and translate full off after effects ? Make it simple ;) – G-Cyrillus Dec 30 '22 at 20:14
  • Actually if your sticky content is always at the top, you don't need sticky in the first place, just set it to fixed position. – TylerH Dec 30 '22 at 20:53
  • I'm honestly surprised I can't find a duplicate for this. The root problem is "how to keep an element horizontally centered even with a scrollbar." – TylerH Dec 30 '22 at 21:09

3 Answers3

1

After doing some digging I found this:

Why is my element not sticking to the left when using position sticky in css?

Essentially, it's not sticking because the body is automatically expanding to the width of the size of the very big box.

Putting it in an inline-block container will make the width not auto-expand to children, and thus allow sticking behavior.

So this works:

body {
    text-align: center;
}

#header {
    background-color: yellow;
    width: max-content;
    position: sticky;
    top: 0;
    left: 50%;
    translate: -50%
}

#container {
    background-color: black;
    color: white;
    width: 200vw;
    height: 200vh;
    display: flex;
    justify-content: center;
    align-content: center;
    flex-direction: column;
}

#whole-thing {
    display: inline-block;
}
<div id="whole-thing">
    <div id="header">
        I should always be at the top and centered
    </div>
    <div id="container">
        <span>
            I am extremely large and wide
        </span>
    </div>
</div>
user1834200
  • 152
  • 1
  • 13
0

Unlike position: sticky and vertical positioning, left: 50% isn't a dynamic positioning option; it just sets the initial position. A horizontal scrollbar will still cause it to move, so that it remains "50% from the left edge".

To achieve a fixed left-right position, add a header container with position: fixed around your header, and within that, your header div can get auto margins:

body {
  text-align: center;
  max-width:100vw;
  overflow:scroll;
}

/*added*/
#headercontainer{
  position:fixed; 
  width:100vw;
  left:0;
  top:0;
}
#header {
  background-color: yellow;
  width: max-content;
  /*left: 50%;*/ /*Removed*/
  margin:auto;/*added*/
}

#container {
  background-color: black;
  color: white;
  width: 200vw;
  height: 200vh;
  display: flex;
  justify-content: center;
  align-content: center;
  flex-direction: column;
}
<div id="headercontainer"> <!-- added -->
    <div id="header">
    I should always be at the top and centered
    </div>
</div>
<div id="container">
  <span>
  I am extremely large and wide
  </span>
</div>
TylerH
  • 20,799
  • 66
  • 75
  • 101
Heya
  • 104
  • 7
  • 1
    Hm. I do need the `position:sticky` behavior where the item initially sits in its own div in the flow of content and sticks when you scroll past it. (So at the very top of the page, the top element is not within the black box., but is its own row with a height.) – user1834200 Dec 30 '22 at 21:56
-1

You mean something like this?:

<div id="header-container">
  <div id="header">
    I should always be at the top and centered
  </div>
</div>
<div id="container">
  <span>
    I am extremely large and wide
  </span>
</div>

body {
  text-align: center;
}

#header-container {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 20px;
  overflow: auto;
  background-color: yellow;
}

#header {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: max-content;
}

#container {
  background-color: black;
  color: white;
  width: 200vw;
  height: 200vh;
  display: flex;
  justify-content: center;
  align-content: center;
  flex-direction: column;
}
eMi
  • 5,540
  • 10
  • 60
  • 109
  • This answer would benefit from an explanation. Walls of code without explanation are often not useful to readers. – TylerH Dec 30 '22 at 20:50