Tips for creating a vertical drawer using jQuery and CSS

Hello, I am currently working on developing a drawer component using Ember.js. If you want to view the progress so far, feel free to check out this jsbin http://jsbin.com/wulija/8/edit

My goal is to have the drawer look like the following initially:

+---------------------------+
|    A      B        C      |
+---------------------------+
  ... other page content ...

When an option is selected, the corresponding component will be displayed. The drawer should slide down to reveal content A and overlap the following page content.

+---------------------------+
|    _A_    B        C      |
+---------------------------+
|                           |  |  Clicking on A slides down to show content A
|    content A              |  V  Following page content is covered by the drawer
+---------------------------+

If option B is clicked, content A will slide left and content B will slide in from the right. The height of the drawer will adjust according to the size of content B.

+---------------------------+
|    A    _B_        C      |
+---------------------------+
|                           |  |  If content B has more content
|                           |  |  It will slide further down
|nt A <--     <-- Content B |  V  
|                           |
+---------------------------+

If the currently selected option is clicked again, the drawer will close.

+---------------------------+
|    A    _B_        C      |
+---------------------------+   ^
                                |  Close drawer

I have encountered a few challenges along the way:

  • One issue is with the sliding drawer adjusting its height based on the content size. Since all content-X elements are set to position: absolute; and moved using jQuery's transform: translate, the drawer does not extend properly because these elements do not occupy any space. Additionally, position: absolute; elements cannot be hidden with overflow-y: hidden;.

  • Another challenge is that each content-X has a different size and its data is fetched via AJAX requests, making the size unknown beforehand. Therefore, having a fixed length drawer is not feasible. Ideally, I would like the browser layout engine to allocate space dynamically as needed. This would require setting content-X elements to position: static;, resulting in the three contents stacking together vertically.

Answer №1

When it comes to completing tasks, there are numerous things on your to-do list. I have provided the first option below.

$(document).ready(function () {
  var show1 = false,
      show2 = false,
      show3 = false,
      
      content1 = $('.btn-1'),
      content2 = $('.btn-2'),
      content3 = $('.btn-3');
  
  $('.content-placeholder').css("width", $(window).width());
  
  var w = $(window).width() + 30;
  
  $(window).resize(function () {
    w = $(window).width() + 30;
  });
  
  function checkDrawer (shouldOpen) {
    if (shouldOpen) {
      $('.drawer-content').addClass('show');
    } else {
      $('.drawer-content').removeClass('show');
    }
  }
  
  $('.btn-1').on('click', function () {
    show1 = !show1;
    show2 = false;
    show3 = false;
    checkDrawer(show1 || show2 || show3);
    if($('.btn-1').hasClass( "current" ))
      {
        $('.main_content').slideUp(1000);
        content1.removeClass('current');
      }
    else
      {
        $('.main_content').slideDown(1000);
        content1.addClass('current');
      }
    $('.drawer-content').css('transform', 'translate(0, 0)');
    
    
    content2.removeClass('current');
    content3.removeClass('current');
  });
  
  $('.btn-2').on('click', function () {
    show1 = false;
    show2 = !show2;
    show3 = false;
    checkDrawer(show1 || show2 || show3);
    
    
    
    $('.drawer-content').css('transform', 'translate(-' + w + 'px, 0)');
    
    
    content1.removeClass('current');
    
    content3.removeClass('current');
    
  });
  
  $('.btn-3').on('click', function () {
    show1 = false;
    show2 = false;
    show3 = !show3;
    checkDrawer(show1 || show2 || show3);
 
    $('.drawer-content').css('transform', 'translate(-' + 2 * w + 'px, 0)');
    

    content1.removeClass('current');
    content2.removeClass('current');
    content3.addClass('current');
  });
});
.main_content{
  position:relative;
  z-index:1;
  display:none;
}

.drawer {
    border: 1px solid green;
    height: 100px;
    position: fixed;
    width: 100%;
}
.drawer-navbar {
    width: 100%;
}
.drawer-content {
    overflow-x: hidden;
    transition: all 0.3s ease 0s;
    width: 5000px;
  position:relative;
}
.drawer-content.show {
    max-height: 700px;
}
.content-placeholder {
    border: 1px solid yellow;
    float: left;
    top: 90px;
    
}
.content-placeholder > div {
    transition: all 0.5s ease 0s;
}
.content-placeholder.current {
    border: 5px solid yellow;
}
.content-1 {
    background-color: red;
    height: 300px;
}
.content-2 {
    background-color: green;
    height: 200px;
}
.content-3 {
    background-color: blue;
    height: 100px;
}
.other-content {
    position: relative;
    top: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>

  <div class="drawer">
    <div class="drawer-navbar">
      <ul>
        <li class="btn-1">1</li>
        <li class="btn-2">2</li>
        <li class="btn-3">3</li>
      </ul>
    </div>
    
    <div class="main_content">
    <div class="drawer-content">
      <div class="content-placeholder">
        <div class="content-1"></div>
      </div>
      <div class="content-placeholder">
        <div class="content-2"></div>
      </div>
      <div class="content-placeholder">
        <div class="content-3"></div>
      </div>     
    </div>
    </div>
  </div>
  <div class="other-content">
    additional web content......sadfa
    sdfj
    asdjf
    sadjf
    sadjf
    jsad
    fjklxzcjlkzxcjv;lkjslkdjfl;kjaskdljflksd
    f
    asdf
    asd
    f
    adsf
    asd
    f
    ads
    fasd
    f
    asd
    fasd
    f
    asd
    fsad
    f
    adsf
    asd
    f
    asdfasd
    fasd
    f
    asdf
    asd
    fa
    sdfa
    sdjf
    asdjf
    aksdjfalskdjflkasdjflkjadslkjflkasf
    
  </div>

Hopefully this helps you progress towards your goal. Good luck!

For reference, you can view the Fiddle Here.

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 could be the reason behind datatables automatically setting the table width when the bServerSide parameter is set to true

After parsing the table data, I noticed that the HTML table is being automatically styled with a width of 1649px (seen in the style attribute). <table id="datatable_user" style="width: 1649px;"> This odd behavior only occurs when the data is source ...

The dilemma between installing Electron or installing Electron-Builder: which one

When it comes to installing Electron for an Electron app with React, the method can vary depending on the tutorial. Some tutorials use electron-builder while others do not, but there is little explanation as to why. First: npx create-react-app app cd app ...

What is the best way to set up the login page and logged-in homepage using Node, Express, and Passport with the "/" route?

I am currently in the process of developing an application using Node.js, Express.js, and Passport.js. My goal is to create a seamless user experience on the homepage where if you are not logged in, you will see a login form (with potential for additional ...

The changes made to $scope in AngularJS are not being displayed in the view

The View Section <div class="col-sm-8" data-ng-init="init_enable_disable()"> <select class="form-control" style="margin-top: 5px;" data-ng-model="schedule.scheduleType" data-ng-change="enable_disableDiv(schedule.scheduleType);"> ...

Trigger a re-render in React using setState(null) and forceUpdate()

When using react 16, setState(null) no longer triggers an update according to the official documentation: The new behavior for calling setState with null is that it does not trigger an update. This gives you the control in the updater function to decide ...

I am finding the event naming conventions in Vue 3 to be quite perplex

In the parent component, there is a child component: <upsetting-moment-step :this-step-number="1" :current-step-number="currentStepNumber" @showNextStep="showNextStep" ></upsetting-moment-step> The par ...

Can JavaScript event listeners be compelled to trigger in a specific sequence?

Is there a way in JavaScript to receive notification or execute a callback function once an event has completed its propagation? Put differently, is it possible to 'prioritize' an event and ensure that it gets triggered after all other event lis ...

Saving vast array in MongoDB

I am currently working on a personal project that involves implementing a search feature. My setup includes using typeahead.js with a REST api created in expressJS and mongoDB. I could use some guidance on two particular challenges I am facing. While my ba ...

How to adjust animation timing for various elements during a CSS 3D flip with a delay?

Here is a CSS flip setup that I have been working on in this fiddle: http://jsfiddle.net/6r82fzk6/ The Goal: I am trying to achieve a slower transition for the back element compared to everything else. The idea is to have the child element of the back fac ...

How come my HTML form keeps refreshing instead of displaying an alert after submission, even though I've included onsubmit="return false"? Additionally, it seems to be throwing an error

Why is this basic HTML and JavaScript code not functioning properly? Instead of alerting once the form is submitted, it refreshes the page and throws an error. It has also been reported to sometimes throw a CORS error when using 'module' as scri ...

Layer divs on top of each other without explicitly defining their stacking order

I am looking to stack multiple tile divs on top of each other by using negative margin-right: -10px. My goal is to have the previous div displayed on top, with new sibling divs appearing below it. Currently, the newer div overlaps the previous one. While ...

Sending back an HTTP response code from PHP to AJAX

I'm currently working on creating a login page for a website. The functionality involves using AJAX to send a request to a PHP script that verifies the username and password input. If the query returns a successful result, I use http_response_code(200 ...

Using External APIs in React: A Guide

Recently, I created a React app using the npm module 'create-react-app' I ran into an issue where I needed to call an external API from api.example.com, but found that Axios was making requests to localhost instead of the external API. Here is ...

Having trouble selecting links in the navigation bar

Just getting started with HTML/CSS and designing a website with buttons. Got some buttons up and running perfectly fine. But now, I'm working on a navigation bar with anchors inside. The problem is that while I can see the anchors when I open the webs ...

I need help figuring out how to retrieve the full path of an uploaded file in JavaScript. Currently, it only returns "c:fakepath" but I need

Is there a way to obtain the complete file path of an uploaded file in javascript? Currently, it only shows c:\fakepath. The file path is being directly sent to the controller through jquery, and I need the full path for my servlet. Are there any alte ...

``CSS: Styling a Rounded Div with a Clipped Scrollbar

I am attempting to contain a scrollbar within a div so that it remains within the rounded corners without overflowing. Take a look at the code snippet below to see the problem in action. Is there a way for the scrollbar to be fixed in its position, while ...

Sluggish webpage (Jquery and bootstrap)

I encountered a minor issue... I created a webpage using BOOTSTRAP and included the Nivo slider (jquery) on it. I utilized bootstrap for its basic styling and responsive design capabilities (adaptation for mobile, tablet, etc). However, my webpage perform ...

Only refresh the content when there are updates from the ajax call

Currently, I am populating an HTML table with data retrieved through an AJAX request. The AJAX call is made at regular intervals of X seconds. I am specifically looking for a way to update the table only when the new data fetched from the AJAX call diffe ...

Issues with PHP ajax causing database insertion failure

Here is the code for making an AJAX request: AJAX var date = new Date().toLocaleTimeString(); var text=this.value; var id=1; $.ajax({ type: "GET", url: "StoreMessages.php" , data: { room: id, msg:text, sendat:date } }); PHP Code if(isset($_GET['r ...

Guide to obtaining ngPrime autocomplete text when the button is clicked within Angular 6

I am currently utilizing the ngPrime autocomplete feature to retrieve data from a service. My goal is to capture the text entered in the autocomplete field whenever a button is clicked. I attempted to access the value using getElementById.value within th ...