Search code examples
javascripthtmlcssreactjs

Does anyone know how the position: sticky property on a sideBar work?


I'm having trouble setting up a Sidebar menu into a sticky position when scrolling on a page. My understanding based on the documentation is that with using the property position: sticky and a distance top: 20px, left: 0px, right:0px...etc it will stick the element. However, that's not happening in my sidebar, what could I be doing wrong?

Image of the sideBar and content with scroll

As you can see in the image, it has a sidebar and a page right next to it. Because of the amount of rows it overflows and generates the scroll option, what I'm trying to do is set the sidebar sticky so it will stay in the same position even though someone scroll.

This is how it looks when I scroll:

Scroll image

I've tried with position:fixed, but it is sending the table to the back of the side bar and disproportioning the size of the table, here is a picture:

Sidebar Fixed

This is my code:

import React, { useState } from 'react'
import { Outlet } from 'react-router-dom'
import Sidebar from '../sidebar/Sidebar'
import SidePages from '../sidebar/SidePages'
import styles from './Layout.module.css'

const Layout = () => {

  return (
    <>
      {/* MAIN PAGE layout... */}
      <Outlet />
      <div className={styles.Slayout}>
        <div className={styles.SsideBar}>
          {/* Sidebar section */}
          <Sidebar/>
        </div>
        {/* Content section */}
        <main className={styles.Smain}>
          <SidePages />
        </main>
      </div>
    </>
  )
}

export default Layout

Now the Sidebar styles :

 .Slayout{
    display: flex;
    /* overflow: hidden; */
}

.SsideBar{
    position: sticky;
    top: 0px;
    width: 300px;
    height: 100vh;
    padding: 20px;
    background-color: #597aa9; 
    color: #597aa9;
    overflow: hidden;
}

.Smain{
    /* position: relative; */
    /*padding: calc(48px * 2); /*calc(48px * 2) // 96px*/
    padding: 12px;  /* padding 12px*/
    /* margin-left: 30; */
    /* margin-left: -900px; */
    background-color: aliceblue;
    width: 90%;  /*full width container // 81%*/
    /* overflow: hidden; */
    height: 100vh;
}

I would appreciate you can teach me how to do it correctly!

Resource I'm using for the position CSS: MCD position documentation


Solution

  • By setting Slayout and SsideBar height to 100vh you have a parent and child which are the same height, so visually there is no way to see it stick when you scroll since we are scrolling past both of those containers.

    If you were to change the height of the Ssidebar in your example to 10vh for testing purposes you can see it will stick but only until 100vh is reached. To get it to stick to the entire length of the page we need to make a few other changes.

    Your CSS becomes this:

    .Slayout{
      position: relative;
        display: flex;
        /* overflow: hidden; */
    }
    
    /* grandparent for sidebar */
    aside {
      position: relative;
    }
    
    /* parent for sidebar */
    .SsideBarParent {
      height: 100%;
    }
    
    .SsideBar{
        position: sticky;
        top: 0px;
        width: 300px;
        height: 100vh;
        padding: 20px;
        background-color: #597aa9; 
        color: #597aa9;
        overflow: hidden;
    }
    
    .Smain{
        /* position: relative; */
        /*padding: calc(48px * 2); /*calc(48px * 2) // 96px*/
        padding: 12px;  /* padding 12px*/
        /* margin-left: 30; */
        /* margin-left: -900px; */
        background-color: #f0ccd9;
        width: 90%;  /*full width container // 81%*/
        /* overflow: hidden; */
        height: auto; /* changed from 100vh */
    }
    

    I have a Codepen to illustrate the changes here: https://codepen.io/zoladesigners/pen/abGeYwa

    First change the height of Smain to auto so the content will determine the height. Then we need to setup the container for the sidebar.

    Think of it like setting up the track for it to stick to. We have our grandparent element that just has a position: relative set to it, then our parent element that is set to be 100% height, and the child is our Ssidebar.

    Now the sidebar will appear to be ever present the height of the screen no matter how long the content is.