Личная боковая панель в дизайне flexbox

Как сделать боковые панели в макете святого Грааля, сделанные с помощью flexbox, липкими? то есть. сторона в стороне и nav html должна перестать прокручиваться дальше, когда достигнет последний элемент. Я пробовал несколько способов, но добился небольшого успеха.

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;
   }

Ответ 1

Предполагая, что я действительно понял, чего вы пытаетесь достичь, это должно быть в соответствии с тем, что вы ищете. Мясо раствора заключается в определении трех состояний или трех условий для позиционирования элемента. В порядке появления:

  • Если мы прокрутили начало боковой панели, но пока не дошли до конца боковой панели. Минус высоты самого меню.
  • Если мы прокрутили конец боковой панели минус высота этого меню.
  • Если значение прокрутки страницы меньше начальной точки боковой панели. То есть, естественное состояние меню, прежде чем прокручиваться.

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

Ответ 2

Как насчет использования нового CSS3 position: sticky в элементах nav и aside?

Недостатком этого подхода является то, что он не поддерживается Internet Explorer, но он требует нулевого Javascript.

Я сделал это изменение здесь:

body {
   /*font: 24px Helvetica;*/
   background: #999999;
  }

  #main {
		position: relative;
   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;
   }

#main > nav, #main > aside {
	position: sticky;
	top: 0;
	height: 100%;
}

  header, footer {
   display: block;
   margin: 4px;
   padding: 5px;
   min-height: 100px;
   border: 1px solid #eebb55;
   border-radius: 7pt;
   background: #ffeebb;
   }
<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>

Ответ 3

Я взял код из кода и переписал код JS с некоторой логикой, сделанной с боковой панелью по мере необходимости. Надеюсь, это полезно:)

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>