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.

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

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:

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.

Comments

Lock Thread

Login

Add Comment[M ↓   Markdown]()

[Upvotes]()[Newest]()[Oldest]()

![](/images/no-user.svg)

Mohamed Hussain

0 points

6 years ago

![](/images/no-user.svg)

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

![](/images/no-user.svg)

rem

0 points

6 years ago

Any chance you can actually include which browser and OS you’re using?

![](/images/no-user.svg)

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.

![](/images/no-user.svg)

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.

![](/images/no-user.svg)

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.

![](/images/no-user.svg)

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

![](/images/no-user.svg)

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.

![](/images/no-user.svg)

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…​

![](/images/no-user.svg)

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?

![](/images/no-user.svg)

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)