flexbox layout with a fixed sidebar that stays in place

Is there a way to make the sidebars in the holy grail layout sticky using flexbox? Specifically, I want the aside and nav sections of the HTML to stop scrolling down further once the last element is reached. I've tried various methods but with limited success.

HTML:

<body>
     <header>header</header>
     <div id='main'>
        <article>This area has a lot of content </article>`
        <nav> This nav should remain fixed </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;
   }

Answer №1

Have you considered implementing the new CSS3 feature position: sticky on the nav and aside elements?

The drawback of this method is that it lacks support from Internet Explorer, but it eliminates the need for JavaScript.

I applied this modification here:

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>

Answer №2

If I've grasped your intention correctly, this solution should align with what you're seeking. The key lies in establishing three distinct states or conditions for positioning the element. These are outlined as follows:

  1. When we scroll past the beginning of the sidebar but haven't yet reached its end, excluding the menu's height.
  2. Once we scroll beyond the end of the sidebar, factoring in the menu's height.
  3. If the page's scrolling position is before the starting point of the sidebar - essentially representing the menu's default state prior to any scrolling.

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

Answer №3

Learn how to create a sticky sidebar using javascript and css with simple steps below.

$(function(){

var stickySidebar = $('.sticky');

if (stickySidebar.length > 0) {
  var stickyHeight = stickySidebar.height(),
      sidebarTop = stickySidebar.offset().top;
}

// on scroll move the sidebar
$(window).scroll(function () {
  if (stickySidebar.length > 0) {
    var scrollTop = $(window).scrollTop();
            
    if (sidebarTop < scrollTop) {
      stickySidebar.css('top', scrollTop - sidebarTop);

      // stop the sticky sidebar at the footer to avoid overlapping
      var sidebarBottom = stickySidebar.offset().top + stickyHeight,
          stickyStop = $('.main-content').offset().top + $('.main-content').height();
      if (stickyStop < sidebarBottom) {
        var stopPosition = $('.main-content').height() - stickyHeight;
        stickySidebar.css('top', stopPosition);
      }
    }
    else {
      stickySidebar.css('top', '0');
    } 
  }
});

$(window).resize(function () {
  if (stickySidebar.length > 0) {
    stickyHeight = stickySidebar.height();
  }
}); });
body {
  font-family: Arial, Helvetica, sans-serif;
  font-size: 14px;
  line-height: 25px;
  background-color: #361039;
  color: #E2E0DE;
  margin: 0;
}

header {
  display: block;
  background-color: #121325;
  font-size: 24px;
  height: 50px;
  padding: 2%;
  text-align: center;
}

section {
  float: left;
  width: 70%;
  padding: 1%;
  margin-right: 1%;
}

aside {
  float: left;
  width: 25%;
  padding: 1%;
  background-color: #5C255A;
}

.sticky {
  position: relative;
  top: 0;
}

footer {
  display: block;
  clear: both;
  background-color: #121325;
  font-size: 24px;
  height: 300px;
  padding: 2%;
  text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header>This is a header</header>

<section class="main-content">
  <article>
    <h1>This is Paragraph</h1>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis quis nibh gravida, gravida nisl ac, imperdiet sem. Fusce quis malesuada magna. Vivamus dignissim gravida tellus sed pulvinar. Morbi eleifend dolor vel velit viverra aliquam. In pharetra felis non leo congue, id iaculis dui laoreet. Pellentesque accumsan ligula sed nisl eleifend consequat. Proin at orci purus. Praesent dignissim at odio nec fringilla. Nulla lacinia ultricies auctor. Mauris vel diam nunc. Ut lorem arcu, interdum id tortor a, tincidunt vestibulum eros. Vivamus sit amet mattis turpis. Nullam auctor ut velit nec adipiscing. Morbi et vehicula diam.</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis quis nibh gravida, gravida nisl ac, imperdiet sem. Fusce quis malesuada magna. Vivamus dignissim gravida tellus sed pulvinar. Morbi eleifend dolor vel velit viverra aliquam. In pharetra felis non leo congue, id iaculis dui laoreet. Pellentesque accumsan ligula sed nisl eleifend consequat. Proin at orci purus. Praesent dignissim at odio nec fringilla. Nulla lacinia ultricies auctor. Mauris vel diam nunc. Ut lorem arcu, interdum id tortor a, tincidunt vestibulum eros. Vivamus sit amet mattis turpis. Nullam auctor ut velit nec adipiscing. Morbi et vehicula diam.</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis quis nibh gravida, gravida nisl ac, imperdiet sem. Fusce quis malesuada magna. Vivamus dignissim gravida tellus sed pulvinar. Morbi eleifend dolor vel velit viverra aliquam. In pharetra felis non leo congue, id iaculis dui laoreet. Pellentesque accumsan ligula sed nisl eleifend consequat. Proin at orci purus. Praesent dignissim at odio nec fringilla. Nulla lacinia ultricies auctor. Mauris vel diam nunc. Ut lorem arcu, interdum id tortor a, tincidunt vestibulum eros. Vivamus sit amet mattis turpis. Nullam auctor ut velit nec adipiscing. Morbi et vehicula diam.</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis quis nibh gravida, gravida nisl ac, imperdiet sem. Fusce quis malesuada magna. Vivamus dignissim gravida tellus sed pulvinar. Morbi eleifend dolor vel velit viverra aliquam. In pharetra felis non leo congue, id iaculis dui laoreet. Pellentesque accumsan ligula sed nisl eleifend consequat. Proin at orci purus. Praesent dignissim at odio nec fringilla. Nulla lacinia ultricies auctor. Mauris vel diam nunc. Ut lorem arcu, interdum id tortor a, tincidunt vestibulum eros. Vivamus sit amet mattis turpis. Nullam auctor ut velit nec adipiscing. Morbi et vehicula diam.</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis quis nibh gravida, gravida nisl ac, imperdiet sem. Fusce quis malesuada magna. Vivamus dignissim gravida tellus sed pulvinar. Morbi eleifend dolor vel velit viverra aliquam. In pharetra felis non leo congue, id iaculis dui laoreet. Pellentesque accumsan ligula sed nisl eleifend consequat. Proin at orci purus. Praesent dignissim at odio nec fringilla. Nulla lacinia ultricies auctor. Mauris vel diam nunc. Ut lorem arcu, interdum id tortor a, tincidunt vestibulum eros. Vivamus sit amet mattis turpis. Nullam auctor ut velit nec adipiscing. Morbi et vehicula diam.</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis quis nibh gravida, gravida nisl ac, imperdiet sem. Fusce quis malesuada magna. Vivamus dignissim gravida tellus sed pulvinar. Morbi eleifend dolor vel velit viverra aliquam. In pharetra felis non leo congue, id iaculis dui laoreet. Pellentesque accumsan ligula sed nisl eleifend consequat. Proin at orci purus. Praesent dignissim at odio nec fringilla. Nulla lacinia ultricies auctor. Mauris vel diam nunc. Ut lorem arcu, interdum id tortor a, tincidunt vestibulum eros. Vivamus sit amet mattis turpis. Nullam auctor ut velit nec adipiscing. Morbi et vehicula diam.</p>
  </article>
</section>

<aside class="sticky">
  <h1>This is a sticky sidebar</h1>
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
  <p>Duis quis nibh gravida, gravida nisl ac, imperdiet sem. Fusce quis malesuada magna.</p>
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</aside>

<footer>This is a footer</footer>

Answer №4

I have implemented the code from CodePen and restructured the JavaScript code along with some customized logic for the sidebar as needed. I hope this solution proves to be beneficial :)

var sidebarArea = $('aside ul');
var footerArea = $('footer');
margin = 10;
offsetTop = sidebarArea.offset().top - margin;
offsetBottom = footerArea.offset().top - (margin * 3 + sidebarArea.height());

$(window).scroll(function() {
  scrollTop = $(window).scrollTop();
  if (scrollTop > offsetTop && sidebarArea.hasClass('natural')) {
    sidebarArea.removeClass('natural').addClass('fixed').css('top', margin);
  }
  if (offsetTop > scrollTop && sidebarArea.hasClass('fixed')) {
    sidebarArea.removeClass('fixed').addClass('natural').css('top', 'auto');
  }
  if (scrollTop > offsetBottom && sidebarArea.hasClass('fixed')) {
    sidebarArea.removeClass('fixed').addClass('bottom').css('top', offsetBottom);
  }
  if (offsetBottom > scrollTop && sidebarArea.hasClass('bottom')) {
    sidebarArea.removeClass('bottom').addClass('fixed').css('top', margin);
  }
});
(remaining CSS and HTML code intact)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Implementing scrolling functionality within a nested container

I need help with getting a nested container (.widget2) to scroll while still keeping the borders intact. Currently, the inner container is scrolling past the bottom edge of the parent container, and the scrollbar isn't displaying correctly. If you w ...

Leveraging Font Awesome and Material Icons within ngFor in Angular 2

I have a unique situation where I need to display a dynamic list of icons in a right side bar. These icons are added to the sidebar based on user actions and are displayed using the ngFor directive. The challenge here is that some icons come from Font Awe ...

Tips on customizing the CSS responsiveness of your Bootstrap carousel

I have recently installed a Bootstrap theme on my Wordpress site and I am trying to make some CSS adjustments. One issue I am facing is with the carousel. Currently, when I resize the website or view it on a mobile device... The carousel maintains a lar ...

Encircle a particular row in a table with a border

I'm having trouble creating a border around only the top row of my table. Right now, the border is only displayed around the outside of the entire table. I also want to add a border specifically to the first row that contains 'Team, Correct Picks ...

Issues arise with the functionalities of FireFox related to transformations and transitions

I've been working on my CSS and here is what I have: img.buttonImg { -webkit-transition: all 0.5s ease-in-out; -moz-transition: all 0.5s ease-in-out; -o-transition: all 0.5s ease-in-out; -ms-transition: all 0.5s ease-in-out; transition: ...

Tips for positioning a highcharts pie chart and legend in the middle of a page

I'm struggling to center my highchart data in a node/react single page application. Currently, it appears off-center like this: https://i.stack.imgur.com/ccR6N.png The chart is floating to the left and I would like to have everything centered within ...

Creating a customized Paypal form with user-selected options

I want to make it easy for visitors to my website to pay through Paypal by simply clicking on a link that will take them directly to the checkout page. What I'm looking for is a way to provide basic options such as: Allowing users to enter their na ...

The dropdown menu is extending outside the header in a right-to-left (RTL) direction

I have implemented the jQuery code below to prevent the dropdown from extending beyond the header area. It works perfectly in the normal LTR version. However, I need a solution for the RTL version. How can I achieve this? jQuery $('.primary-menu .dr ...

Conceal a table with jQuery

Is there a way to initially conceal a table on page load only to reveal it with a sliding animation when a specific link is clicked? I have attempted using the following code to hide the table: $('.table_div').hide(); I have enclosed the table ...

Showing information from a table for editing purposes with the use of HTML input tags

As I navigate my way through the complexities of HTML and PHP coding, I’m faced with a challenge in displaying database content on an editable table within my web page. Clicking the edit button should lead to a separate page where data can be modified. ...

In TypeScript version 2.4.1, the fontWeight property encounters an error where a value of type 'number' cannot be assigned to the types of '"inherit", 400'

When attempting to set the fontWeight property in TypeScript, I encounter the following error: Types of property 'test' are incompatible. Type '{ fontWeight: number; }' is not assignable to type 'Partial<CSSProperties>&a ...

The 600 pixel wide page is not completely filling the 640 pixel width screen on a mobile device

Currently, I am conducting a test on a webpage using an iPhone 5s with a screen resolution of 1136 x 640 pixels. The meta tag is set as follows: <meta name="viewport" content="user-scalable=yes, initial-scale=1, width=device-width, shrink-to-fit=no"&g ...

Tips for merging identical media queries into a single query using SASS

Previously, I organized my media queries in LESS by combining them at a single place like this LESS: .media-mixin(@break) when (@break = 1200px) { .abc{ color: red; } } .media-mixin(@break) when (@break = 1200px) { .xyz{ color: yellow; ...

Is there a way to circumvent the mouse up event?

I want to create a feature where when a user clicks down, something specific occurs. The sequence of events includes: An action taking place (which is not the focus here). Triggering a mouse up event. Implemented with: angular, html, css. Excludes: jQue ...

Combining Bootstrap with Rails

As I delve into the official documentation on incorporating Twitter Bootstrap in Rails, I stumbled upon an interesting tidbit: It mentions to eliminate all the *= require_self and *= require_tree . statements from the Sass file and opt for @import to im ...

Responsive slide displays a unique number of items per slide depending

I created a logo slider using Bootstrap, similar to the one showcased here: http://jsfiddle.net/juddlyon/Q2TYv/10/. Currently, each slide in the slider displays 4 logos. I would like to make it responsive so that on smaller screens, only 2 logos are shown ...

Ways to stop the floating label from blending with the input field

Attempting to incorporate the Bootstrap Material design theme into my project, I have implemented a basic text input field using the code below: <div class="form-control-wrapper"> <input class="form-control empty" type="text"></input> ...

Creating a flexible image layout within a container with relative positioning

I attempted to create a basic slideshow with images sliding from right to left as an animation: let slides = document.querySelectorAll('.img-container'); let l = slides.length; let i = 0; setInterval(function(){ i = (i + 1) % l; if(i == 0){ f ...

Is the Ngx-bootstrap popover automatic positioning malfunctioning when placed on the right side of the screen?

I am currently facing an issue while implementing popovers on our application using Angular 6.0.1, Ngx-bootstrap 2.0.5, and Bootstrap 4.1.1. The problem arises when I use 'auto' positioning for the popovers, specifically on the right side of the ...

Attempting to apply custom styles to jQuery components using CSS

Looking to restyle the black bar on my test page located at The black bar with 3 tabs about halfway down the page needs a new color scheme. By inspecting with FireBug, I found these elements: <ul class="ui-tabs-nav ui-helper-reset ui-helper-clearfix ...