A good[ish] website
Web development blog, loads of UI and JavaScript topics
Before position: sticky
, we had to finesse around with scroll listeners and bounding box measurements, ugh. But position sticky works extremely well and has gained enough browser support to make it a viable option.
As a refresher, these are all the position values we have at the moment:
.foo {
position: static|relative|absolute|fixed|sticky
}
Sticky is just one of them. Below are some examples.
Here’s a pretty standard looking layout with a header, content, and a footer at the bottom. And the header sticks to the top when scrolled down.
The example markup:
<div class="wrap">
<header class="sticky-header">Sticky header</header>
<p>Position sticky demo...</p>
<footer>Footer</footer>
</div>
And the CSS (mandatory lines highlighted):
.wrap {
border: 1px solid #aaa;
height: 400px;
}
.sticky-header {
position: sticky; top: 20px;}
It looks like this:
Position sticky demo...
Element can also be stuck to the bottom of the page.
The below layout uses a "sticky footer" technique, which is a different kind of sticky eh, it pushes the footer all the way down no matter how much content there is, using some flexbox
smartness. Read about the sticky footer technique.
Here’s the HTML, pretty much the same as above:
<div class="wrap">
<header class="header">Sticky header</header>
<p class="content">Position sticky demo...</p>
<footer class="footer">Sticky footer</footer>
</div>
We can set the footer position to sticky and bottom to zero:
.wrap {
display: flex;
flex-direction: column;
height: 400px;
}
.content {
flex: 1;
margin: 20px;
}
.footer {
bottom: 0; position: sticky;}
And the footer stays glued to the bottom:
Position sticky demo...
Table heads (<th>
) can be stuck on place also. The following bit of code is from the website you’re reading atm:
th {
background-color: rgba(255, 255, 255, 0.9);
position: sticky;
top: 0;
}
And this a position sticky compatibility table using it:
Browser | Has support | Notes |
---|---|---|
Chrome | ✅ | Partial support |
Opera | ✅ | Partial support |
Edge | ✅ | Partial support |
Firefox | ✅ | - |
Safari | ✅ | - |
IE | 🚫 | - |
Partial support refers to: "Supported on th
elements, but not thead
or tr
- See Chrome bug"
It’s important to set the background color on the element that will be stuck on its place, or it looks ugly when content scrolls from under it.
Adding an extra wrapping components breaks it, because the stickiness relies on the height of its immediate parent component:
<div class="wrap">
<!-- This wrapper breaks it -->
<div>
<header class="sticky-header">Sticky header</header>
</div>
<p>Position sticky demo...</p>
<footer>Footer</footer>
</div>
Setting overflow: hidden
to the parent element breaks the sticky.
overflow: hidden
is not preventingposition: sticky
from working. But if you set overflow to hidden on any ancestor of your sticky element, then this ancestor element will be the scrolling container for your sticky element. If you switch the overflow value on your ancestor fromhidden
toscroll
and scroll this ancestor (not the window), then you can see that sticky is still working. — StackOverflow answer by chaenu.
You could think position sticky as a hybrid of relative and fixed position, at some point the component’s position changes to fixed, basically the same way we had to do with JavaScript before. Now it’s just built-in.
Sticky has been around for a while now, I found it from a 2015 spec. I remember longingly looking looking up position sticky from caiuse.com, but it was only supported in Firefox, and maybe Chrome if a flag was set. I guess it just took a while for the browsers to implement it, and now that Edge and Opera are based on Chromium, it’s all of a sudden supported everywhere.
Comments would go here, but the commenting system isn’t ready yet, sorry. Tweet me @hiljaa if you want to make a correction etc.