Why bottom:0 doesn't work with position:sticky?
Asked Answered
A

3

17

I'm trying to understand what css "sticky" does. I can get it to stick to the 'top' of its parent, but not to the 'bottom'

My test code is:

.block {
  background: pink;
  width: 50%;
  height: 200px;
}

.move {
  position: sticky;
  bottom: 0;
}
1111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>
<div class="block">
  AAAA
  <div class="move">
    BBBB
  </div>
</div>
222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>

When I have "move" set to 'top:0' it sticks to the top of the pink block, but when set to 'bottom:0' it seems no longer fixed/sticky.

Allegorical answered 9/2, 2019 at 18:18 Comment(0)
L
28

It's working fine but you will see nothing. Let's have a look at the definition:

A stickily positioned element is an element whose computed position value is sticky. It's treated as relatively positioned until its containing block crosses a specified threshold (such as setting top to value other than auto) within its flow root (or the container it scrolls within), at which point it is treated as "stuck" until meeting the opposite edge of its containing blockref

Give a big margin to the block element to hide it from the screen then start scrolling slowly

.block {
  background: pink;
  width: 50%;
  height: 200px;
  margin-top:120vh;
}

.move {
  position: sticky;
  bottom: 0;
}
<div class="block">
  AAAA
  <div class="move">
    BBBB
  </div>
</div>

You will notice that when your element is showing the BBB is overlapping the AAA until it reach its initial place. This is the sticky behavior when using bottom:0. So our element is kept position:relative and when the container start going out from the screen on the top, it become sticky to its bottom until it reach the opposite edge (the top of the container).

Exactly the same happen with top:0 but in the opposite direction:

.block {
  background: pink;
  width: 50%;
  height: 200px;
  margin-bottom:120vh;
}

.move {
  position: sticky;
  top: 0;
}
<div class="block">
  AAAA
  <div class="move">
    BBBB
  </div>
</div>

So sticky will not position the element to the top or the bottom but it will decide how the element shoul stick in order to be visible when the container will start moving out of the screen.

In order to obtain what you want you need to put your element in the bottom using other properties and keep it bottom sticky.

Here is an example where I place the element at the bottom using flexbox and I specify that I need it to be sticky at the bottom.

.block {
  background: pink;
  width: 50%;
  height: 200px;
  margin-top:120vh;
  display:flex;
  flex-direction:column;
}

.move {
  margin-top:auto;
  position: sticky;
  bottom: 0;
}
<div class="block">
  AAAA
  <div class="move">
    BBBB
  </div>
</div>

So position:sticky will never define the position of the element like we do with absolute or fixed but it will define how the element will stick when there is a scrolling behavior.


Here more examples to better understand:

.block {
  background: pink;
  display:inline-flex;
  vertical-align:top;
  height: 200px;
  max-width:100px;
  flex-direction:column;
  margin:100vh 0;
}

.e1 {
  position: sticky;
  top: 0;
}
.e2 {
  margin-top:auto;
  position: sticky;
  top: 0;
}
.e3 {
  position: sticky;
  top: 20px;
}
.e4 {
  position: sticky;
  bottom: 0;
  margin:auto;
}
.e5 {
  position: sticky;
  bottom: 0;
  top:0;
  margin:auto;
}
.e5 {
  position: sticky;
  bottom: 0;
}
<div class="block">
  <div class="e1">Top sticky</div>
</div>
<div class="block">
  <div class="e2">Top sticky at bottom (nothing will happen :( )</div>
</div>
<div class="block">
  <div class="e3">Top sticky at 10px</div>
</div>
<div class="block">
  <div class="e4">bottom sticky in the middle</div>
</div>
<div class="block">
  <div class="e5">top/bottom sticky in the middle</div>
</div>
<div class="block">
  <div class="e6">bottom sticky at the top (nothing will happen :( )</div>
</div>

Another common mistake with sticky is to forget about the height/width of the element relatively to the one of its parent. If the height of element is equal to the height of the parent (containing block) then logically there will be no sticky behavior because we are already at the opposite edge.

.block {
  background: pink;
  display:inline-flex;
  vertical-align:top;
  height: 200px;
  max-width:100px;
  flex-direction:column;
  margin:100vh 0;
}

.block > div {
  border:2px solid;
} 
.e1 {
  position: sticky;
  top: 0;
}
<div class="block">
  <div class="e1">Top sticky</div>
</div>
<div class="block">
  <div class="e1" style="height:100%">I will not stick</div>
</div>
<div class="block">
  <div class="e1" style="height:80%">I will stick a little ..</div>
</div>
<div class="block" style="height:auto">
  <div class="e1">I will not stick too</div>
</div>

Notice the last case where the height of the parent is set to auto (default value) thus its height will be defined by its content which make the sticky element to have the same height as the containing block and nothing will happen because there is no room for a sticky behavior.

Lablab answered 9/2, 2019 at 20:19 Comment(0)
B
6

Try the following code:

.block {
  background: pink;
  width: 50%;
}

.movetop {
  position: sticky;
  top: 0;
  background: #ccc;
  padding: 10px;
  color: #ae81fe;
  z-index: 1;
  border: 1px solid #777;
}

.movebot {
  background: #ccc;
  padding: 10px;
  color: #ae81fe;
  position: -webkit-sticky;
  position: sticky;
  border: 1px solid #777;
}

.movebot {
  bottom: 0
}
11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>
<div class="block">
  <div class="movetop">
    header
  </div>
  content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>
  <div class="movebot">
    footer
  </div>
</div>
222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>

You can find more about position:sticky on gedd.ski/post/position-sticky

Blowgun answered 9/2, 2019 at 19:38 Comment(0)
H
0

you need to put your sticky element as a last child to archive the sticky bottom behaviour

Hexylresorcinol answered 18/4 at 15:36 Comment(2)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Faddist
This answer worked! The above ones just didn't.Curtate

© 2022 - 2024 — McMap. All rights reserved.