In the last 2 posts, I wrote about best practises around handling scroll events and then how to combine a sticky nav with smooth scrolling. Both solutions required JavaScript, but there’s solutions right around the corner that allows us to do away with all the JavaScript and let the browser do all the work with a few directions from CSS.
[](https://training.leftlogic.com/buy/terminal/cli2?coupon=BLOG\&utm_source=blog\&utm_medium=banner\&utm_campaign=remysharp-discount)
[READER DISCOUNTSave $50 on terminal.training](https://training.leftlogic.com/buy/terminal/cli2?coupon=BLOG\&utm_source=blog\&utm_medium=banner\&utm_campaign=remysharp-discount)
[I’ve published 38 videos for new developers, designers, UX, UI, product owners and anyone who needs to conquer the command line today.](https://training.leftlogic.com/buy/terminal/cli2?coupon=BLOG\&utm_source=blog\&utm_medium=banner\&utm_campaign=remysharp-discount)
[$49 - only from this link](https://training.leftlogic.com/buy/terminal/cli2?coupon=BLOG\&utm_source=blog\&utm_medium=banner\&utm_campaign=remysharp-discount)
Firstly, I’ve replicated the ffconf2016 site and stripped out all the JavaScript that ran the smooth scrolling and sticky nav.
Then I turn to two CSS properties:
-
position: sticky
- currently [supported](http://caniuse.com/#feat=css-sticky) in Firefox, Chrome and Safari -
scroll-behavior: smooth
- currently [supported](http://caniuse.com/#feat=css-scroll-behavior) in Firefox only
The effect is exactly what I want and the final code is extremely light compared to the original JavaScript version.
[](/images/css-sticky.webm)
Implementation details[](#implementation-details)
The scroll-behavior
is applied directly on the html
element so that it applies to whole window scrolling.
The position: sticky
always catches me out. First I applied it to the navigation element, but this doesn’t work because it’s sticky to it’s parent, and the parent doesn’t have an inner scroll. The html
element is the element that’s scrolling, so the stickiness is applied to the whole header element on the page (that includes the navigation bar).
Since the sticky is applied to the entire header block (which is the height of the page), the top
position for the sticky element, needs to be the height of the header element (100%
) less the height of the navigation (in my case 100px
). So I’m going to make use of the excellent CSS calc
value (which is [very well supported](http://caniuse.com/#search=calc)): top: calc(-100% + 100px)
.
The final code is shown below. I’ve only applied it when the navigation is full present, in my case at > 768px
wide, and I’ve had to tweak the header component to use flex box to keep it set to the height of the window (note that this in only specific to my case, it’s likely you wouldn’t need this).
@media all and (min-width: 768px) {
html {
scroll-behavior: smooth;
}
#masthead {
position: sticky;
top: calc(-100% + 100px);
/* make sure stick above images */
z-index: 1;
/* tweaks to the ffconf design
to keep the height right */
display: flex;
flex-direction: column;
}
.logo-wrapper {
flex-basis: 85vh;
}
}
[Full working demo here](https://css-smooth-sticky-demo.now.sh/) - currently only Firefox supports both position: sticky
and scroll-behavior
so it’s best viewed there. But you can also see it working nicely (without enhancements) in Chrome and other browsers.
Published 29-Jun 2017 under #code. [Edit this post](https://github.com/remy/remysharp.com/blob/main/public/blog/css-sticky-nav-and-smooth-scroll.md)
Comments
Lock Thread
Login
Add Comment[M ↓ Markdown]()
[Upvotes]()[Newest]()[Oldest]()

Mohamed Hussain
0 points
6 years ago
In MacOS Chrome 59, the header is not coming 100% of the window , making the sticky element hidden on top. [https://uploads.disquscdn.c…;](https://uploads.disquscdn.com/images/27432627dedbd568f8e29e14c7aa0065d5111a55f30259d9b85365e19f32328c.png) [https://uploads.disquscdn.c…;](https://uploads.disquscdn.com/images/8fb0ec19117c88deab0bde94e476aca515a547c95adae5c305241ccba648e1d4.png)

Francesco Bedussi
0 points
6 years ago
The demo doesn’t work as expected, changes in the window height move the header up or down

rem
0 points
6 years ago
Any chance you can actually include which browser and OS you’re using?

Satyajit Sahoo
0 points
6 years ago
Can repro on both Chrome and Firefox on Mac. To repro, just scroll until the header becomes sticky, then resize the browser window.

rem
0 points
6 years ago
Okay, then yes, this a) isn’t what a typical user will do! But moreover b) that’s the existing ffconf CSS having a side effect. It’s only because I adjusted (quickly) the existing site to show a working demo of the CSS props rather than putting together an overly simply "hello world" demo.

Francesco Bedussi
0 points
6 years ago
Windows 8, chrome 59 and firefox 54. It’s a weird behavior… It seems the percentage in top is calculated relative to viewport instead of element.
I managed to get it work extacting #sticky-header from #masthead and applying position: sticky top: 0 directly to it.

rem
0 points
6 years ago
I’ve just tested with latest FF and Windows 10, and the smooth scrolling and sticky nav are working as expected.
If I resize the browser screen (down from full screen) then the placement of the sticky nav is off, but that’s just an artifact of ffconf 2016 CSS that hasn’t been fully adjusted for this demo. i.e. that’s to say: ignore it :)

rem
0 points
6 years ago
Chrome only has sticky header, but not smooth scrolling. I don’t have Windows 8, but I do have Windows 10, so I’ll give this a test tomorrow when I’m back at home. Someone else reported Firefox on Windows not working too.

GehirnmitEi
0 points
6 years ago
I guess you want something like height:calc(100vh - 100px); on .logo-wrapper and remove the flex-basis: 85vh on .logo-sticky…

Mike
0 points
6 years ago
hm, should the demo be working? Sticky header is either too high (so cut off) or way too low (showing log bg) on Firefox (54.0.1 64-bit Win 10). Had not much time so could not find out why really but seems the calc(100% - 100px) is definitely not working?

rem
0 points
6 years ago
I’ll check this out on Windows to see what’s up. Thanks for flagging.
[Commento](https://commento.io)