Collapsible flexible-width sidebar using only CSS

19,253

How about changing the width instead of position on click? I use max-width in this case, it works almost the same as unknown width. This will probably cause the content reflow on the sidebar, so use white-space:nowrap if it's acceptable.

http://jsfiddle.net/dn4ge901/

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 workaround is using transform width position together, but the animation effect will be slightly different.

http://jsfiddle.net/vkhyp960/

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>
Share:
19,253
Daniel
Author by

Daniel

Co-Founder &amp; Developer of Codecks. Background in AI/Computer Linguistics, mostly doing Frontend-Work with React these days.

Updated on July 05, 2022

Comments

  • Daniel
    Daniel almost 2 years

    Let's assume I have a collapsible fixed-width sidebar defined 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 here: http://codepen.io/anon/pen/pJRYJb

    So here's the question:

    How can I go from there to a flexible-width sidebar?

    Here are the constraints:

    • no javascript (I want the browser to deal with the layouting – not me)
    • the sidebar must not overlap the content
    • when collapsed, the sidebar's right border needs to be aligned with the window's left border (to be able to attach an absolutely positioned tab on the right side that's always visible)
    • the width of the sidebar shouldn't change if collapsed to avoid reflows during the transition
    • smooth transition without any sudden jumps
    • modern CSS (flexboxes, calc) is fine

    The main issue here is that I can't find a way to say margin-right: -100% where 100% refers to the width of sidebar

    Any help will be greatly appreciated!