Wednesday, March 8, 2017

sticky sidebar in flexbox design

Leave a Comment

How to make the sidebars in the holy grail layout made with flexbox be made sticky? ie. the aside and nav portion of the html should stop scrolling down further when the last element has reached. I tried multiple ways but achieved little success.

HTML:

<body>      <header>header</header>      <div id='main'>         <article>This area has lot of content </article>`         <nav> This nav should not scroll</nav>         <aside>This aside too</div></aside>      </div>      <footer>footer</footer> </body> 

CSS:

body {    /*font: 24px Helvetica;*/    background: #999999;   }    #main {    min-height: 800px;    margin: 0px;    padding: 0px;    display: -webkit-flex;    display:         flex;    -webkit-flex-flow: row;            flex-flow: row;    }    #main > article {    margin: 4px;    padding: 5px;    border: 1px solid #cccc33;    border-radius: 7pt;    background: #dddd88;    -webkit-flex: 3 1 60%;            flex: 3 1 60%;    -webkit-order: 2;            order: 2;    }    #main > nav {    margin: 4px;    padding: 5px;    border: 1px solid #8888bb;    border-radius: 7pt;    background: #ccccff;    -webkit-flex: 1 6 20%;            flex: 1 6 20%;    -webkit-order: 1;            order: 1;    }    #main > aside {    margin: 4px;    padding: 5px;    border: 1px solid #8888bb;    border-radius: 7pt;    background: #ccccff;    -webkit-flex: 1 6 20%;            flex: 1 6 20%;    -webkit-order: 3;            order: 3;    }    header, footer {    display: block;    margin: 4px;    padding: 5px;    min-height: 100px;    border: 1px solid #eebb55;    border-radius: 7pt;    background: #ffeebb;    } 

2 Answers

Answers 1

I have taken up the code from code pen and rewritten the JS code with some logic made with sidebar as required.Hope it is helpful :)

var stickArea = $('aside ul');  var footArea = $('footer');  margin = 10;  offtop = stickArea.offset().top - margin;  offbtm = footArea.offset().top - (margin * 3 + stickArea.height());    $(window).scroll(function() {    topScr = $(window).scrollTop();    if (topScr > offtop && stickArea.hasClass('natural')) {      stickArea.removeClass('natural').addClass('fixed').css('top', margin);    }    if (offtop > topScr && stickArea.hasClass('fixed')) {      stickArea.removeClass('fixed').addClass('natural').css('top', 'auto');    }    if (topScr > offbtm && stickArea.hasClass('fixed')) {      stickArea.removeClass('fixed').addClass('bottom').css('top', offbtm);    }    if (offbtm > topScr && stickArea.hasClass('bottom')) {      stickArea.removeClass('bottom').addClass('fixed').css('top', margin);    }  });
* {    box-sizing: border-box;  }    body {    min-height: 100vh;    display: -webkit-box;    display: -ms-flexbox;    display: flex;    -webkit-box-orient: vertical;    -webkit-box-direction: normal;    -ms-flex-direction: column;    flex-direction: column;  }    .master {    -webkit-box-flex: 1;    -ms-flex-positive: 1;    flex-grow: 1;    display: -webkit-box;    display: -ms-flexbox;    display: flex;    -webkit-box-pack: center;    -ms-flex-pack: center;    justify-content: center;  }    .master .inner-w {    display: -webkit-box;    display: -ms-flexbox;    display: flex;    -webkit-box-orient: vertical;    -webkit-box-direction: normal;    -ms-flex-direction: column;    flex-direction: column;    -ms-flex-preferred-size: 960px;    flex-basis: 960px;  }    .master main {    display: -webkit-box;    display: -ms-flexbox;    display: flex;    -webkit-box-orient: vertical;    -webkit-box-direction: normal;    -ms-flex-direction: column;    flex-direction: column;    -webkit-box-flex: 1;    -ms-flex-positive: 1;    flex-grow: 1;  }    @media (min-width: 900px) {    .master main {      -webkit-box-orient: horizontal;      -webkit-box-direction: normal;      -ms-flex-direction: row;      flex-direction: row;      -webkit-box-pack: justify;      -ms-flex-pack: justify;      justify-content: space-between;    }  }    .master .content {    -ms-flex-preferred-size: 70%;    flex-basis: 70%;    min-height: 2000px;  }    .master aside {    -ms-flex-preferred-size: 350px;    flex-basis: 350px;    -webkit-box-flex: 0;    -ms-flex-positive: 0;    flex-grow: 0;    -ms-flex-negative: 0;    flex-shrink: 0;  }    .master aside .widget-list {    width: 330px;  }    body.sticky-sidebar .master aside .widget-list {    position: fixed;    top: 10px;  }    body {    margin: 0;    background: #add8e6;    padding: 10px;  }    .master {    background: #90ee90;  }    .master .inner-w {    padding: 10px;  }    .master header,  .master .content,  .master aside,  .master footer {    padding: 10px;  }    .master header {    background: #ffc0cb;    min-height: 120px;  }    .master .content {    background: #f5deb3;  }    .master aside {    background: #ffd700;    min-height: 400px;  }    .master aside .widget-list {    background: #d3d3d3;    padding: 10px;  }    .master aside .widget-list .widget {    background: rgba(0, 0, 0, 0.1);    padding: 10px;  }    .master aside .widget-list .widget:not(:first-of-type) {    margin-top: 10px;  }    .master footer {    background: #808080;    min-height: 500px;  }    ul {    margin: 0;    padding: 0;    list-style: none;  }      /** additional Css For Sidebar Logic **/    .master aside .widget-list.fixed {    position: fixed;  }    .master aside .widget-list.bottom {    position: absolute;  }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>  <div class='master'>    <div class='inner-w'>        <header>        <h1>Attempts at a sticky sidebar for squishy and more-complex flex-box layouts - sorta ~ eh?</h1>      </header>        <main>        <div class='content'>          content        </div>          <aside class="">          <ul class='widget-list natural'>            <li class='widget'>              widget 1            </li>            <li class='widget'>              widget 2            </li>            <li class='widget'>              widget 3            </li>              </ul>        </aside>      </main>        <footer>        footer      </footer>      </div>  </div>

Answers 2

Assuming I actually understood what you're trying to achieve, this should be along the lines of what you're looking for. The meat of the solution lies in defining three states or three conditions for positioning the element. In order of appearance:

  1. If we've scrolled past the beginning of sidebar but haven't reached the end of sidebar just yet. Minus the height of the menu itself.
  2. If we've scrolled past the end of sidebar minus the height of it's menu.
  3. If the page scroll value is less than the beginning point of the sidebar. Ie, the natural state of the menu, before we scroll.

if(currentScrollPosition >= sidebarPosition && currentScrollPosition <= threshold) {      $widget.css({top: 10, position:'fixed'}); } else if(currentScrollPosition >= threshold) {     $widget.css({top: threshold, position:'absolute'}); } else if(currentScrollPosition <= sidebarPosition) {     $widget.css({top: 'auto', position:'static'}); } 

http://codepen.io/anon/pen/jByPEJ

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment