CSS Only Sidebar Dropdown (without using Bootstrap)

I want to create a sidebar with collapsible dropdown options and smooth animations using only pure css/js/html/jquery, without relying on bootstrap like I did in the past. Here is an example of what I created previously with bootstrap:

Now, as a challenge, I am trying to achieve the same functionality using only pure css. So far, I have been working on this code snippet but haven't been able to implement expand/collapse accordion feature yet:

var isSidebarOpen = false;

function sideNavClicked(){
    console.log('sideNavClicked()')
    isSidebarOpen ? closeNav() : openNav();
}

function openNav() {
console.log('openNav')
    isSidebarOpen=true;
  document.getElementById("mySidebar").style.width = "250px";
  document.getElementById("main").style.marginLeft = "250px";
}

function closeNav() {
console.log('closeNav')
    isSidebarOpen=false;
  document.getElementById("mySidebar").style.width = "0";
  document.getElementById("main").style.marginLeft= "0";
}
body {
  font-family: "Lato", sans-serif;
}

.sidebar {
  height: 100%;
  width: 0;
  position: fixed;
  z-index: 1;
  top: 0;
  left: 0;
  background-color: #111;
  overflow-x: hidden;
  transition: 0.5s;
  padding-top: 60px;
}

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

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

.sidebar .closebtn {
  position: absolute;
  top: 0;
  right: 25px;
  font-size: 36px;
  margin-left: 50px;
}

.openbtn {
  font-size: 20px;
  cursor: pointer;
  background-color: #111;
  color: white;
  padding: 10px 15px;
  border: none;
}

.openbtn:hover {
  background-color: #444;
}

#main {
  transition: margin-left .5s;
  padding: 16px;
}

/* On smaller screens, where height is less than 450px, change the style of the sidenav (less padding and a smaller font size) */
@media screen and (max-height: 450px) {
  .sidebar {padding-top: 15px;}
  .sidebar a {font-size: 18px;}
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">

</head>
<body>

<div id="mySidebar" class="sidebar">
  <a href="javascript:void(0)" class="closebtn" onclick="closeNav()">×</a>
  <a href="#">About</a>
  <a href="#">Expand This ▼</a>
    <ul>
      <li><a href="#">Coffee</a></li>
      <li><a href="#">Coverage</a></li>
    </ul>
  
  <a href="#">Clients</a>
  <a href="#">Contact</a>
</div>

<div id="main">
  <button class="openbtn" onclick="sideNavClicked()">☰</button>  
  <h2>Collapsed Sidebar</h2>
  <p>Click on the hamburger menu/bar icon to open the sidebar, and push this content to the right.</p>
</div>


</body>
</html> 

I'm looking for a small scale example to enhance this code further. It's also hosted on jsfiddle: https://jsfiddle.net/martinradio/7wey2ujt/7/

Answer №1

To enhance your animation, consider implementing the following:

#animatedObj{
    filter: opacity: 0; /* or a different effect to create a transition */
    -webkit-transition: filter 200ms linear;
}
.show{
    filter: opacity: 1;
    -webkit-transition: filter 200ms linear;

Then, in your JavaScript/jQuery code:

$('#animatedObj').click(function(){
    $('#animatedObj').toggleClass('show')
    if($('#animatedObj').hasClass('show')){
        $('#animatedObj').append("<list thing>")
    }else{
        $('#animatedObj').remove("<list thing>")
    }
})

Consider exploring different CSS effects that might work better for your design.

Answer №2

Feel free to test out my solution here, with added animations for a more engaging experience.

var isSidebarOpen = false;

function sideNavClicked() {
  isSidebarOpen ? closeNav() : openNav();
}

function openNav() {
  isSidebarOpen = true;
  document.getElementById('mySidebar').classList.add('sidebar-show');
  document.getElementById('main').classList.add('main-show');
}

function closeNav() {
  isSidebarOpen = false;
  document.getElementById('mySidebar').classList.remove('sidebar-show');
  document.getElementById('main').classList.remove('main-show');
}

function toggleMenuItem(element){
    document.getElementById(element.dataset.ulid).classList.toggle("ul-show");
}
html,
body {
  font-family: "Lato", sans-serif;
  height: 100%;
  margin: 0;
}

.super-animation{
  -webkit-transition: -webkit-transform 300ms ease;
  -webkit-transition-duration: 300ms;
  -moz-transition: -moz-transform 300ms ease;
  transition: transform 300ms ease;
}

.main-content{
  margin: 0;
  display: flex;
  position: relative;
  width: 100%;
  height: 100%;
}

.sidebar {
  height: 100%;
  max-height: calc(100% - 15px);
  width: 250px;
  position: absolute;
  z-index: 1;
  top: 0;
  left: 0;
  background-color: #111;
  overflow-x: hidden;
  padding-top: 60px;
  
  right: 0;
  -webkit-transform: translate3d(calc(-100%), 0, 0);
  -moz-transform: translate3d(calc(-100%), 0, 0);
  transform: translate3d(calc(-100%), 0, 0);
}

.sidebar.sidebar-show{
  -webkit-transform: translate3d(0, 0, 0);
  -moz-transform: translate3d(0, 0, 0);
  transform: translate3d(0, 0, 0);
}

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

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

.sidebar .closebtn {
  position: absolute;
  top: 0;
  right: 25px;
  font-size: 36px;
  margin-left: 50px;
}

.openbtn {
  font-size: 20px;
...
<li><a href="#">Coffee</a></li>
<li><a href="#">Coverage</a></li>
</ul>

<a href="#">Clients</a>
<a href="#">Contact</a>
  </div>

  <div id="main" class="super-animation">
    <button class="openbtn" onclick="sideNavClicked()">☰</button>  
    <h2>Collapsed Sidebar</h2>
    <p>Click on the hamburger menu/bar icon to open the sidebar, and push this content to the right.</p>
  </div>
</div>
</body>
</html>

Answer №3

Maybe this is the solution you've been searching for I made some additions to your javascript code and incorporated a few classes in the html, including ul tag and a tag to collapse the submenu. I have included comments in the added code to clarify the modifications that were made...


Check out the code snippet below


var isSidebarOpen = false;

function sideNavClicked() {
  console.log("sideNavClicked()");
  isSidebarOpen ? closeNav() : openNav();
}

function openNav() {
  console.log("openNav");
  isSidebarOpen = true;
  document.getElementById("mySidebar").style.width = "250px";
  document.getElementById("main").style.marginLeft = "250px";
}

function closeNav() {
  console.log("closeNav");
  isSidebarOpen = false;
  document.getElementById("mySidebar").style.width = "0";
  document.getElementById("main").style.marginLeft = "0";
}

////------------Added Line of Code----------------
const list = document.querySelector(".toggle--list");
// const submenu
document.querySelector(".submenu").classList.add("hidden");
list.addEventListener("click", e => {
  document.querySelector(".submenu").classList.toggle("hidden");
});
///////////////////
body {
    font-family: "Lato", sans-serif;
  }
  
  .sidebar {
    height: 100%;
    width: 0;
    position: fixed;
    z-index: 1;
    top: 0;
    left: 0;
    background-color: #111;
    overflow-x: hidden;
    transition: 0.5s;
    padding-top: 60px;
  }
  
  .sidebar a {
    padding: 8px 8px 8px 32px;
    text-decoration: none;
    font-size: 25px;
    color: #818181;
    display: block;
    transition: 0.3s;
  }
  
  .sidebar a:hover {
    color: #f1f1f1;
  }
  
  .sidebar .closebtn {
    position: absolute;
    top: 0;
    right: 25px;
    font-size: 36px;
    margin-left: 50px;
  }
  
  .openbtn:hover {
    background-color: #444;
  }
  
  #main {
    transition: margin-left .5s;
    padding: 16px;
  }
  
  /* On smaller screens, where height is less than 450px, change the style of the sidenav (less padding and a smaller font size) */
  @media screen and (max-height: 450px) {
    .sidebar {padding-top: 15px;}
    .sidebar a {font-size: 18px;}
  }

/*-----------added line of code----------------*/
.hidden{
    display:none;
    visibility: hidden;
}
/*---------------------------------------------*/
<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <div id="mySidebar" class="sidebar">
      <a href="javascript:void(0)" class="closebtn" onclick="closeNav()">×</a>
      <a href="#">About</a>
      <a href="#" class="toggle--list">Expand This ▼</a>
      <!--Added classname here-->
      <ul class="submenu">
        <!--Added classname here-->
        <li><a href="#">Coffee</a></li>
        <li><a href="#">Coverage</a></li>
      </ul>

      <a href="#">Clients</a>
      <a href="#">Contact</a>
    </div>

    <div id="main">
      <button class="openbtn" onclick="sideNavClicked()">☰</button>
      <h2>Collapsed Sidebar</h2>
      <p>
        Click on the hamburger menu/bar icon to open the sidebar, and push this
        content to the right.
      </p>
    </div>
    <script src="script.js"></script>
  </body>
</html>

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

Combining Packery with ajax-loaded content and the ability to re-layout Packery frames

Currently, I am in the process of designing a layout using the Packery library from Metafizzy to showcase post titles and thumbnails. The idea is that when these posts are clicked on, the initial content will be hidden, and then replaced with the rest of t ...

What steps are involved in setting up a local server on my computer in order to create an API that can process http requests from Flutter?

New to API creation here, so please be patient. I plan to eventually host my API on a more robust server, but for now, I want to get started by setting something up locally on my PC to work on backend functions. The API goals include: Verify incoming requ ...

Is it feasible to retrieve information within a behavior in Drupal?

I recently installed the "Autologout" Drupal module, which can be found at . This module includes a timer that ends your session if there is no activity on the page for a set period of time. However, I am interested in adjusting the timer value to better ...

Getting Javascript as a string using Selenium in Python

Is it possible to retrieve JavaScript code using Python Selenium? Specifically, I want the JS code as a string. function validateForm() { var x = document.forms["myForm"]["Password"].value; if (x.length >= 6) { } } ...

Transforming CSS shorthand background properties into longhand representation

I have been working on a function to convert shorthand CSS background declarations into longhand. The function I created is functional, but it does not handle cases where the background-color property includes color values like black or yellow. It also doe ...

Spin and flip user-submitted images with the power of HTML5 canvas!

I am currently working on a profile upload system where we are implementing image rotation using the HTML5 canvas object with JavaScript. Although the uploaded image is rotating, we are facing issues where parts of the image are being cut off randomly. So ...

Working with MySQL in Node.js using async/await

Struggling with utilizing async/await in Node.js with MySQL as it consistently returns an undefined value. Can someone shed light on what could be causing this issue? See my code snippet below. const mysql = require('promise-mysql'); var co ...

What exactly is Bootstrap - a CSS framework, a JavaScript framework, or a combination

Being new to Bootstrap, I have taken the time to explore What is Bootstrap? as well as http://getbootstrap.com/. From what I understand so far, Bootstrap is a CSS framework that aids in creating responsive designs that can adapt to various devices. Essent ...

Retrieving Data from Vue JS Store

I am fetching value from the store import {store} from '../../store/store' Here is the Variable:- let Data = { textType: '', textData: null }; Upon using console.log(store.state.testData) We see the following result in the cons ...

Is it possible to index elements starting from 1 in Jquery?

Is there a way to make the index element start from 1 without having to use "if(index ===0) return true;"? $( 'h3' ).each(function( index ) { ...do things... } Many loops typically begin at 0 because of their association with arrays, wh ...

Bidirectional Data Binding Using Meteor and React

When using Meteor, the getMeteorData() method is preferred over getInitialState(). But how can we achieve binding, especially with regards to a user's surname in their profile? ... getMeteorData() { return { u = Meteor.user() } }, componentRen ...

Encountering an Enumeration Exception when trying to delete an element from a collection list using a foreach loop

I encountered an issue when attempting to remove an element from a list collection using foreach. I have searched online but have not found a clear explanation for the problem. If anyone has knowledge about this, please share the information. ...

What is the reason for the filter not displaying the IFRAME?

I have a filter set up to automatically embed YouTube videos for user-generated content by searching for links and verifying if they are valid YouTube videos. If they are, the video should be embedded using standard iframe code; otherwise, it remains just ...

JavaScript function to convert a string of characters into a readable time format

Is there a way to input a string in an 'input type="time"' field in my HTML code? <label class="item item-input"> <span class="input-label">Departure Time </span> <input type="time" ng-model="heur ...

Troubleshooting issues with Firebase integration in a Node.js environment

I am currently encountering difficulties implementing Firebase in my Node.js project. Below is the code snippet that I am attempting to execute on Node. var firebase = require("firebase"); var admin = require("firebase-admin"); var serviceAccount = requi ...

Display the div only during the printing process

Imagine I have a situation where there is a block of content that I only want to show when printing. It looks something like this: <div id="printOnly"> <b>Title</b> <p> Printing content </p> </div&g ...

Conceal the div element if the screen size drops below a certain threshold

Is it possible to hide a div element when the browser width is less than or equal to 1026px using CSS, like this: @media only screen and (min-width: 1140px) {}? If not, what are some alternative solutions? Additional information: When hiding the div eleme ...

How can I align rectangles with different heights to display side by side using Javascript?

Currently, I am designing a press page for a website where the headlines/articles are displayed in rectangles. To achieve this layout, I am using the following CSS: .press-blocks{ column-count: 4; column-gap: 2em; padding-left: 10%; padding ...

React and Redux: The Search for Missing Props

I am embarking on a new project using a different technology stack for the first time. In my previous job, I inherited an existing project with everything already set up. However, I am facing issues as my props are coming up as undefined and I am unsure wh ...

Is Grouping Together Installed Private Modules Possible?

Exploring a modular JavaScript approach in my upcoming project is a new concept for me. I would prefer explanations to be simple due to my limited experience. I have uploaded my private package on npm: @name/package-name The private package contains mul ...