A sticky sidebar in HTML that is confined to a specific div element

I'm working on creating an HTML sidebar that is constrained to the size of a div (not full-screen like typical sidebars) and also sticky. This means that when the height of the div exceeds the screen's height, the sidebar should stick to the screen and not scroll.

So far, I have achieved the first part - limiting the sidebar's height to the div it's in.

HTML

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h2>Top text</h2>
<div class="filtering">

  <div id="mySidenav" class="sidenav">
    <div id="sticky">
    <a href="javascript:void(0)" onclick="closeNav()" class="close" id="closefilter"></a>
    <div id="filterheader">Filter</div>
    <div id="filtercontent">
      <div id="subfilterheader">Platforms</div>
      <ul style="list-style: none;" id="filterlist">
        <li>
          <div class="checkbox">
            <label><input id="filtersteam" type="checkbox" onchange="changeFilter('steam')"/>Steam</label>
          </div>
        </li>
        <li>
          <div class="checkbox">
            <label><input id="filterepic" type="checkbox" onchange="changeFilter('epic')"/>Epic</label>
          </div>
        </li>
        <li>
          <div class="checkbox">
            <label><input id="filterorigin" type="checkbox" rel="origin" onchange="changeFilter('origin')"/>Origin</label>
          </div>
        </li>
        <li>
          <div class="checkbox">
            <label><input id="filtergog" type="checkbox" rel="gog" onchange="changeFilter('gog')"/>GOG</label>
          </div>
        </li>
      </ul>
      </div>
    </div>
  </div>

<span style="font-size:30px;cursor:pointer" onclick="openNav()">&#9776; open</span>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Sed adipiscing diam donec adipiscing tristique risus. Nullam eget felis eget </p>
</div>
<h1>Bottom text</h1>
</body>
</html>

CSS

body {
  font-family: "Lato", sans-serif;
}
.sidenav {
  height: 100%;
  width: 0;
  z-index: 2;
  top: 0;
  left: 0;
  background-color: #111;
  overflow-x: hidden;
  transition: 0.5s;
  position: absolute;
}

.sidenav a {
  padding: 8px 8px 8px 32px;
  text-decoration: none;
  font-size: 25px;
  color: #818181;
  display: block;
  transition: 0.3s;
}


.sidenav a:hover {
  color: #f1f1f1;
}

.sidenav #filterheader {
  top: 0;
  right: 25px;
  font-size: 36px;
  margin-left: 30px;
  margin-top: 32px;
  text-align: left;
  color: white;
}

p{
  font-size: 50px;
}

.filtering{
  position: relative;
}


#subfilterheader{
  color: white;
  font-size: 21px;
  margin-top: 30px;
  margin-left: 40px;
}

#filterlist{
  margin-left: 15px;
  color: white;
}

#sticky{
  position: sticky;
  position: -webkit-sticky;
  top: 30px;
}


.close {
  position: absolute;
  right: 0px;
  width: 32px;
  height: 32px;
  opacity: 0.3;
}
.close:hover {
  opacity: 1;
}
.close:before, .close:after {
  position: absolute;
  left: 15px;
  content: ' ';
  height: 33px;
  width: 2px;
  background-color: #ffffff;
}
.close:before {
  transform: rotate(45deg);
}
.close:after {
  transform: rotate(-45deg);
}

@media screen and (max-height: 450px) {
  .sidenav a {font-size: 18px;}
}

JS - opening and closing of the sidebar

function openNav() {
  document.getElementById("mySidenav").style.width = "250px";
}

function closeNav() {
  document.getElementById("mySidenav").style.width = "0";
}

JS fiddle - https://jsfiddle.net/4a31mgw0/

My aim is to integrate it with a functionality like this: https://jsfiddle.net/yn5rv0ke/
Is there a way to make the sidebar both limited to a div and sticky?

Answer №1

To achieve a sticky behavior for a div, it must have a defined height. Based on your description, the issue in your previous code was placing the sticky div inside the sidebar and assigning the height to the sidebar itself.

For better organization, it is recommended to work with separate divs such as a sidebar div and a content div.

In the revised solution, display: flex was added to the main div (.filtering) and the text content was wrapped in another div (.main-content). This ensures that the sidebar is only sticky within the main div. Additionally, considering the placement of the button to open and close the div near the text content, it was assumed that you did not want it to be sticky.

Here is the updated solution: (and fiddle)

[code snippet and HTML code provided in the original text]

Answer №2

I have made some adjustments to your code snippet here

Essentially, you must apply the position: fixed property to your #mySidenav element. However, this may cause the element to lose its dynamic height. To address this issue, I included some JavaScript code to dynamically adjust its style based on its container (I assigned the id #container to the parent element with class filtering). The changes in CSS and JS were made to the #mySidenav element rather than the .sticky one to achieve the desired result.

By the way, the animation may appear a bit odd when the menu first opens. In this case, consider moving the JavaScript commands that modify the style to an earlier point in the code.

Answer №3

To change the CSS property from position: absolute to position: fixed will ensure the element stays fixed in its position on the page.

Check out this link for a live example: https://jsfiddle.net/vhgj29yk/

Answer №4

Simply adjust the structure a bit, along with some CSS and JavaScript modifications.

  function toggleNav() {
  document.getElementById("mySidenav").classList.toggle("open");
  document.getElementById("openBtn").classList.toggle("hidden");
  document.getElementById("content-wrapper").classList.toggle("shifted");
}
body {
  font-family: "Lato", sans-serif;
  margin:0;
  padding: 0;
}
span#openBtn {
  display: inline-block;
  width: fit-content;
}
div#content-wrapper {
  padding: 0px 15px;
}
.sidenav {
  height: 100vh;
  width: 0;
  z-index: 2;
  top: 0;
  left: 0;
  background-color: #111;
  overflow-x: hidden;
  overflow-y: scroll;
  transition: 0.5s;
  position: absolute;
}
/* CSS styles for scrollbar */
@media screen and (max-height: 450px) {
  .sidenav a {font-size: 18px;}
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="style.css" />
</head>
<body>

<div class="filtering">

  <div id="mySidenav" class="sidenav">
    <div id="sticky">
    <a href="javascript:void(0)" onclick="toggleNav()" class="close" id="closefilter"></a>
    <div id="filterheader">Filter</div>
    <div id="filtercontent">
      <div id="subfilterheader">Platforms</div>
      <ul style="list-style: none;" id="filterlist">
        <li>
          <div class="checkbox">
            <label><input id="filtersteam" type="checkbox" onchange="changeFilter('steam')"/>Steam</label>
          </div>
        </li>
        <li>
          <div class="checkbox">
            <label><input id="filterepic" type="checkbox" onchange="changeFilter('epic')"/>Epic</label>
          </div>
        </li>
        <li>
          <div class="checkbox">
            <label><input id="filterorigin" type="checkbox" rel="origin" onchange="changeFilter('origin')"/>Origin</label>
          </div>
        </li>
        <li>
          <div class="checkbox">
            <label><input id="filtergog" type="checkbox" rel="gog" onchange="changeFilter('gog')"/>GOG</label>
          </div>
        </li>
      </ul>
      </div>
    </div>
  </div>
  <div id="content-wrapper">
    <div class="header">
      <h1>Top Text</h1>
    </div>
  <span id="openBtn" style="font-size:30px;cursor:pointer" onclick="toggleNav()">&#9776; open</span>
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Sed adipiscing diam donec adipiscing tristique risus. Nullam eget felis eget </p>
  
  <div class="footer"><h1>Bottom text</h1></div>
</div>
</div>
</body>
</html>

Answer №5

Update Your JavaScript Code with the Following:

document.getElementById("mySidenav").style.overflow = "hidden";
document.getElementById("sticky").style.overflow = "hidden";
document.getElementById("sticky").style.width = "0";
document.getElementById("sticky").style.background = "#111";
function openNav() {
  document.getElementById("mySidenav").style.width = "250px";
  document.getElementById("sticky").style.width = "250px";
}

function closeNav() {
  document.getElementById("mySidenav").style.width = "0";
  document.getElementById("sticky").style.width = "0";
}
var s = document.querySelector('#sticky');
document.addEventListener('scroll', ()=>{
if(window.scrollY > s.offsetHeight){
    s.style.position="fixed";
}
else s.style.position="static"

});

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

What is causing my div to transition repeatedly from the bottom to the top instead of the center position?

Currently, I am using React and Tailwind CSS and facing an issue with the transition property. My goal is to have a div grow in width and height from the center until it covers the entire viewport when a specific state variable becomes true. The content in ...

Only one active class is allowed in the Bootstrap Accordion at any given time

I have implemented Bootstrap's accordion on my webpage, consisting of two different sections with unique content. Upon loading the page, the active class defaults to the first element of the first section. However, if I navigate to the "Second" sectio ...

Guide on setting a value in $(document).ready using code behind

I am currently working on a .NET application with the use of Twitter Bootstrap. My main challenge right now is retrieving data from a .aspx.cs page to a .aspx page. Here's a look at my code: strObject.cs public class strObject { public string Nam ...

Encountering a Basic React Issue: Unable to Implement @material-ui/picker in Next.js

I'm currently attempting to integrate the @material-ui/pickers library into my Next.js application. In order to incorporate the Picker provider, I followed the guidance provided in the Next.js documentation by adding the _app.js file inside /pages: i ...

The error message "Cannot access property 'findAll' of undefined in expressjs" is displayed

An issue has occurred with ExpressJS: TypeError - Cannot read property 'findAll' of undefined. It seems that all Sequelize functions are not working correctly. Numerous errors are popping up, such as "Cannot read property 'sequelize method& ...

A server that broadcasts using Javascript, Node.js, and Socket.IO

Could someone provide a simple example of how to create a Node.JS server that runs both a TCP and Socket.IO server? The main goal is to pass data from a TCP client to multiple Socket.IO clients who are interested in it. This setup is intended to facilita ...

When using Expressjs MVC, encountering difficulties in retrieving data from mongoose in the listAll() function within the router

I'm currently working on implementing MVC-like architecture in Express.js for a very specific scenario. I suspect there may be an issue with promises, but I'm struggling to debug the problem effectively. Here's how the architecture is set u ...

Switch Image on Hover in Panel Group

After delving into Bootstrap, I encountered an issue. I have a Panel-Group with an image and some text. The challenge is switching the image on hover, but it should change when hovering over the panel, not just the image itself. I've found solutio ...

Include two additional elements for action in a list

In my React project, I've created a list with the following elements: Avatar Text Edit icon Delete icon I managed to set up the structure successfully up until the delete icon. Now, how can I properly add it without overlapping the edit icon? Both ...

Error encountered: unable to locate module - '@deck.gl/exper-layers'

When attempting to run npm start on the trip example in deck.gl, I encountered an issue. Although other examples open without any problems, the trip example is giving me this npm error: Module not found: Error: Can't resolve '@deck.gl/experim ...

Tips for keeping the scrollbar permanently at the bottom in JavaScript?

I am trying to implement a feature where a div always scrolls down automatically. scrollDown(){ var chat = this.conversation; this.conversation.scrollTop = chat.scrollHeight; } checkKeyPress(e){ if (e.key == "Enter") { this.scrollDown(); .. ...

Unusual behavior observed in Safari regarding transitions and animations

I have encountered a strange bug in Safari 8 and 9 on desktop, as well as iOS 8.4 and newer on mobile devices. I am perplexed by why it is happening and how to resolve it. This issue can be replicated with 100% accuracy. Here are the steps to reproduce: ...

Activating autocomplete outcomes via AJAX using Cucumber/Capybara/Selenium

Whenever I try to run my tests, the autocomplete dropdown menu doesn't appear unless I physically click on the search input field. This is a Cucumber test that utilizes Selenium Webdriver, and the data is sourced from the Crafty Clicks Address Autoco ...

Typescript encounters ERROR TS1128: Expecting a declaration or statement

Having trouble with a TypeScript error in my game-details.component.ts file that I've been trying to fix for a couple of hours. It's showing up at line 26, column 54 and everything seems correct to me. Interestingly, when I press CTRL + S in my ...

Utilize AngularJS to integrate a service into the router functionality

What is the best way to inject a service into my router so that its JSON result will be accessible throughout the entire application? Router: export default ['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterP ...

5 Creative Techniques for Manipulating Boolean Variables in If Statements

I am receiving a unique custom header value and the values I am getting are accurate. The expected values include: true, false, undefined. However, the response associated with the value: false is incorrect. Code Snippet let deviceStatus = req.headers[ ...

Angucomplete Alternative solves the challenge of accessing remote URLs

I have been using the Angucomplete Alt directive for creating an autocomplete feature. It has been working well so far, but now I want to customize a specific request to be sent to my server. <div angucomplete-alt id="input-name" ...

Update the jQuery script tag with new content - rewrite everything

I am facing an issue with jquery. I need to change the link to src only when "document.write" is present. Below is my code: myscript.js document.write("TEST ABCD"); test.html <html> <body> <button id="example">click me</button&g ...

Bootstrap dropdown menu fails to adapt to updated navbar height

I recently made a modification to the navbar size on my website, increasing it from 50px to 63px by tweaking a line in the bootstrap.css file. The exact code snippet I utilized for this adjustment is as follows: .navbar { position: relative; min ...

problem encountered while attempting to transmit data to multer in React

I was attempting to upload an image to the backend using Multer. I have reviewed the backend code multiple times and it appears to be correct. Could there be an issue with my front-end code? Here is a POST code snippet: const response = await fetch(' ...