1

Below is the code snippet and if run it, you can see the header element does not stick. I have looked at the at following questions. “Position: sticky;” not Working CSS and HTML and CSS: 'position: sticky' not working when 'height' is defined among many others but it did not help..

Here is my code.

<body style="margin: 0">
  <div id="header" style="height: 50px;width: 100%;position: sticky;top: 0px;background-color: rgb(33, 150, 243);">
    <div>header contents</div>
    <div>header contents</div>
  </div>
  <div id="container" style="position: absolute; top: 50px; left: 0px; width: 100%; background: #ddd;">
    <div style="height: 1000px;">
      <div>some contents</div>
      <br>
      <div>some contents</div>
      <br>
      <div>some contents</div>
      <br>
      <div>some contents</div>
      <br>
      <div>some contents</div>
      <br>
    </div>
  </div>
</body>

Also I noticed if I remove position: absolute from the container div, the sticky starts to work properly. Any help will be appreciated.

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
Ajay Goyal
  • 21
  • 1
  • 2

3 Answers3

8

Adding border to the body will show you the issue:

<body style="margin: 0;border:2px solid red;">
  <div id="header" style="height: 50px;width: 100%;position: sticky;top: 0px;background-color: rgb(33, 150, 243);">
    <div>header contents</div>
    <div>header contents</div>
  </div>
  <div id="container" style="position: absolute; top: 50px; left: 0px; width: 100%;">
    <div style="height: 1000px;">
      <div>some contents</div>
      <br>
      <div>some contents</div>
      <br>
      <div>some contents</div>
      <br>
      <div>some contents</div>
      <br>
      <div>some contents</div>
      <br>
    </div>
  </div>
</body>

As you can see the height of the body is defined by the sticky element thus there is no sticky behavior. if you remove the positon:absolute you will make the element part of the flow thus the body height will increase and you have a sticky behavior

<body style="margin: 0;border:2px solid red;">
  <div id="header" style="height: 50px;width: 100%;position: sticky;top: 0px;background-color: rgb(33, 150, 243);">
    <div>header contents</div>
    <div>header contents</div>
  </div>
  <div id="container" style=" top: 50px; left: 0px; width: 100%;">
    <div style="height: 1000px;">
      <div>some contents</div>
      <br>
      <div>some contents</div>
      <br>
      <div>some contents</div>
      <br>
      <div>some contents</div>
      <br>
      <div>some contents</div>
      <br>
    </div>
  </div>
</body>

The issue isn't the position:absolute element but the height of the containing block (parent container) of the sticky element. This one need to be big enough (at least bigger than the sticky element) to have a sticky behavior.

Increasing the body height and keeping the absolute element will also fix this:

<body style="margin: 0;border:2px solid red;height:200px;">
  <div id="header" style="height: 50px;width: 100%;position: sticky;top: 0px;background-color: rgb(33, 150, 243);">
    <div>header contents</div>
    <div>header contents</div>
  </div>
  <div id="container" style="position: absolute; top: 50px; left: 0px; width: 100%;">
    <div style="height: 1000px;">
      <div>some contents</div>
      <br>
      <div>some contents</div>
      <br>
      <div>some contents</div>
      <br>
      <div>some contents</div>
      <br>
      <div>some contents</div>
      <br>
    </div>
  </div>
</body>

Another related answer where you can find more examples of how sticky works: Why element with position:sticky doesn't stick to the bottom of parent?

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • know of any questions discussing `sticky` in the context of offsetting inline elements with `translateY`? – oldboy Oct 08 '20 at 22:23
  • i edited my question. what i am doing is wrapping each letter of a `p` in a `span`, then `translateY` offsetting each letter incrementally (i.e. first letter is offset by `100%`, second letter `200%`, third `300%`, and so on) and i want them to stick to the top of the container as one scrolls the element to eventually form the whole word/sentence/etc, but cant figure out how to do it – oldboy Oct 08 '20 at 22:26
  • @oldboy I guess it deserve a question ;) It would be easier to make a full answer instead of simple comment (more users can also think about the issue and give potential solutions) – Temani Afif Oct 08 '20 at 22:30
  • ok, posted a Q. i did my best to word it as well as i could. [HERE](https://stackoverflow.com/questions/64271747/position-sticky-while-offsetting-inline-elements) is the quesiton – oldboy Oct 08 '20 at 23:01
0

As mentioned above, since the body height is not set, the header's position will never change from relative to fixed (this is what sticky does - see (https://www.w3schools.com/cssref/pr_class_position.asp).

If you needed to keep the container absolutely positioned but can't/don't want to define the body height, you could use position:fixed instead of position:sticky for the header id, and include z-index:1 so that it appears over the container:

<body style="margin: 0">
  <div id="header" style="height: 50px;width: 100%;position: fixed;top: 0px;background-color: rgb(33, 150, 243); z-index:1;">
    <div>header contents</div>
    <div>header contents</div>
  </div>
  <div id="container" style="position: absolute; top: 50px; left: 0px; width: 100%; background: #ddd;">
    <div style="height: 1000px;">
      <div>some contents</div>
      <br>
      <div>some contents</div>
      <br>
      <div>some contents</div>
      <br>
      <div>some contents</div>
      <br>
      <div>some contents</div>
      <br>
    </div>
  </div>
</body>
abr
  • 73
  • 6
0

In this case,if you want to set height of div to specific value, you can set min-height:1000px for body element and set z-index for div#header to 1.

<body style="margin: 0;min-height: 1000px">
<div id="header"
     style="height: 50px;width: 100%;position: sticky;top: 0;background-color: rgb(33, 150, 243);z-index:1">
    <div>header contents</div>
    <div>header contents</div>
</div>
    <div id="container" style="position: absolute; top: 50px; left: 0; width: 100%; background: #ddd;">
        <div style="height: 1000px;">
            <div>some contents</div>
            <br>
            <div>some contents</div>
            <br>
            <div>some contents</div>
            <br>
            <div>some contents</div>
            <br>
            <div>some contents</div>
            <br>
        </div>
    </div>


</body>
MN. Vala
  • 129
  • 1
  • 6