In this tutorial, we’ll discuss the sticky value of the CSS position property.

This tutorial is closely related to the HTML and CSS basics article series.

A sticky lollipop in a plate Photo by Unsplash

In CSS, position: sticky used to be not supported or not correctly implemented or not implemented in a standardized way in a number of browsers.

That’s why it took quite some time for this value on the position property to start getting some traction and being accepted and used as part of a front-end web developer’s toolbox.

However, these days have been over for quite some time, and if you haven’t already had experience with position: sticky, read on.

How does position:sticky work in CSS?

For the CSS position:sticky to work meaningfully, we need to define the area to which an element should stick.

This means that besides us setting our chosen element to position:sticky, we also need to “define” the container to which this sticky element will stick.

Luckily, this is as simple as can get: as soon as we’ve defined an element to have position:sticky, we’re immediately setting that element’s closest ancestor as the sticky container.

This sticky container is the part of the page in which a sticky item can have this fixed-like behavior, meaning: area of the page where the sticky item can behave as if it is a fixed element.

Keep in mind that the sticky container still behaves the same as all the regularly positioned elements in our HTML structure. If we scroll the sticky parent, eventually, it will scroll out of view, and with it, the sticky element will scroll out as well.

Hoever, as long as the sticky container is in the viewport, the sticky element will appear as though it is fixed on the page, and its specific position will depend on the top, right, bottom and left properties’ values - if we choose to define them.

Long story short: the sticky element is “a prisoner” of its sticky container.

A simple position:sticky CSS example

In this example, we’ll have a sidebar as a sticky container, and an orange-colored div as a sticky element. This is an approach that websites sometimes use to show information that user “must” see as they scroll, such as some promotional content on a website.

The HTML for our simple position:sticky example is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<main>
  <h2>Here goes the main content</h2>
</main>
<aside>
  <div>
    <h2>This is a non-sticky div</h2>
  </div>
  <div id="stick">
    <h2>This is a sticky div</h2>
  </div>
  <div>
    <h2>This is another non-sticky<br>
      HTML element</h2>
  </div>
</aside>

The CSS for our example is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
div {
  min-height: 300px;
}
body {
  display: flex;
  width: 800px;
  margin: 0 auto;
}
main {
  width: 500px;
  height: 4000px;
}
aside {
  width: 300px;
  height: 2000px;
}

main,
aside {
  padding: 20px;
  margin: 20px;
  border: 1px solid gray;
}

#stick {
  background: orange;
  position: sticky;
  top: 20px;
}

Here’s the live demo of our simple position:sticky example demonstrating the sticky behavior.

Note that we’re setting the top position to 20px so that the sticky element doesn’t get “glued” to the very top of its sticky wrapper (i.e the aside element).

However, this means that the third div in the aside element will get scrolled under the sticky and thus for a brief moment (depending on how fast a user is scrolling the page), the heading of the third div will be visible between the top of the viewport and the 20 pixels’ empty area above the sticky div.

There are a number of ways to deal with this glitchy-looking issue, but we will not cover them now. It’s just important to keep in mind that things like the one above are possible, and will occur. The best approach, as with anything related to web design and development, is to test our work, and implement a solution that is suitable for a given scenario.

In other words, sometimes we want to have the exact behavior like the one shown in our simple example of position:sticky. Other times, we’d need to improve the user experience, by, for example, starting our sticky container from top: 0, but then nesting other divs inside of it, to get the same visual effect as if it was moved from the top by 20 pixels - thus getting “the best of both worlds”.