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.
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 will stuck in order to be visible when the container will disappear from 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 stuck when there is a scroll 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 will be no room for the sticky behavior.
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
I hope it helps.
Peace.