CSS for collapsible sidebar with dynamic width

Imagine having a collapsible fixed-width sidebar like this:

HTML

<div class="container">
  <div class="sidebar" id="sidebar">
    SIDEBAR
  </div>
  <div class="content">
    lorem bla bla
    <button onclick="document.getElementsByClassName('sidebar')[0].classList.toggle('collapsed')">
      toggle Sidebar
    </button>
  </div>
</div>

CSS

body {
  margin:0;
}

.container {
  display: flex;
  min-height:100px;
}

.sidebar {
  position: relative;
  left: 0;
  width: 200px;
  background-color: #ccc;
  transition: all .25s;
}

.sidebar.collapsed {
  left:-200px;
  margin-right:-200px;
}

Codepen link: http://codepen.io/anon/pen/pJRYJb

Now, the question arises:

How can we transform this into a flexible-width sidebar?

Here are the key requirements:

  • Avoid using JavaScript for layouting
  • Ensure that the sidebar does not overlap the content
  • When collapsed, align the sidebar's right border with the window's left border
  • Maintain constant sidebar width even when collapsed to prevent reflows during transitions
  • Create smooth transitions without abrupt movements
  • Utilize modern CSS features like flexbox and calc

The challenge lies in finding a way to set margin-right: -100%, where 100% represents the sidebar's width

Your assistance is highly appreciated!

Answer №1

Have you thought about adjusting the width instead of changing the position when clicked? Using max-width in this scenario can yield similar results to an unknown width. Keep in mind that this change may cause content reflow on the sidebar, so consider using white-space:nowrap if it fits your needs.

Check out this example on jsFiddle

body {
    margin: 0;
}
.container {
    display: flex;
}
.sidebar {
    background: #ccc;
    transition: all .1s;
    max-width: 1000px;
}
.sidebar.collapsed {
    max-width: 0;
    overflow: hidden;
}
<div class="container">
    <div class="sidebar" id="sidebar">SIDEBAR</div>
    <div class="content">lorem bla bla
        <button onclick="document.getElementsByClassName('sidebar')[0].classList.toggle('collapsed')">toggle Sidebar</button>
    </div>
</div>

Another approach is combining transform with position for a different animation effect.

View this alternative solution on jsFiddle

body {
    margin: 0;
}
.container {
    display: flex;
}
.sidebar {
    background: #ccc;
    transition: all .1s;
}
.sidebar.collapsed {
    transform: translateX(-100%);
    position: absolute;
}
<div class="container">
    <div class="sidebar" id="sidebar">
        <div>SIDEBAR</div>
    </div>
    <div class="content">lorem bla bla
        <button onclick="document.getElementsByClassName('sidebar')[0].classList.toggle('collapsed')">toggle Sidebar</button>
    </div>
</div>

Answer №2

Expanding on Pangloss' idea regarding the transformation... you can easily adjust the content by applying a negative margin if you have knowledge of the sidebar's width. There is no necessity for the sidebar to switch to absolute positioning.

@mixin transitionAll() {
  transition: all .3s ease-out;
}
html, body {
  height: 100%;
}
.container {
  display: flex;
  width: 100%;
  height: 100%;
}
.sidebar {
  flex: 1 0 300px;
  background: #333;
  height: 100%;
  @include transitionAll();
  &.is-collapsed {
    transform: translateX(-100%);
  }
}
.content {
  width: 100%;
  height: 100%;
  padding: 1rem;
  background: #999;
  @include transitionAll();
  &.is-full-width {
    margin-left: -300px;
  }
}

--

<div class="container">
  <aside class="sidebar">
  </aside>
  <section class="content">
    <button class="btn btn-primary">Toggle</button>
  </section>
</div>

--

$(function() {
  $('.btn').on('click', function() {
    $('.sidebar').toggleClass('is-collapsed');
    $('.content').toggleClass('is-full-width');
  });
});
Check out Jason Florence's Pen LxRYQB on CodePen.

Answer №3

If it helps, I actually do have a solution using JavaScript. The animation itself is completed purely with CSS in order to address the issue with setting the width to 'auto'. By utilizing JavaScript, you can simply define the width of the sidebar domElement when the element loads:

domElement.style.width = `${parseInt(domElement.offsetWidth)}px`;

This effectively solves the problem of the unknown width. You can still implement your '.collapsed' method as desired. The only modification required is adding '!important' to the width value in

.collapsed {width: 300px !important;}
.

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

Sending a request to a PHP file using Ajax in order to display information fetched from

I am attempting to display the database row that corresponds with the student's forename and surname selected from the dropdown list. I have managed to store the first name and surname in a variable called clickeditem. However, I suspect there may be ...

Adding an entry to a table with the events linked to a specific link

Let's imagine we have a table: <table id="myTable"> <tbody> <tr> <td> <a class="removeLink" >Remove</a> </td> </tr> <tr> ...

I am experiencing issues with my three.js script not functioning properly within the context of a

I have been working on implementing a raycaster function in my project that only activates when an entity is visible. To achieve this, I was advised to create a custom script for better control. I have set up all entities and their child entities to be in ...

Placing MySQL information into a container

Currently working on a tutorial and attempting to update the styling. While I understand that the code may not be up-to-date, breaking it down into parts is aiding my comprehension of the whole. I am exploring the idea of inserting MySQL data into divs in ...

Attempting to evenly distribute items within a div container

My goal is to arrange the items in the container div evenly on a single line. I want them to be spaced out like this: https://i.sstatic.net/kA2zj.png I'm struggling to achieve this layout where the items are on the same line and evenly distributed w ...

Stuck on AMChart while trying to load data

Hello! I am currently utilizing the AMCharts framework to generate charts from data stored in a MySQL database. However, I have encountered an issue where instead of displaying the chart, I am stuck with a perpetual "Loading Data" message. You can view a ...

What is the most efficient way to temporarily transform a button into a tab switcher?

Review this snippet of code within a jQuery event listener. The element $(this) refers to a <form>. const submitButton = $(this).find('[type=submit]'); submitButton.removeClass('btn-primary') ...

The width of the Apex chart is either overflowing or not stretching properly

I'm currently utilizing apexcharts within a vue environment. My goal is to have the sparkline graph expand to occupy 100% of its parent's width. Here is what I attempted: <div> <apexchart :options="chartOptions" :ser ...

A single button that performs multiple actions with just one click

Summary: Seeking assistance in implementing a button that triggers three different actions upon being clicked thrice. Detailed description: On one page of my website, there is an introduction with text and images. I currently have a button that switches t ...

The AddThis counter is missing the right border when integrated with Twitter's Bootstrap 3

When implementing the standard code provided by alongside Twitter's Bootstrap 3, I noticed that the right border of the counter is not displaying: ...

Dawn Break Alarm Timepiece - Online Platform

My buddy recently purchased a "sunrise alarm clock" that gradually brightens to mimic a sunrise and make waking up easier. I had the thought of replicating this effect with my laptop, but I've been facing issues with getting the JavaScript time funct ...

Give GetElementsByClassName a shot

Hey, have you tried using js ref_doc_getelementsbyClassName? "I keep getting the error message 'Uncaught TypeError: Cannot set property 'value' of null' " Check out this HTML code snippet: <input type="text" cla ...

Issue with Rendering Rapheal Pie Chart in Internet Explorer 9

I encountered an issue in IE9 where I received the error message "SVG4601: SVG Path data has incorrect format and could not be completely parsed" while trying to draw a pie chart on an HTML5 page using Raphael JS and SVG. The problem arose when the "d" att ...

Leverage the power of Bootstrap by showcasing several carousels in a sleek grid layout

How can I display dynamically generated carousels in a grid format using Bootstrap4? Current formation: https://i.sstatic.net/H3du7.png I want to showcase multiple carousels containing one or more images in a clean grid layout instead of the current hor ...

missing method in HTML/JavaScript

Just experimenting with functions and time... The outcome is showing as undefined on the live server. However, if I execute the JavaScript code separately, the correct greetings display. Why is this happening? Is there a solution to rectify it? const tod ...

Using jQuery and cheerio to iterate through a collection of items

I am currently reviewing the elements within 2 HTML tables: <table class="content"> <tbody> <tr> <th>title1</th> <td>info1</td> </tr> <tr> ...

Tips for transferring the ID from one element to another using JavaScript

I'm attempting to create a slideshow using icons all within one class. The "active" style class will have an ID and represent the current picture. By clicking either the left or right button, I aim to change the style of the active class. const l ...

The oversized monitor is cut off halfway due to postcss-pxtorem

When designing a screen with dimensions of 3840 x 2160, the initial draft was created with 1920 x 1080. I utilized postcss-pxtorem with a "rootValue" set to 192 for responsive scaling. The zoom is normal and functional on screens below 1920 pixels wide. ...

Assistance required: Click on the button to select and copy all text within the specified paragraph ID

Hey there! I've got a div with a dropdown menu that reveals text and images based on the selected option. What I want to achieve is having a button that allows users to copy all the content inside the div. Below is my sample code for the div dropdown ...

Overlap between sidebar and navbar

I am currently working on developing an admin panel for one of my projects. I designed a sidebar and implemented a standard bootstrap 4 navbar. However, I encountered a minor issue where the bootstrap 4 navbar is extending to the full width of the page ins ...