Личная боковая панель в дизайне 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>