How To Build Multiple Stacking Sticky Sidebars with Pure CSS and Bootstrap 4

PostedDecember 12, 2019 8.4k views Development

While this tutorial has content that we believe is of great benefit to our community, we have not yet tested or edited it to ensure you have an error-free learning experience. It's on our list, and we're working on it! You can help us out by using the "report an issue" button at the bottom of the tutorial.

In this tutorial you’ll work on building multiple sticky sidebars that stack without using any JavaScript.

We’ll discuss:

  • Multiple Stacking Sticky Sidebars.
  • Reasons you would want to do this.
  • Issues developers encounter doing it with JavaScript or plugins.
  • The technique with CSS3 (position: sticky).
  • That same technique but with pure CSS.
  • Bunch of Bootstrap 4 Demos with Sticky Sidebars.

Multiple Stacking Sticky Sidebars

I’m talking specifically about this design pattern where there’s a single sidebar with multiple sticky content in it:

https://codepen.io/ncerminara/pen/zaGZGK

There’s a couple reason why you might implement this. To name a few:

  • Make sub-navigation easily accessible.
  • Highlight your content in your sidebar more as a user scrolls.
  • Increase your ad impressions, clicks, and page views.

The JavaScript Way

There are many plugins for doing this:

It’s also possible to write a small script for it yourself, but I know most people likely use plugins.

How the JavaScript Works

The general idea is your script or plugin will do something like this with JavaScript:

  1. Calculate offset of a position: relative; element from top of window on scroll.
  2. When that element’s offset is or is about 0, calculate the position (left, top, or right) of that element against the window.
  3. Switch it to position: fixed; with the calculated top, left, or right.
  4. Optionally, have your JS redo these calculations when it reaches the bottom of its parent.
  5. Switch it to position: absolute; and position it at bottom of the container.

It’s not too bad of work, but it’s definitely a lot to juggle even if you have a plugin trying to figure this all out for you.

Content Jumping

When you switch from position: relative; to position: fixed; the height is removed from the parent element. This means there might be a “jump” up of content.

Check out this demo:

https://codepen.io/ncerminara/pen/qKdmMz

Width 100% vs Width Auto

If the element you want to be “sticky” is currently position: relative; and responsive to the container (width: 100%) and then you swap to position: fixed, you’ll get an element that is 100% of the window or at width auto depending on your CSS.

Here’s our demo again. This time watch the width of the “sticky” element.

https://codepen.io/ncerminara/pen/qKdmMz

Finally, if you have a complicated website, with multiple sticky sidebars on a single page, that’s a lot of JavaScript calculations happening on scroll. CSS-Tricks has a great tutorial explaining through this issue.

Here’s a codepen showing that off, forked from Chris Coyier’s Codepen in that article:

https://codepen.io/ncerminara/pen/mKyvQr

This is no big secret if you’ve been paying attention to CSS3. You can now make any element essentially behave this way with pure CSS. It’s easy.

You just need to have the CSS applied and at least one direction property which is usually the top:

.make-me-sticky {
    position: sticky;
    top: 0;
}

Now, all elements with the class will be sticky to the top of the container, all the way to the bottom.

Below are some demos with Bootstrap 4:

Basic Sticky Sidebar with Bootstrap 4

https://codepen.io/ncerminara/pen/eKNROb

Browser Support

Like anything fun with CSS3 its browser support is not consistent. If you can afford to have IE users not have a sticky elements, it’s perfect. You wouldn’t have to worry about any complex fallback because it’ll just not implement “stickiness”.

/* Cross-Browser Support */
.make-me-sticky {
    position: relative; /* I am the fallback */

    /* Give it everything you got! (use an auto prefixer...) */
    position: -webkit-sticky;
    position: -moz-sticky;
    position: -ms-sticky;
    position: -o-sticky;
    position: sticky;

    top: 0; /* Required  */
}

Stacking Sticky Sidebars without JavaScript

Now let’s use CSS3 thing with a clever technique to have a dynamic stacking sticky sidebar design pattern.

To reiterate, our goal is to:

  • Have a sticky sidebar.
  • Space out a bunch of them to show multiple items sticky separately.
  • Not use JavaScript.
  • Keep it simple.

Multiple Stacking Sticky Sidebar Demo with Pure CSS

First, here’s a demo of it working in action. This is 100% CSS:

https://codepen.io/ncerminara/pen/VdLmoe

How it Works

We know how to use CSS sticky and that it just affixes an element to the top and the bottom of it’s container based on scroll position.

So all we need to do, is add a bunch of containers evenly split and put sticky content inside of them. See this blueprint of what we want to create with them marked container 1, container 2, container 3, and container n:

Multiple Sticky Sidebars

An easy trick to simulate the equal heights would be using position: absolute;. Here’s some sample code:

/* "TITLE HERE" from above */
.title-section {
    width: 100%;
    height: auto
}


/* "CONTENT" From Above */
.content-section {

     /* size of my container minus sidebar width */
    width: calc(100% - 300px);

    /* Estimated height of largest sidebar in case of short content */
    min-height: 800px;
}

/* SIDEBAR */
.sidebar-section {
    position: absolute;
    right: 0;
    top: 0;
    width: 300px;
    height: 100%; /* Super important! */
}

/* "SIDEBAR CONTAINER" in the blueprint */
.sidebar-item {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 25%;

    /* Position the items */
    &:nth-child(2) { top: 25%; }
    &:nth-child(3) { top: 50%; }
    &:nth-child(4) { top: 75%; }
}

Then, the HTML:

<article>
    <div class="container-fluid">
        <div class="col-md-12">

            <div class="title-section">
                <h1>TITLE HERE</h1>
            </div>

            <div class="inner-guts">


                <div class="content-section">
                    <h2>Content Section</h2>
                </div>


                <div class="sidebar-section">

                    <div class="sidebar-item">
                        <h3>Item 1</h3>
                    </div>
                    <div class="sidebar-item">
                        <h3>Item 2</h3>
                    </div>
                    <div class="sidebar-item">
                        <h3>Item 3</h3>
                    </div>
                    <div class="sidebar-item">
                        <h3>Item 4</h3>
                    </div>

                </div>


            </div>
        </div>
    </div>
</article>

And finally a demo:

https://codepen.io/ncerminara/pen/zaGoPm?editors=1100#0

Next, Let’s Make it Sticky

Now, to make it sticky we just need that CSS property in each of the sidebar-items. So, add these lines of code:

.make-me-sticky {
    position: sticky;
    top: 0;
}
<!-- Repeat this -->
<div class="sidebar-item">
    <div class="make-me-sticky">

    </div>
</div>

...

...

We’re just using position: absolute; to build the layout we want then position: sticky; to do all our work. Here is the blueprint live:

https://codepen.io/ncerminara/pen/VdLmoe

Issues you’ll face

Here are some issues that you might face with this approach:

  • The content container is shorter than the sidebar.
  • The sidebar items height are taller than their individual container.
  • You have different quantities than 4 for your sidebar.

Nothing is perfect, but this is a pretty great technique. You’ll have to adjust the CSS here for your individual use case, but it’s not a bad solution at all given we have no JavaScript.

Make it a Helper Library / Mixin for Different Quantities

For dynamically changing content, I would do something like this in CSS. You could probably make a smarter SASS / LESS Mixin though:

.sidebar-item {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
}
.has-4-items .sidebar-item {
    height: 25%;
    &:nth-child(2) { top: 25%; }
    &:nth-child(3) { top: 50%; }
    &:nth-child(4) { top: 75%; }
}
.has-3-items .sidebar-item {
    height: 33.333333%;
    &:nth-child(2) { top: 33.333333%; }
    &:nth-child(3) { top: 66.666666%; }
}
.has-2-items .sidebar-item {
    height: 50%;
    &:nth-child(2) { top: 50%; }
}

Bootstrap and Flexbox

In this example you’ll notice we used calc of exactly 300px for the sidebar width. This is because ad units are that size, so it’s become the standard on the web for a sidebar.

With Bootstrap 4, their grid system is flexbox by default. The biggest for most users are columns of equal height by default with Bootstrap 4.

Check out this demo showing that:

https://codepen.io/ncerminara/pen/EjqbPj

Now, let’s leverage that with sticky sidebars.

Instead of doing the calc trick, we’ll just use a Bootstrap 4 grid system. The only thing we need to update on our code is to make sure the .make-me-sticky has left and right padding that matches your column gutters.

So the default setup will be:

.make-me-sticky {
    position: sticky;
    top: 0;

    /* For Bootstrap 4 */
    padding: 0 15px;
}

Check out the demo below:

https://codepen.io/ncerminara/pen/zaGZGK?editors=1100

Multiple Stacking Sticky Sidebars

Let’s do this in multiple columns at different quantities with just CSS.

https://codepen.io/ncerminara/pen/VdLpzd

Conclusion

This was a tutorial on how to use position: sticky; with Bootstrap 4 to create multiple sticky sidebars or multiple, multiple sticky sidebars.

0 Comments

Creative Commons License