Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 363
user801347 Avatar asked Feb 09 '19 18:02

user801347


People also ask

Why is position sticky not working?

The 2 most common culprits why position: sticky; might not work are: You haven't defined top: 0;, bottom: 0;, left: 0 or something similar One of the parents of your sticky element has overflow (x or y) set to hidden, scroll or auto. For me it was the first one. For me overflow-x: hidden on the body was the reason - thanks for your hint!

What is the sticky behavior when using bottom position relative 0?

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).

How does CSS position sticky really work?

The reason for that is that when an element is given the position: sticky style, the sticky item’s container is the only area in which the sticky item can stick. The item doesn’t have any elements to float over since it can only float over sibling elements, which, being an only child, it doesn’t have. How CSS Position Sticky Really Works!

Does sticky position the element to the top or bottom?

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.


2 Answers

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.

like image 124
Temani Afif Avatar answered Nov 15 '22 06:11

Temani Afif


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

like image 38
YourPalNurav Avatar answered Nov 15 '22 08:11

YourPalNurav