Search code examples
javascripthtmlcssbordersidebar

CSS: how to make the left edge of a div follow the right edge of a sidebar with animated width?


Being just an occasional HTML/CSS/JavaScript coder, I’m stuck with a seemingly simple problem.

I want to build a very simple website layout with a content div and a sidebar on the left that can be hidden. The content div has a variable width; the right side always sticks to the right side of the browser window, the left side adjusts to the sidebar. If the sidebar is displayed, it should use a defined proportional part of the browser window width.

function toggleSidebar() {
  var sidebar = document.getElementById("mySidebar");
  var content = document.getElementById("myContent");
  if (sidebar.style.width === "0%") {
    sidebar.style.width = "25%";
    content.style.marginLeft = "25%";
  } else {
    sidebar.style.width = "0%";
    content.style.marginLeft = "0%";
  }
}
#myHeaderBar {
  position: fixed;
  left: 0px;
  right: 0px;
  height: 90px;
  z-index: 1;
  border-bottom: 1px solid #A2A2A2;
}

#mySidebar {
  background-color: #F7F7F7;
  position: fixed;
  top: 98px;
  left: 0px;
  width: 25%;
  bottom: 0px;
  overflow-y: auto;
  border-right: 1px solid #A2A2A2;
  transition: 0.5s;
}

#myContent {
  position: absolute;
  top: 98px;
  margin-left: 25%;
  bottom: 0px;
  overflow-y: auto;
  transition: 0.5s;
}
<!DOCTYPE html>

<head>
  <meta http-equiv="content-type" content="text/html;charset=utf-8" />
  <title>Sidebar Test</title>
</head>

<body>
  <div id="myHeaderBar">
    <h2>Header</h2>
    <a href="#" onclick="toggleSidebar()">Toggle Sidebar</a>
  </div>

  <div id="mySidebar">
    <p>Some Link</p>
    <p>Some Link</p>
    <p>Some Link</p>
    <p>Some Link</p>
    <p>Some Link</p>
    <p>Some Link</p>
    <p>Some Link</p>
    <p>Some Link</p>
  </div>

  <div id="myContent">
    <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
      takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
      et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
    <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
      takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
      et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
    <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
      takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
      et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
    <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
      takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
      et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
  </div>


</body>

</html>

This is all trivial and works just fine.

My problem arises when I try to limit the minimal and maximal width of the sidebar (which is what I want to do).

Of course, I can add

max-width:200px;
min-width:120px;

to #mySidebar and (if displaying the sidebar)

sidebar.style.minWidth = "120px";

or (if hiding the sidebar)

sidebar.style.minWidth = "0px";

to toggleSidebar().

But there are no equivalent parameters for the #myContent div, i.e. there is no such thing as min-margin-left and max-margin-left. As a result, text overlaps or gaps in the edge cases:

function toggleSidebar() {
  var sidebar = document.getElementById("mySidebar");
  var content = document.getElementById("myContent");
  if (sidebar.style.width === "0%") {
    sidebar.style.width = "25%";
    sidebar.style.minWidth = "120px";
    content.style.marginLeft = "25%";
  } else {
    sidebar.style.width = "0%";
    sidebar.style.minWidth = "0px";
    content.style.marginLeft = "0%";
  }
}
#myHeaderBar {
  position: fixed;
  left: 0px;
  right: 0px;
  height: 90px;
  z-index: 1;
  border-bottom: 1px solid #A2A2A2;
}

#mySidebar {
  background-color: #F7F7F7;
  position: fixed;
  top: 98px;
  left: 0px;
  width: 25%;
  max-width:200px;
  min-width:120px;
  bottom: 0px;
  overflow-y: auto;
  border-right: 1px solid #A2A2A2;
  transition: 0.5s;
}

#myContent {
  position: absolute;
  top: 98px;
  margin-left: 25%;
  bottom: 0px;
  overflow-y: auto;
  transition: 0.5s;
}
<!DOCTYPE html>

<head>
  <meta http-equiv="content-type" content="text/html;charset=utf-8" />
  <title>Sidebar Test</title>
</head>

<body>
  <div id="myHeaderBar">
    <h2>Header</h2>
    <a href="#" onclick="toggleSidebar()">Toggle Sidebar</a>
  </div>

  <div id="mySidebar">
    <p>Some Link</p>
    <p>Some Link</p>
    <p>Some Link</p>
    <p>Some Link</p>
    <p>Some Link</p>
    <p>Some Link</p>
    <p>Some Link</p>
    <p>Some Link</p>
  </div>

  <div id="myContent">
    <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
      takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
      et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
    <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
      takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
      et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
    <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
      takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
      et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
    <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
      takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
      et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
  </div>


</body>

</html>

Is there a concise CSS/JavaScript solution for this problem? I do not want to use any Javascript library just because of that.

Thank you in advance for any tips!


Solution

  • Thanks for your input!

    While (unsuccessfully) investigating the CSS Grid solution suggested by @Holli, I found a CSS Flexbox solution that almost works (see remaining issue below). Here’s the code snippet; I changed the min and max width of #mySidebar to 120px and 200px to make the effect more immediately obvious.

    function toggleSidebar() {
      var sidebar = document.getElementById("mySidebar");
      var content = document.getElementById("myContent");
      if (sidebar.style.width === "0%") {
        sidebar.style.width = "25%";
        sidebar.style.minWidth = "120px";
      } else {
        sidebar.style.width = "0%";
        sidebar.style.minWidth = "0px";
      }
    }
    #myHeaderBar {
      position: fixed;
      left: 0px;
      right: 0px;
      height: 90px;
      z-index: 1;
      border-bottom: 1px solid #A2A2A2;
    }
    
    #myContainer {
      position: absolute;
      display: flex;
      top: 99px;
      left: 0px;
      bottom: 0px
    }
    
    #mySidebar {
      background-color: #F7F7F7;
      width: 25%;
      max-width: 200px;
      min-width: 120px;
      overflow-x: hidden;
      overflow-y: auto;
      border-right: 1px solid #A2A2A2;
      transition: 0.5s;
    }
    
    #myContent {
      flex: 1;
      overflow-y: auto;
      transition: 0.5s;
    }
    <div id="myHeaderBar">
      <h2>Header</h2>
      <a href="#" onclick="toggleSidebar()">Toggle Sidebar</a>
    </div>
    
    <div id="myContainer">
      <div id="mySidebar">
        <p>Some Link</p>
        <p>Some Link</p>
        <p>Some Link</p>
        <p>Some Link</p>
        <p>Some Link</p>
        <p>Some Link</p>
        <p>Some Link</p>
        <p>Some Link</p>
      </div>
    
      <div id="myContent">
        <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
          takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
          et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
        <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
          takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
          et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
        <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
          takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
          et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
        <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
          takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
          et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
      </div>
    
    </div>

    One issue remains: (EDIT: One issue was solved and the code updated accordingly, so only one issue (not two) remains)

    For this to work as it should, I need to position #myContainer (the Flex container) 99px from the top although the height of #myHeaderBar is only 90px. I have no idea why that is. Of course, specifying 99px solves the issue and poses no problem (as far as I can see for now), but I’d like to unterstand what’s happening. Any ideas?